Noeud:Preprocessing, Noeud « Next »:, Noeud « Previous »:Preparation, Noeud « Up »:Pulling it Together



Preprocessing

Let's start with preprocessing. Locate the file main.c in the m4/src directory. Send it to the preprocessor using the command

gcc -E main.c -I../m4/ -I. -I..

which will display the result straight to screen. I've included the -I options because main.c includes a number of files in different directories. Since this command will send the output straight to the screen, to be able to have a look at the output, I sent it to a temporary file (temp.i) using file redirection:

gcc -E main.c -I../m4/ -I. -I.. > temp.i

Check out the file sizes now you've preprocessed the file. There is a big difference; mine showed the following sizes (the sizes will differ, possibly radically, depending on which build version you use):

     $ ls -l main.c temp.i
     -rw-r--r--   1 rich     users       13995 Jun  2 01:12 main.c
     -rw-r--r--   1 rich     users       58376 Aug  1 16:53 temp.i
     

Notice that it's almost five times bigger. This is because the #includes have packed in all their information. We can study this by looking at a grep of the preprocessed file, filtering for all lines beginning with a # symbol:

     $ grep '^#' temp.i 
     # 1 "main.c"
     # 1 "/usr/include/getopt.h" 1 3
     # 160 "/usr/include/getopt.h" 3
     # 20 "main.c" 2
     # 1 "/usr/include/signal.h" 1 3
     # 1 "/usr/include/features.h" 1 3
     # 138 "/usr/include/features.h" 3
     # 196 "/usr/include/features.h" 3
     # 1 "/usr/include/sys/cdefs.h" 1 3
     ...
     # 1 "../m4/m4module.h" 1
     # 1 "../m4/error.h" 1
     # 1 "../m4/system.h" 1
     # 100 "../m4/system.h"
     # 143 "../m4/system.h"
     # 27 "../m4/error.h" 2
     # 23 "../m4/m4module.h" 2
     # 1 "../m4/list.h" 1
     # 24 "../m4/m4module.h" 2
     # 1 "../m4/ltdl.h" 1
     # 75 "../m4/ltdl.h"
     # 107 "../m4/ltdl.h"
     # 278 "../m4/ltdl.h"
     # 301 "../m4/ltdl.h"
     # 25 "../m4/m4module.h" 2
     # 1 "/usr/include/obstack.h" 1 3
     # 338 "/usr/include/obstack.h" 3
     ...
     

If you actually look at the contents of temp.i, there will be massive patches of white space; this occurs when the preprocessor is stripping out comments that do not need to be included (and if included would make the file even larger). Recall from The Preprocessor that the above #'s have a special significance; they tell us where and when a file is included, and which files are included from the file being included (and so on). For example, one portion of my temp.i file read as follows (omitting newlines where necessary to save space):

     # 227 "/usr/include/signal.h" 2 3
     ...
     extern int sigprocmask  (int __how,
     			     __const sigset_t *__set, sigset_t *__oset)    ;
     
     extern int sigsuspend  (__const sigset_t *__set)    ;
     
     extern int __sigaction  (int __sig, __const struct sigaction *__act,
     			     struct sigaction *__oact)    ;
     extern int sigaction  (int __sig, __const struct sigaction *__act,
     			   struct sigaction *__oact)    ;
     ...
     # 1 "/usr/include/bits/sigcontext.h" 1 3
     

The fist line, # 227 "/usr/include/signal.h" 2 3 is saying "At line number 227 in /usr/include/signal.h, note the return to this file from some other file, and supress any warnings that may arrise from the following textual substitution". Then, at the end of the above code snippet, /usr/include/bits/sigcontext.h is included, and off the preprocessor goes again.