xref: /openbsd/gnu/usr.bin/gcc/gcc/cppmain.c (revision c87b03e5)
1 /* Preprocess only, using cpplib.
2    Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003
3    Free Software Foundation, Inc.
4    Written by Per Bothner, 1994-95.
5 
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 
20  In other words, you are welcome to use, share and improve this program.
21  You are forbidden to forbid anyone else to use, share and improve
22  what you give them.   Help stamp out software-hoarding!  */
23 
24 #include "config.h"
25 #include "system.h"
26 #include "cpplib.h"
27 #include "cpphash.h"
28 
29 static void setup_callbacks PARAMS ((cpp_reader *));
30 
31 /* General output routines.  */
32 static void scan_translation_unit PARAMS ((cpp_reader *));
33 static void scan_translation_unit_trad PARAMS ((cpp_reader *));
34 static void account_for_newlines PARAMS ((cpp_reader *, const uchar *,
35 					  size_t));
36 static int dump_macro PARAMS ((cpp_reader *, cpp_hashnode *, void *));
37 
38 static void print_line PARAMS ((cpp_reader *, const struct line_map *,
39 				unsigned int, const char *));
40 static void maybe_print_line PARAMS ((cpp_reader *, const struct line_map *,
41 				      unsigned int));
42 
43 /* Callback routines for the parser.   Most of these are active only
44    in specific modes.  */
45 static void cb_line_change PARAMS ((cpp_reader *, const cpp_token *, int));
46 static void cb_define	PARAMS ((cpp_reader *, unsigned int, cpp_hashnode *));
47 static void cb_undef	PARAMS ((cpp_reader *, unsigned int, cpp_hashnode *));
48 static void cb_include	PARAMS ((cpp_reader *, unsigned int,
49 				 const unsigned char *, const cpp_token *));
50 static void cb_ident	  PARAMS ((cpp_reader *, unsigned int,
51 				   const cpp_string *));
52 static void cb_file_change PARAMS ((cpp_reader *, const struct line_map *));
53 static void cb_def_pragma PARAMS ((cpp_reader *, unsigned int));
54 
55 /* Preprocess and output.  */
56 void
cpp_preprocess_file(pfile,in_fname,out_stream)57 cpp_preprocess_file (pfile, in_fname, out_stream)
58      cpp_reader *pfile;
59      const char *in_fname;
60      FILE *out_stream;
61 {
62   /* Initialize the printer structure.  Setting print.line to -1 here
63      is a trick to guarantee that the first token of the file will
64      cause a linemarker to be output by maybe_print_line.  */
65   pfile->print.line = (unsigned int) -1;
66   pfile->print.printed = 0;
67   pfile->print.prev = 0;
68   pfile->print.map = 0;
69   pfile->print.outf = out_stream;
70 
71   setup_callbacks (pfile);
72 
73   if (cpp_read_main_file (pfile, in_fname, NULL))
74     {
75       cpp_options *options = &pfile->opts;
76       cpp_finish_options (pfile);
77 
78       /* A successful cpp_read_main_file guarantees that we can call
79 	 cpp_scan_nooutput or cpp_get_token next.  */
80       if (options->no_output)
81 	{
82 	  /* Scan -included buffers, then the main file.  */
83 	  while (pfile->buffer->prev)
84 	    cpp_scan_nooutput (pfile);
85 	  cpp_scan_nooutput (pfile);
86 	}
87       else if (options->traditional)
88 	scan_translation_unit_trad (pfile);
89       else
90 	scan_translation_unit (pfile);
91 
92       /* -dM command line option.  Should this be in cpp_finish?  */
93       if (options->dump_macros == dump_only)
94 	cpp_forall_identifiers (pfile, dump_macro, NULL);
95     }
96 
97   /* Flush any pending output.  */
98   if (pfile->print.printed)
99     putc ('\n', pfile->print.outf);
100 }
101 
102 /* Set up the callbacks as appropriate.  */
103 static void
setup_callbacks(pfile)104 setup_callbacks (pfile)
105      cpp_reader *pfile;
106 {
107   cpp_options *options = &pfile->opts;
108   cpp_callbacks *cb = cpp_get_callbacks (pfile);
109 
110   if (! options->no_output)
111     {
112       cb->line_change = cb_line_change;
113       /* Don't emit #pragma or #ident directives if we are processing
114 	 assembly language; the assembler may choke on them.  */
115       if (options->lang != CLK_ASM)
116 	{
117 	  cb->ident      = cb_ident;
118 	  cb->def_pragma = cb_def_pragma;
119 	}
120       if (! options->no_line_commands)
121 	cb->file_change = cb_file_change;
122     }
123 
124   if (options->dump_includes)
125     cb->include  = cb_include;
126 
127   if (options->dump_macros == dump_names
128       || options->dump_macros == dump_definitions)
129     {
130       cb->define = cb_define;
131       cb->undef  = cb_undef;
132     }
133 }
134 
135 /* Writes out the preprocessed file, handling spacing and paste
136    avoidance issues.  */
137 static void
scan_translation_unit(pfile)138 scan_translation_unit (pfile)
139      cpp_reader *pfile;
140 {
141   bool avoid_paste = false;
142 
143   pfile->print.source = NULL;
144   for (;;)
145     {
146       const cpp_token *token = cpp_get_token (pfile);
147 
148       if (token->type == CPP_PADDING)
149 	{
150 	  avoid_paste = true;
151 	  if (pfile->print.source == NULL
152 	      || (!(pfile->print.source->flags & PREV_WHITE)
153 		  && token->val.source == NULL))
154 	    pfile->print.source = token->val.source;
155 	  continue;
156 	}
157 
158       if (token->type == CPP_EOF)
159 	break;
160 
161       /* Subtle logic to output a space if and only if necessary.  */
162       if (avoid_paste)
163 	{
164 	  if (pfile->print.source == NULL)
165 	    pfile->print.source = token;
166 	  if (pfile->print.source->flags & PREV_WHITE
167 	      || (pfile->print.prev
168 		  && cpp_avoid_paste (pfile, pfile->print.prev, token))
169 	      || (pfile->print.prev == NULL && token->type == CPP_HASH))
170 	    putc (' ', pfile->print.outf);
171 	}
172       else if (token->flags & PREV_WHITE)
173 	putc (' ', pfile->print.outf);
174 
175       avoid_paste = false;
176       pfile->print.source = NULL;
177       pfile->print.prev = token;
178       cpp_output_token (token, pfile->print.outf);
179 
180       if (token->type == CPP_COMMENT)
181 	account_for_newlines (pfile, token->val.str.text, token->val.str.len);
182     }
183 }
184 
185 /* Adjust pfile->print.line for newlines embedded in output.  */
186 static void
account_for_newlines(pfile,str,len)187 account_for_newlines (pfile, str, len)
188      cpp_reader *pfile;
189      const uchar *str;
190      size_t len;
191 {
192   while (len--)
193     if (*str++ == '\n')
194       pfile->print.line++;
195 }
196 
197 /* Writes out a traditionally preprocessed file.  */
198 static void
scan_translation_unit_trad(pfile)199 scan_translation_unit_trad (pfile)
200      cpp_reader *pfile;
201 {
202   while (_cpp_read_logical_line_trad (pfile))
203     {
204       size_t len = pfile->out.cur - pfile->out.base;
205       maybe_print_line (pfile, pfile->print.map, pfile->out.first_line);
206       fwrite (pfile->out.base, 1, len, pfile->print.outf);
207       pfile->print.printed = 1;
208       if (!CPP_OPTION (pfile, discard_comments))
209 	account_for_newlines (pfile, pfile->out.base, len);
210     }
211 }
212 
213 /* If the token read on logical line LINE needs to be output on a
214    different line to the current one, output the required newlines or
215    a line marker, and return 1.  Otherwise return 0.  */
216 static void
maybe_print_line(pfile,map,line)217 maybe_print_line (pfile, map, line)
218      cpp_reader *pfile;
219      const struct line_map *map;
220      unsigned int line;
221 {
222   /* End the previous line of text.  */
223   if (pfile->print.printed)
224     {
225       putc ('\n', pfile->print.outf);
226       pfile->print.line++;
227       pfile->print.printed = 0;
228     }
229 
230   if (line >= pfile->print.line && line < pfile->print.line + 8)
231     {
232       while (line > pfile->print.line)
233 	{
234 	  putc ('\n', pfile->print.outf);
235 	  pfile->print.line++;
236 	}
237     }
238   else
239     print_line (pfile, map, line, "");
240 }
241 
242 /* Output a line marker for logical line LINE.  Special flags are "1"
243    or "2" indicating entering or leaving a file.  */
244 static void
print_line(pfile,map,line,special_flags)245 print_line (pfile, map, line, special_flags)
246      cpp_reader *pfile;
247      const struct line_map *map;
248      unsigned int line;
249      const char *special_flags;
250 {
251   /* End any previous line of text.  */
252   if (pfile->print.printed)
253     putc ('\n', pfile->print.outf);
254   pfile->print.printed = 0;
255 
256   pfile->print.line = line;
257   if (! CPP_OPTION (pfile, no_line_commands))
258     {
259       size_t to_file_len = strlen (map->to_file);
260       unsigned char *to_file_quoted = alloca (to_file_len * 4 + 1);
261       unsigned char *p;
262 
263       /* cpp_quote_string does not nul-terminate, so we have to do it
264 	 ourselves.  */
265       p = cpp_quote_string (to_file_quoted,
266 			    (unsigned char *)map->to_file, to_file_len);
267       *p = '\0';
268       fprintf (pfile->print.outf, "# %u \"%s\"%s",
269 	       SOURCE_LINE (map, pfile->print.line),
270 	       to_file_quoted, special_flags);
271 
272       if (map->sysp == 2)
273 	fputs (" 3 4", pfile->print.outf);
274       else if (map->sysp == 1)
275 	fputs (" 3", pfile->print.outf);
276 
277       putc ('\n', pfile->print.outf);
278     }
279 }
280 
281 /* Called when a line of output is started.  TOKEN is the first token
282    of the line, and at end of file will be CPP_EOF.  */
283 static void
cb_line_change(pfile,token,parsing_args)284 cb_line_change (pfile, token, parsing_args)
285      cpp_reader *pfile;
286      const cpp_token *token;
287      int parsing_args;
288 {
289   if (token->type == CPP_EOF || parsing_args)
290     return;
291 
292   maybe_print_line (pfile, pfile->print.map, token->line);
293   pfile->print.prev = 0;
294   pfile->print.source = 0;
295 
296   /* Supply enough spaces to put this token in its original column,
297      one space per column greater than 2, since scan_translation_unit
298      will provide a space if PREV_WHITE.  Don't bother trying to
299      reconstruct tabs; we can't get it right in general, and nothing
300      ought to care.  Some things do care; the fault lies with them.  */
301   if (!CPP_OPTION (pfile, traditional))
302     {
303       pfile->print.printed = 1;
304       if (token->col > 2)
305 	{
306 	  unsigned int spaces = token->col - 2;
307 
308 	  while (spaces--)
309 	    putc (' ', pfile->print.outf);
310 	}
311     }
312 }
313 
314 static void
cb_ident(pfile,line,str)315 cb_ident (pfile, line, str)
316      cpp_reader *pfile;
317      unsigned int line;
318      const cpp_string * str;
319 {
320   maybe_print_line (pfile, pfile->print.map, line);
321   fprintf (pfile->print.outf, "#ident \"%s\"\n", str->text);
322   pfile->print.line++;
323 }
324 
325 static void
cb_define(pfile,line,node)326 cb_define (pfile, line, node)
327      cpp_reader *pfile;
328      unsigned int line;
329      cpp_hashnode *node;
330 {
331   maybe_print_line (pfile, pfile->print.map, line);
332   fputs ("#define ", pfile->print.outf);
333 
334   /* -dD command line option.  */
335   if (CPP_OPTION (pfile, dump_macros) == dump_definitions)
336     fputs ((const char *) cpp_macro_definition (pfile, node),
337 	   pfile->print.outf);
338   else
339     fputs ((const char *) NODE_NAME (node), pfile->print.outf);
340 
341   putc ('\n', pfile->print.outf);
342   pfile->print.line++;
343 }
344 
345 static void
cb_undef(pfile,line,node)346 cb_undef (pfile, line, node)
347      cpp_reader *pfile;
348      unsigned int line;
349      cpp_hashnode *node;
350 {
351   maybe_print_line (pfile, pfile->print.map, line);
352   fprintf (pfile->print.outf, "#undef %s\n", NODE_NAME (node));
353   pfile->print.line++;
354 }
355 
356 static void
cb_include(pfile,line,dir,header)357 cb_include (pfile, line, dir, header)
358      cpp_reader *pfile;
359      unsigned int line;
360      const unsigned char *dir;
361      const cpp_token *header;
362 {
363   maybe_print_line (pfile, pfile->print.map, line);
364   fprintf (pfile->print.outf, "#%s %s\n", dir,
365 	   cpp_token_as_text (pfile, header));
366   pfile->print.line++;
367 }
368 
369 /* The file name, line number or system header flags have changed, as
370    described in MAP.  From this point on, the old pfile->print.map might be
371    pointing to freed memory, and so must not be dereferenced.  */
372 
373 static void
cb_file_change(pfile,map)374 cb_file_change (pfile, map)
375      cpp_reader *pfile;
376      const struct line_map *map;
377 {
378   const char *flags = "";
379 
380   /* First time?  */
381   if (pfile->print.map == NULL)
382     {
383       /* Avoid printing foo.i when the main file is foo.c.  */
384       if (!CPP_OPTION (pfile, preprocessed))
385 	print_line (pfile, map, map->from_line, flags);
386     }
387   else
388     {
389       /* Bring current file to correct line when entering a new file.  */
390       if (map->reason == LC_ENTER)
391 	maybe_print_line (pfile, map - 1, map->from_line - 1);
392 
393       if (map->reason == LC_ENTER)
394 	flags = " 1";
395       else if (map->reason == LC_LEAVE)
396 	flags = " 2";
397       print_line (pfile, map, map->from_line, flags);
398     }
399 
400   pfile->print.map = map;
401 }
402 
403 /* Copy a #pragma directive to the preprocessed output.  */
404 static void
cb_def_pragma(pfile,line)405 cb_def_pragma (pfile, line)
406      cpp_reader *pfile;
407      unsigned int line;
408 {
409   maybe_print_line (pfile, pfile->print.map, line);
410   fputs ("#pragma ", pfile->print.outf);
411   cpp_output_line (pfile, pfile->print.outf);
412   pfile->print.line++;
413 }
414 
415 /* Dump out the hash table.  */
416 static int
dump_macro(pfile,node,v)417 dump_macro (pfile, node, v)
418      cpp_reader *pfile;
419      cpp_hashnode *node;
420      void *v ATTRIBUTE_UNUSED;
421 {
422   if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
423     {
424       fputs ("#define ", pfile->print.outf);
425       fputs ((const char *) cpp_macro_definition (pfile, node),
426 	     pfile->print.outf);
427       putc ('\n', pfile->print.outf);
428       pfile->print.line++;
429     }
430 
431   return 1;
432 }
433