OSDN Git Service

* cppmain.c (struct printer): New member source.
[pf3gnuchains/gcc-fork.git] / gcc / cppmain.c
1 /* CPP main program, using CPP Library.
2    Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001
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 "intl.h"
28
29 /* Encapsulates state used to convert the stream of tokens coming from
30    cpp_get_token back into a text file.  */
31 struct printer
32 {
33   FILE *outf;                   /* Stream to write to.  */
34   const struct line_map *map;   /* Logical to physical line mappings.  */
35   const cpp_token *prev;        /* Previous token.  */
36   const cpp_token *source;      /* Source token for spacing.  */
37   unsigned int line;            /* Line currently being written.  */
38   unsigned char printed;        /* Nonzero if something output at line.  */
39 };
40
41 int main                PARAMS ((int, char **));
42 static void general_init PARAMS ((const char *));
43 static void do_preprocessing PARAMS ((int, char **));
44 static void setup_callbacks PARAMS ((void));
45
46 /* General output routines.  */
47 static void scan_translation_unit PARAMS ((cpp_reader *));
48 static void check_multiline_token PARAMS ((const cpp_string *));
49 static int dump_macro PARAMS ((cpp_reader *, cpp_hashnode *, void *));
50
51 static void print_line PARAMS ((const struct line_map *, unsigned int,
52                                 const char *));
53 static void maybe_print_line PARAMS ((const struct line_map *, unsigned int));
54
55 /* Callback routines for the parser.   Most of these are active only
56    in specific modes.  */
57 static void cb_line_change PARAMS ((cpp_reader *, const cpp_token *, int));
58 static void cb_define   PARAMS ((cpp_reader *, unsigned int, cpp_hashnode *));
59 static void cb_undef    PARAMS ((cpp_reader *, unsigned int, cpp_hashnode *));
60 static void cb_include  PARAMS ((cpp_reader *, unsigned int,
61                                  const unsigned char *, const cpp_token *));
62 static void cb_ident      PARAMS ((cpp_reader *, unsigned int,
63                                    const cpp_string *));
64 static void cb_file_change PARAMS ((cpp_reader *, const struct line_map *));
65 static void cb_def_pragma PARAMS ((cpp_reader *, unsigned int));
66
67 const char *progname;           /* Needs to be global.  */
68 static cpp_reader *pfile;       /* An opaque handle.  */
69 static cpp_options *options;    /* Options of pfile.  */
70 static struct printer print;
71
72 int
73 main (argc, argv)
74      int argc;
75      char **argv;
76 {
77   general_init (argv[0]);
78
79   /* Contruct a reader with default language GNU C89.  */
80   pfile = cpp_create_reader (NULL, CLK_GNUC89);
81   options = cpp_get_options (pfile);
82   
83   do_preprocessing (argc, argv);
84
85   if (cpp_destroy (pfile))
86     return FATAL_EXIT_CODE;
87
88   return SUCCESS_EXIT_CODE;
89 }
90
91 /* Store the program name, and set the locale.  */
92 static void
93 general_init (argv0)
94      const char *argv0;
95 {
96   progname = argv0 + strlen (argv0);
97
98   while (progname != argv0 && ! IS_DIR_SEPARATOR (progname[-1]))
99     --progname;
100
101   xmalloc_set_program_name (progname);
102
103 /* LC_CTYPE determines the character set used by the terminal so it
104    has to be set to output messages correctly.  */
105
106 #ifdef HAVE_LC_MESSAGES
107   setlocale (LC_CTYPE, "");
108   setlocale (LC_MESSAGES, "");
109 #else
110   setlocale (LC_ALL, "");
111 #endif
112
113   (void) bindtextdomain (PACKAGE, localedir);
114   (void) textdomain (PACKAGE);
115 }
116
117 /* Handle switches, preprocess and output.  */
118 static void
119 do_preprocessing (argc, argv)
120      int argc;
121      char **argv;
122 {
123   int argi = 1;  /* Next argument to handle.  */
124
125   argi += cpp_handle_options (pfile, argc - argi , argv + argi);
126   if (CPP_FATAL_ERRORS (pfile))
127     return;
128
129   if (argi < argc)
130     cpp_fatal (pfile, "Invalid option %s", argv[argi]);
131   else
132     cpp_post_options (pfile);
133
134   if (CPP_FATAL_ERRORS (pfile))
135     return;
136
137   /* If cpp_handle_options saw --help or --version on the command
138      line, it will have set pfile->help_only to indicate this.  Exit
139      successfully.  [The library does not exit itself, because
140      e.g. cc1 needs to print its own --help message at this point.]  */
141   if (options->help_only)
142     return;
143
144   /* Initialize the printer structure.  Setting print.line to -1 here
145      is a trick to guarantee that the first token of the file will
146      cause a linemarker to be output by maybe_print_line.  */
147   print.line = (unsigned int) -1;
148   print.printed = 0;
149   print.prev = 0;
150   print.map = 0;
151   
152   /* Open the output now.  We must do so even if no_output is on,
153      because there may be other output than from the actual
154      preprocessing (e.g. from -dM).  */
155   if (options->out_fname[0] == '\0')
156     print.outf = stdout;
157   else
158     {
159       print.outf = fopen (options->out_fname, "w");
160       if (print.outf == NULL)
161         {
162           cpp_notice_from_errno (pfile, options->out_fname);
163           return;
164         }
165     }
166
167   setup_callbacks ();
168
169   if (cpp_start_read (pfile, options->in_fname))
170     {
171       /* A successful cpp_start_read guarantees that we can call
172          cpp_scan_nooutput or cpp_get_token next.  */
173       if (options->no_output)
174         cpp_scan_nooutput (pfile);
175       else
176         scan_translation_unit (pfile);
177
178       /* -dM command line option.  Should this be in cpp_finish?  */
179       if (options->dump_macros == dump_only)
180         cpp_forall_identifiers (pfile, dump_macro, NULL);
181
182       cpp_finish (pfile);
183     }
184
185   /* Flush any pending output.  */
186   if (print.printed)
187     putc ('\n', print.outf);
188
189   if (ferror (print.outf) || fclose (print.outf))
190     cpp_notice_from_errno (pfile, options->out_fname);
191 }
192
193 /* Set up the callbacks as appropriate.  */
194 static void
195 setup_callbacks ()
196 {
197   cpp_callbacks *cb = cpp_get_callbacks (pfile);
198
199   if (! options->no_output)
200     {
201       cb->line_change = cb_line_change;
202       cb->ident      = cb_ident;
203       cb->def_pragma = cb_def_pragma;
204       if (! options->no_line_commands)
205         cb->file_change = cb_file_change;
206     }
207
208   if (options->dump_includes)
209     cb->include  = cb_include;
210
211   if (options->dump_macros == dump_names
212       || options->dump_macros == dump_definitions)
213     {
214       cb->define = cb_define;
215       cb->undef  = cb_undef;
216     }
217 }
218
219 /* Writes out the preprocessed file, handling spacing and paste
220    avoidance issues.  */
221 static void
222 scan_translation_unit (pfile)
223      cpp_reader *pfile;
224 {
225   bool avoid_paste = false;
226
227   print.source = NULL;
228   for (;;)
229     {
230       const cpp_token *token = cpp_get_token (pfile);
231
232       if (token->type == CPP_PADDING)
233         {
234           avoid_paste = true;
235           if (print.source == NULL
236               || (!(print.source->flags & PREV_WHITE)
237                   && token->val.source == NULL))
238             print.source = token->val.source;
239           continue;
240         }
241
242       if (token->type == CPP_EOF)
243         break;
244
245       /* Subtle logic to output a space if and only if necessary.  */
246       if (avoid_paste)
247         {
248           if (print.source == NULL)
249             print.source = token;
250           if (print.source->flags & PREV_WHITE
251               || (print.prev && cpp_avoid_paste (pfile, print.prev, token))
252               || (print.prev == NULL && token->type == CPP_HASH))
253             putc (' ', print.outf);
254         }
255       else if (token->flags & PREV_WHITE)
256         putc (' ', print.outf);
257
258       avoid_paste = false;
259       print.source = NULL;
260       print.prev = token;
261       cpp_output_token (token, print.outf);
262
263       if (token->type == CPP_STRING || token->type == CPP_WSTRING
264           || token->type == CPP_COMMENT)
265         check_multiline_token (&token->val.str);
266     }
267 }
268
269 /* Adjust print.line for newlines embedded in tokens.  */
270 static void
271 check_multiline_token (str)
272      const cpp_string *str;
273 {
274   unsigned int i;
275
276   for (i = 0; i < str->len; i++)
277     if (str->text[i] == '\n')
278       print.line++;
279 }
280
281 /* If the token read on logical line LINE needs to be output on a
282    different line to the current one, output the required newlines or
283    a line marker, and return 1.  Otherwise return 0.  */
284
285 static void
286 maybe_print_line (map, line)
287      const struct line_map *map;
288      unsigned int line;
289 {
290   /* End the previous line of text.  */
291   if (print.printed)
292     {
293       putc ('\n', print.outf);
294       print.line++;
295       print.printed = 0;
296     }
297
298   if (line >= print.line && line < print.line + 8)
299     {
300       while (line > print.line)
301         {
302           putc ('\n', print.outf);
303           print.line++;
304         }
305     }
306   else
307     print_line (map, line, "");
308 }
309
310 /* Output a line marker for logical line LINE.  Special flags are "1"
311    or "2" indicating entering or leaving a file.  */
312 static void
313 print_line (map, line, special_flags)
314      const struct line_map *map;
315      unsigned int line;
316      const char *special_flags;
317 {
318   /* End any previous line of text.  */
319   if (print.printed)
320     putc ('\n', print.outf);
321   print.printed = 0;
322
323   print.line = line;
324   if (! options->no_line_commands)
325     {
326       fprintf (print.outf, "# %u \"%s\"%s",
327                SOURCE_LINE (map, print.line), map->to_file, special_flags);
328
329       if (map->sysp == 2)
330         fputs (" 3 4", print.outf);
331       else if (map->sysp == 1)
332         fputs (" 3", print.outf);
333
334       putc ('\n', print.outf);
335     }
336 }
337
338 /* Called when a line of output is started.  TOKEN is the first token
339    of the line, and may be CPP_EOF.  */
340
341 static void
342 cb_line_change (pfile, token, parsing_args)
343      cpp_reader *pfile ATTRIBUTE_UNUSED;
344      const cpp_token *token;
345      int parsing_args;
346 {
347   if (token->type == CPP_EOF || parsing_args)
348     return;
349
350   maybe_print_line (print.map, token->line);
351   print.printed = 1;
352   print.prev = 0;
353   print.source = 0;
354
355   /* Supply enough spaces to put this token in its original column,
356      one space per column greater than 2, since scan_translation_unit
357      will provide a space if PREV_WHITE.  Don't bother trying to
358      reconstruct tabs; we can't get it right in general, and nothing
359      ought to care.  Some things do care; the fault lies with them.  */
360   if (token->col > 2)
361     {
362       unsigned int spaces = token->col - 2;
363
364       while (spaces--)
365         putc (' ', print.outf);
366     }
367 }
368
369 static void
370 cb_ident (pfile, line, str)
371      cpp_reader *pfile ATTRIBUTE_UNUSED;
372      unsigned int line;
373      const cpp_string * str;
374 {
375   maybe_print_line (print.map, line);
376   fprintf (print.outf, "#ident \"%s\"\n", str->text);
377   print.line++;
378 }
379
380 static void
381 cb_define (pfile, line, node)
382      cpp_reader *pfile;
383      unsigned int line;
384      cpp_hashnode *node;
385 {
386   maybe_print_line (print.map, line);
387   fputs ("#define ", print.outf);
388
389   /* -dD command line option.  */
390   if (options->dump_macros == dump_definitions)
391     fputs ((const char *) cpp_macro_definition (pfile, node), print.outf);
392   else
393     fputs ((const char *) NODE_NAME (node), print.outf);
394
395   putc ('\n', print.outf);
396   print.line++;
397 }
398
399 static void
400 cb_undef (pfile, line, node)
401      cpp_reader *pfile ATTRIBUTE_UNUSED;
402      unsigned int line;
403      cpp_hashnode *node;
404 {
405   maybe_print_line (print.map, line);
406   fprintf (print.outf, "#undef %s\n", NODE_NAME (node));
407   print.line++;
408 }
409
410 static void
411 cb_include (pfile, line, dir, header)
412      cpp_reader *pfile;
413      unsigned int line;
414      const unsigned char *dir;
415      const cpp_token *header;
416 {
417   maybe_print_line (print.map, line);
418   fprintf (print.outf, "#%s %s\n", dir, cpp_token_as_text (pfile, header));
419   print.line++;
420 }
421
422 /* The file name, line number or system header flags have changed, as
423    described in MAP.  From this point on, the old print.map might be
424    pointing to freed memory, and so must not be dereferenced.  */
425
426 static void
427 cb_file_change (pfile, map)
428      cpp_reader *pfile ATTRIBUTE_UNUSED;
429      const struct line_map *map;
430 {
431   const char *flags = "";
432
433   /* First time?  */
434   if (print.map == NULL)
435     {
436       /* Avoid printing foo.i when the main file is foo.c.  */
437       if (!options->preprocessed)
438         print_line (map, map->from_line, flags);
439     }
440   else
441     {
442       /* Bring current file to correct line when entering a new file.  */
443       if (map->reason == LC_ENTER)
444         maybe_print_line (map - 1, map->from_line - 1);
445
446       if (map->reason == LC_ENTER)
447         flags = " 1";
448       else if (map->reason == LC_LEAVE)
449         flags = " 2";
450       print_line (map, map->from_line, flags);
451     }
452
453   print.map = map;
454 }
455
456 /* Copy a #pragma directive to the preprocessed output.  */
457 static void
458 cb_def_pragma (pfile, line)
459      cpp_reader *pfile;
460      unsigned int line;
461 {
462   maybe_print_line (print.map, line);
463   fputs ("#pragma ", print.outf);
464   cpp_output_line (pfile, print.outf);
465   print.line++;
466 }
467
468 /* Dump out the hash table.  */
469 static int
470 dump_macro (pfile, node, v)
471      cpp_reader *pfile;
472      cpp_hashnode *node;
473      void *v ATTRIBUTE_UNUSED;
474 {
475   if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
476     {
477       fputs ("#define ", print.outf);
478       fputs ((const char *) cpp_macro_definition (pfile, node), print.outf);
479       putc ('\n', print.outf);
480       print.line++;
481     }
482
483   return 1;
484 }