Noeud:Preprocessing, Noeud « Next »:Compilation, Noeud « Previous »:Preparation, Noeud « Up »:Pulling it Together
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
#include
s 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.