Display preprocessor output just processing the conditional compilation directives - c-preprocessor

I've got a c program that has grown organically over a long period of time to support multiple different targets using #if #else #elif and #endif directives.
How would I use the gcc preprocessor (or the m4 preprocessor) to display to code that would be compiled as a result of a particular identifier being defined without displaying any of the conditional compilation directives or expanding any include files or macros.
gcc -E doesn't work as it expands both macros and include files and I'd prefer not to do this by hand!
For example on a linux system where the 'linux' identifier is defined then parsing the following code:
#include <stdio.h>
#if defined(linux)
#include <unistd.h>
#include <sys/types.h>
#elif defined(WIN32)
#include <windows.h>
#elif defined(VMS)
#include <timeb.h>
#include <lib$routines.h>
#else
#include <sys/types.h>
#include <sys/timeb.h>
#endif
#include "debug.h"
int i_wait(long l_delay) { /* wait for milliseconds */
#if defined(linux) /* Use usleep() function */
debug(fprintf(stderr, "Pausing using usleep() for %ld ms.\n", l_delay));
return (usleep(l_delay * 1000));
#elif defined(WIN32) /* Use usleep() function */
debug(fprintf(stderr, "Pausing using sleep() for %d ms.\n", l_delay));
Sleep(l_delay);
return (0);
#elif defined(VMS) /* Use VMS LIB$WAIT */
float f_seconds;
debug(fprintf(stderr, "Pausing using LIB$WAIT for %ld ms.\n", l_delay));
f_seconds = l_delay / 1000.0;
return (lib$wait(&f_seconds));
#else /* Use a portable but very inefficent busy loop */
struct timeb o_start, o_end;
debug(fprintf(stderr, "Pausing for %ld ms.\n", l_delay));
ftime(&o_start);
ftime(&o_end);
while ((1000 * (o_end.time - o_start.time) + o_end.millitm - o_start.millitm) < l_delay) {
ftime(&o_end);
}
return(0);
#endif
}
Should produce the output below:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include "debug.h"
int i_wait(long l_delay) { /* wait for milliseconds */
debug(fprintf(stderr, "Pausing using usleep() for %ld ms.\n", l_delay));
return (usleep(l_delay * 1000));
}

Related

LwIP into NUC970_NonOS_BSP-master incorrect works LWIP_DEBUG option

I'm trying build LwIP 1.4.1 (this version uses vendor for example) and I want to build with diagnostic messages for UDP.
Problem: In debug.h condition #ifdef LWIP_DEBUG builds as undefined, but if #define LWIP_DEBUG exist warning about redefine it.
Updated: it repeatable in four files.
udp.c
#include "lwip/opt.h"
err_t
udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
{
// My comment
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_bind(ipaddr = "));
return ERR_OK;
}
opt.h
#ifndef __LWIP_OPT_H__
#define __LWIP_OPT_H__
#include "lwipopts.h"
#include "lwip/debug.h"
#endif /* __LWIP_OPT_H__ */
lwipopts.h
#ifndef __LWIPOPTS_H__
#define __LWIPOPTS_H__
#include "lwipopts.h"
#include "lwip/debug.h"
#define LWIP_DEBUG 1
#define UDP_DEBUG LWIP_DBG_ON
#endif /* __LWIPOPTS_H__ */
and debug.h
#ifndef __LWIP_DEBUG_H__
#define __LWIP_DEBUG_H__
#include "lwip/opt.h"
//#define LWIP_DEBUG exist
#ifdef LWIP_DEBUG
#define LWIP_DEBUGF(debug, message) do { if ((debug) & 0x80U) { \
LWIP_PLATFORM_DIAG(message); \
} } while(0)
#else /* LWIP_DEBUG */
#define LWIP_DEBUGF(debug, message)
#endif /* LWIP_DEBUG */
#endif /* __LWIP_DEBUG_H__ */
If you try on purpose to define it in multiple headers, that may be included at the same time from a .c file, each header needs to do something like:
#ifndef LWIP_DEBUG
#define LWIP_DEBUG 1
#endif
Or alternatively:
#undef LWIP_DEBUG
#define LWIP_DEBUG 1
I have found problem: remove any includes from lwipopts.h.
It reproduces in two files, udp.c and modifed lwipopts.h
#ifndef __LWIPOPTS_H__
#define __LWIPOPTS_H__
#include "lwipopts.h"
//#include "lwip/debug.h"
/* REDUCED BODY BEGIN */
//#define LWIP_DEBUG exist
#ifdef LWIP_DEBUG
#define LWIP_DEBUGF(debug, message) do { printf("%d, %s\n", debug, message); } while(0)
#else /* LWIP_DEBUG */
#define LWIP_DEBUGF(debug, message)
#endif /* LWIP_DEBUG */
/* REDUCED BODY END */
#define LWIP_DEBUG 1
#define UDP_DEBUG LWIP_DBG_ON
#endif /* __LWIPOPTS_H__ */
Definition LWIP_DEBUG after #ifdef LWIP_DEBUG condition.
It is because users lwipopts.h contain
#include "lwipopts.h"
#include "lwip/debug.h"
lwipopts.h should not contain any include directive!
Little bit explain:
How it should be
#include "lwip/opt.h"
#include "lwipopts.h"
// BODY lwipopts.h
#include "lwip/debug.h"
//#include "opt.h" /* guarded */
// BODY debug.h
How it is in git Nuvoton (reduced):
#include "lwip/opt.h" /* udp.c */
#include "lwipopts.h"
//#include "lwipopts.h" /* guarded */
#include "lwip/debug.h"
//#include "lwip/opt.h" /* guarded */
// BODY debug.h
// BODY lwipopts.h
//#include "lwip/debug.h" /* guarded */
//#include "lwip/opt.h" /* guarded */
So, bodies of debug.h and lwipopts.h swaped.

How to get PID_MAX macro?

I would like to get the value of the PID_MAX macro present in the file /sys/sys/proc.h.
My current code (main.c) :
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> /* type pid_t */
#include <sys/proc.h> /* macro PID_MAX */
#include <sys/unistd.h> /* function getpid, getppid */
/*
gcc -Wall -Wextra main.c -o main
./main
*/
int main ()
{
pid_t pidmax = PID_MAX;
printf ( "Value = %d\n", pidmax );
return 0;
}
Return the following error :
error: 'PID_MAX' undeclared (first use in this function); did you mean 'UID_MAX'?
How is it possible?
Another method to recover the PID_MAX?
There is no platform-independent method for retrieving the maximum pid value.
Under Linux, for example, you can determine the value through the /proc/sys interface
$ sysctl kernel/pid_max
32768
Under FreeBSD, the value is 99999. If you look closely in sys/proc.h, you will notice that the macro PID_MAX is guarded by
#ifdef _KERNEL
...
#define PID_MAX 99999
...
#endif
This is, why you cannot (and should not) use it in userspace programs.
The PID_MAX macro defines the hard limit of PID values by BSD kernels (such as kFreeBSD); it shouldn't be used by user space programs because the actual maximum PID value could be further lowered in the runtime, controlled by kern.pid_max sysctl.
To get such runtime limitation in an user space program, use sysctlbyname(3); for example:
#include <sys/types.h>
#include <sys/sysctl.h>
#include <stdio.h>
int main() {
int pid_max;
size_t len = sizeof pid_max;
if(sysctlbyname("kern.pid_max", &pid_max, &len, NULL, 0) < 0) {
perror("sysctlbyname: kern.pid_max");
return 1;
}
printf("kern.pid_max=%d\n", pid_max);
return 0;
}

Discover available clock types at compile time

[Ubuntu 14.04, 3.16.0-34-generic Kernel, GCC 4.8.4, Clang 3.5.0]
I'm writing some elapsed time performance routines for an application I have, and I would like to do it in a cross-platform manner.
I would like to write it in such a way that the right clock type is selected during compile, rather than run-time (which I can do by testing for failures and using fallbacks).
The clock_getres(2) man page states:
On POSIX systems on which these functions are available, the symbol _POSIX_TIMERS is defined in <unistd.h> to a value greater than 0. The symbols _POSIX_MONOTONIC_CLOCK, _POSIX_CPUTIME, _POSIX_THREAD_CPUTIME
indicate that CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID are available. (See also sysconf(3).)
I have included in my code , , and but my conditional compile statements don't recognise the symbol _POSIX_MONOTONIC_CLOCK. It always prints the 'gettimeofday' message. I've tried GCC and Clang but get the same result.
My code below is incomplete (and incorrect) and I would appreciate some assistance on how to do this right.
#include <unistd.h>
#include <features.h>
#include <stdio.h> // printf (otherwise forward declaration warning)
#include <stdlib.h> // NULL
#include <sys/time.h>
long long get_utime(void)
{
struct timeval tv;
if (gettimeofday(&tv, NULL) == -1) return -1LL;
long long t = (long long) tv.tv_usec +
(long long) tv.tv_sec * 1000000LL;
return t;
}
int main() {
union time{
struct timespec tSpec;
long long tLL;
} myT;
#ifdef CLOCK_MONOTONIC_RAW
clock_gettime(CLOCK_MONOTONIC_RAW, &myT.tSpec);
printf("CLOCK_MONOTONIC_RAW\n");
#elif _POSIX_MONOTONIC_CLOCK
clock_gettime(CLOCK_MONOTONIC, &myT.tSpec);
printf("CLOCK_MONOTONIC\n");
#else
myT.tLL = get_utime();
printf("gettimeofday\n");
#endif // CLOCK_MONOTONIC_RAW
return 0;
}
I'm not using any configure or auto-configure software.
Also, a comment about the relative speeds of CLOCK_MONOTONIC & CLOCK_MONOTONIC_RAW would be nice. I understand the difference and their limitations.
You aren’t declaring the headers and feature-test macros that the man page says you need. This works:
#define _POSIX_C_SOURCE 200809L // <- This was missing.
#define _XOPEN_SOURCE 700 // <- This is optional.
#include <unistd.h>
#include <stdio.h> // printf (otherwise forward declaration warning)
#include <stdlib.h> // NULL
#include <sys/time.h>
#include <time.h> // <- This was missing.
long long get_utime(void)
{
struct timeval tv;
if (gettimeofday(&tv, NULL) == -1) return -1LL;
long long t = (long long) tv.tv_usec +
(long long) tv.tv_sec * 1000000LL;
return t;
}
int main() {
union time{
struct timespec tSpec;
long long tLL;
} myT;
#ifdef CLOCK_MONOTONIC_RAW
clock_gettime(CLOCK_MONOTONIC_RAW, &myT.tSpec);
printf("CLOCK_MONOTONIC_RAW\n");
#elif _POSIX_MONOTONIC_CLOCK
clock_gettime(CLOCK_MONOTONIC, &myT.tSpec);
printf("CLOCK_MONOTONIC\n");
#else
myT.tLL = get_utime();
printf("gettimeofday\n");
#endif // CLOCK_MONOTONIC_RAW
return 0;
}

How to split this into header and source files?

I have some C code I'd like to split into a header file and a source file:
#ifndef BENCHMARK_H
#define BENCHMARK_H
#ifdef WIN32
#include <windows.h>
double get_time()
{
LARGE_INTEGER t, f;
QueryPerformanceCounter(&t);
QueryPerformanceFrequency(&f);
return (double)t.QuadPart/(double)f.QuadPart;
}
#else
#include <sys/time.h>
#include <sys/resource.h>
double get_time()
{
struct timeval t;
struct timezone tzp;
gettimeofday(&t, &tzp);
return t.tv_sec + t.tv_usec*1e-6;
}
#endif
#endif
What would be the proper format of the resulting benchmark.h and benchmark.c?
I know the header file should contain function declarations, while the source file should be where the actual function definitions reside. Would this following code be correct? Namely, should the #ifdef WIN32 directive be in both files as I have it below? Or should it all be in the .c file?
benchmark.h
#ifndef BENCHMARK_H
#define BENCHMARK_H
#ifdef WIN32
#include <windows.h>
#else
#include <sys/time.h>
#include <sys/resource.h>
#endif
double get_time();
#endif
benchmark.c
#ifdef WIN32
double get_time()
{
LARGE_INTEGER t, f;
QueryPerformanceCounter(&t);
QueryPerformanceFrequency(&f);
return (double)t.QuadPart/(double)f.QuadPart;
}
#else
double get_time()
{
struct timeval t;
struct timezone tzp;
gettimeofday(&t, &tzp);
return t.tv_sec + t.tv_usec*1e-6;
}
#endif
Together, a header file and a c file form a "code module" (or if you will: an ADT, a class etc).
The header file is always to be regarded as the user interface of your code, where the "user" is the programmer who is going to use your module. It shall never contain any code or variable definitions, period.
While the c file contains the actual implementation, which is of no interest to the user, and should not be of any concern to them. The c file should use private encapsulation and everything that the user need not know should be in that file.
The above is how you design C programs, or any program in any language. This is not subjective, it is not opinion-based, it is the only way. If you are doing your program design differently, you are doing it wrong.
As for your specific program, it should be designed in the following way:
benchmark.h
#ifndef BENCHMARK_H
#define BENCHMARK_H
double get_time (void);
/* documentation about how this function is used should be put here */
#endif
benchmark.c
#include "benchmark.h"
/*** Include files ***/
#ifdef WIN32
#include <windows.h>
#else
#include <sys/time.h>
#include <sys/resource.h>
#endif
/*** Other stuff, for example constants, typedefs, static file scope variables ***/
/*** function definitions ***/
#ifdef WIN32
double get_time (void)
{
LARGE_INTEGER t, f;
QueryPerformanceCounter(&t);
QueryPerformanceFrequency(&f);
return (double)t.QuadPart/(double)f.QuadPart;
}
#else
double get_time (void)
{
struct timeval t;
struct timezone tzp;
gettimeofday(&t, &tzp);
return t.tv_sec + t.tv_usec*1e-6;
}
#endif
Note that double get_time() means "function that accepts any parameter" in C. That is poor style, use void instead. C and C++ are different in this regard. In C++, func() and func(void) mean the same thing.
I would simplify it to this, the only thing needed in the header file is the function prototype.
benchmark.h
double get_time();
benchmark.c
#ifdef WIN32
#include <windows.h>
#include "benchmark.h"
double get_time()
{
LARGE_INTEGER t, f;
QueryPerformanceCounter(&t);
QueryPerformanceFrequency(&f);
return (double)t.QuadPart/(double)f.QuadPart;
}
#else
#include <sys/time.h>
#include <sys/resource.h>
#include "benchmark.h"
double get_time()
{
struct timeval t;
struct timezone tzp;
gettimeofday(&t, &tzp);
return t.tv_sec + t.tv_usec*1e-6;
}
#endif

Getting problem with timing in C in visual studio 2010

I have a function for getting system time. The function is defined as follows.
int getSystemTime(struct timeval tv, void * tz);{
DWORD milliseconds;
milliseconds = timeGetTime();
tv->tv_sec = milliseconds / 1000;
tv->tv_usec = (milliseconds % 1000) * 1000;
return 0;
}
Precisely following are the problems:
1.error: identifier DWORD is undentified .
2.error: identifier timeGetTime() is undefined.
3.error: identifier suseconds_t is undefined.
I tried to include windef.h where DWORD is defined. But the problem is, I got the error like:
1. error: identifier PCONTEXT is undefined.
The header file for time included is time.h. Here the timeval defined is:
#ifndef _WINSOCK_H
struct timeval {
time_t tv_sec;
suseconds_t tv_usec;
};
Could you please tell me what shall I do to make this function run in windows environment?
[EDIT]
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_WINDOWS_H
#include <windows.h>
#endif
#ifdef HAVE_MMSYSTEM_H
#include <mmsystem.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
You need to include windows.h at the top of your C file.

Resources