support/cpp2/cpphash.h, support/cpp2/cpplib.h, support/cpp2/cpplex.c,
[fw/sdcc] / support / cpp2 / 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 char *last_fname;       /* previous file name.  */
35   const char *syshdr_flags;     /* system header flags, if any.  */
36   unsigned int lineno;          /* line currently being written.  */
37   unsigned char printed;        /* nonzero if something output at lineno.  */
38 };
39
40 int main                PARAMS ((int, char **));
41 static void general_init PARAMS ((const char *));
42 static void do_preprocessing PARAMS ((int, char **));
43 static void setup_callbacks PARAMS ((void));
44
45 /* General output routines.  */
46 static void scan_buffer PARAMS ((cpp_reader *));
47 static void check_multiline_token PARAMS ((cpp_string *));
48 static int printer_init PARAMS ((cpp_reader *));
49 static int dump_macro PARAMS ((cpp_reader *, cpp_hashnode *, void *));
50
51 static void print_line PARAMS ((const char *));
52 static void maybe_print_line PARAMS ((unsigned int));
53
54 /* Callback routines for the parser.   Most of these are active only
55    in specific modes.  */
56 static void cb_define   PARAMS ((cpp_reader *, cpp_hashnode *));
57 static void cb_undef    PARAMS ((cpp_reader *, cpp_hashnode *));
58 static void cb_include  PARAMS ((cpp_reader *, const unsigned char *,
59                                  const cpp_token *));
60 static void cb_ident      PARAMS ((cpp_reader *, const cpp_string *));
61 static void cb_file_change PARAMS ((cpp_reader *, const cpp_file_change *));
62 static void cb_def_pragma PARAMS ((cpp_reader *));
63
64 const char *progname;           /* Needs to be global.  */
65 static cpp_reader *pfile;       /* An opaque handle.  */
66 static cpp_options *options;    /* Options of pfile.  */
67 static struct printer print;
68
69 int
70 main (argc, argv)
71      int argc;
72      char **argv;
73 {
74   general_init (argv[0]);
75
76   /* Contruct a reader with default language GNU C89.  */
77   pfile = cpp_create_reader (NULL, CLK_GNUC89);
78   options = cpp_get_options (pfile);
79   
80   do_preprocessing (argc, argv);
81
82   /* Call to cpp_destroy () omitted for performance reasons.  */
83   if (cpp_errors (pfile))
84     return FATAL_EXIT_CODE;
85
86   return SUCCESS_EXIT_CODE;
87 }
88
89 /* Store the program name, and set the locale.  */
90 static void
91 general_init (argv0)
92      const char *argv0;
93 {
94   progname = argv0 + strlen (argv0);
95
96   while (progname != argv0 && ! IS_DIR_SEPARATOR (progname[-1]))
97     --progname;
98
99   xmalloc_set_program_name (progname);
100
101 /* LC_CTYPE determines the character set used by the terminal so it
102    has to be set to output messages correctly.  */
103
104 #ifdef HAVE_LC_MESSAGES
105   setlocale (LC_CTYPE, "");
106   setlocale (LC_MESSAGES, "");
107 #else
108   setlocale (LC_ALL, "");
109 #endif
110
111   (void) bindtextdomain (PACKAGE, localedir);
112   (void) textdomain (PACKAGE);
113 }
114
115 /* Handle switches, preprocess and output.  */
116 static void
117 do_preprocessing (argc, argv)
118      int argc;
119      char **argv;
120 {
121   int argi = 1;  /* Next argument to handle.  */
122
123   argi += cpp_handle_options (pfile, argc - argi , argv + argi);
124   if (CPP_FATAL_ERRORS (pfile))
125     return;
126
127   if (argi < argc)
128     cpp_fatal (pfile, "Invalid option %s", argv[argi]);
129   else
130     cpp_post_options (pfile);
131
132   if (CPP_FATAL_ERRORS (pfile))
133     return;
134
135   /* If cpp_handle_options saw --help or --version on the command
136      line, it will have set pfile->help_only to indicate this.  Exit
137      successfully.  [The library does not exit itself, because
138      e.g. cc1 needs to print its own --help message at this point.]  */
139   if (options->help_only)
140     return;
141
142   /* Open the output now.  We must do so even if no_output is on,
143      because there may be other output than from the actual
144      preprocessing (e.g. from -dM).  */
145   if (printer_init (pfile))
146     return;
147
148   setup_callbacks ();
149
150   if (cpp_start_read (pfile, options->in_fname))
151     {
152       /* A successful cpp_start_read guarantees that we can call
153          cpp_scan_buffer_nooutput or cpp_get_token next.  */
154       if (options->no_output)
155         cpp_scan_buffer_nooutput (pfile, 1);
156       else
157         scan_buffer (pfile);
158
159       /* -dM command line option.  Should this be in cpp_finish?  */
160       if (options->dump_macros == dump_only)
161         cpp_forall_identifiers (pfile, dump_macro, NULL);
162
163       cpp_finish (pfile);
164     }
165
166   /* Flush any pending output.  */
167   if (print.printed)
168     putc ('\n', print.outf);
169
170   if (ferror (print.outf) || fclose (print.outf))
171     cpp_notice_from_errno (pfile, options->out_fname);
172 }
173
174 /* Set up the callbacks as appropriate.  */
175 static void
176 setup_callbacks ()
177 {
178   cpp_callbacks *cb = cpp_get_callbacks (pfile);
179
180   if (! options->no_output)
181     {
182       cb->ident      = cb_ident;
183       cb->def_pragma = cb_def_pragma;
184       if (! options->no_line_commands)
185         cb->file_change = cb_file_change;
186     }
187
188   if (options->dump_includes)
189     cb->include  = cb_include;
190
191   if (options->dump_macros == dump_names
192       || options->dump_macros == dump_definitions)
193     {
194       cb->define = cb_define;
195       cb->undef  = cb_undef;
196       cb->poison = cb_def_pragma;
197     }
198 }
199
200 /* Writes out the preprocessed file.  Alternates between two tokens,
201    so that we can avoid accidental token pasting.  */
202 static void
203 scan_buffer (pfile)
204      cpp_reader *pfile;
205 {
206   unsigned int index, line;
207   cpp_token tokens[2], *token;
208
209   do
210     {
211       for (index = 0;; index = 1 - index)
212         {
213           token = &tokens[index];
214           cpp_get_token (pfile, token);
215
216           if (token->type == CPP_EOF)
217             break;
218
219           line = cpp_get_line (pfile)->output_line;
220           if (print.lineno != line)
221             {
222               unsigned int col = cpp_get_line (pfile)->col;
223
224               /* Supply enough whitespace to put this token in its original
225                  column.  Don't bother trying to reconstruct tabs; we can't
226                  get it right in general, and nothing ought to care.  (Yes,
227                  some things do care; the fault lies with them.)  */
228               maybe_print_line (line);
229               if (col > 1)
230                 {
231                   if (token->flags & PREV_WHITE)
232                     col--;
233                   while (--col)
234                     putc (' ', print.outf);
235                 }
236             }
237           else if ((token->flags & (PREV_WHITE | AVOID_LPASTE))
238                        == AVOID_LPASTE
239                    && cpp_avoid_paste (pfile, &tokens[1 - index], token))
240             token->flags |= PREV_WHITE;
241           /* Special case '# <directive name>': insert a space between
242              the # and the token.  This will prevent it from being
243              treated as a directive when this code is re-preprocessed.
244              XXX Should do this only at the beginning of a line, but how?  */
245           else if (token->type == CPP_NAME && token->val.node->directive_index
246                    && tokens[1 - index].type == CPP_HASH)
247             token->flags |= PREV_WHITE;
248
249           cpp_output_token (token, print.outf);
250           print.printed = 1;
251           if (token->type == CPP_STRING || token->type == CPP_WSTRING
252             || token->type == CPP_COMMENT
253             /* SDCC _asm specific */
254             || token->type == CPP_ASM)
255             check_multiline_token (&token->val.str);
256         }
257     }
258   while (cpp_pop_buffer (pfile) != 0);
259 }
260
261 /* Adjust print.lineno for newlines embedded in tokens.  */
262 static void
263 check_multiline_token (str)
264      cpp_string *str;
265 {
266   unsigned int i;
267
268   for (i = 0; i < str->len; i++)
269     if (str->text[i] == '\n')
270       print.lineno++;
271 }
272
273 /* Initialize a cpp_printer structure.  As a side effect, open the
274    output file.  */
275 static int
276 printer_init (pfile)
277      cpp_reader *pfile;
278 {
279   print.last_fname = 0;
280   print.lineno = 0;
281   print.printed = 0;
282
283   if (options->out_fname[0] == '\0')
284     print.outf = stdout;
285   else
286     {
287       print.outf = fopen (options->out_fname, "w");
288       if (! print.outf)
289         {
290           cpp_notice_from_errno (pfile, options->out_fname);
291           return 1;
292         }
293     }
294
295   return 0;
296 }
297
298 /* Newline-terminate any output line currently in progress.  If
299    appropriate, write the current line number to the output, or pad
300    with newlines so the output line matches the current line.  */
301 static void
302 maybe_print_line (line)
303      unsigned int line;
304 {
305   /* End the previous line of text (probably only needed until we get
306      multi-line tokens fixed).  */
307   if (print.printed)
308     {
309       putc ('\n', print.outf);
310       print.lineno++;
311       print.printed = 0;
312     }
313
314   if (options->no_line_commands)
315     {
316       print.lineno = line;
317       return;
318     }
319
320   /* print.lineno is zero if this is the first token of the file.  We
321      handle this specially, so that a first line of "# 1 "foo.c" in
322      file foo.i outputs just the foo.c line, and not a foo.i line.  */
323   if (line >= print.lineno && line < print.lineno + 8 && print.lineno)
324     {
325       while (line > print.lineno)
326         {
327           putc ('\n', print.outf);
328           print.lineno++;
329         }
330     }
331   else
332     {
333       print.lineno = line;
334       print_line ("");
335     }
336 }
337
338 static void
339 print_line (special_flags)
340   const char *special_flags;
341 {
342   /* End any previous line of text.  */
343   if (print.printed)
344     putc ('\n', print.outf);
345   print.printed = 0;
346
347   /* SDCC likes #line, not # number. Should be fixed... */
348 #if 0  
349   fprintf (print.outf, "# %u \"%s\"%s%s\n",
350            print.lineno, print.last_fname, special_flags, print.syshdr_flags);
351 #else
352   fprintf (print.outf, "#line %u \"%s\"%s%s\n",
353            print.lineno, print.last_fname, special_flags, print.syshdr_flags);
354 #endif     
355 }
356
357 /* Callbacks.  */
358
359 static void
360 cb_ident (pfile, str)
361      cpp_reader *pfile ATTRIBUTE_UNUSED;
362      const cpp_string * str;
363 {
364   maybe_print_line (cpp_get_line (pfile)->output_line);
365   fprintf (print.outf, "#ident \"%s\"\n", str->text);
366   print.lineno++;
367 }
368
369 static void
370 cb_define (pfile, node)
371      cpp_reader *pfile;
372      cpp_hashnode *node;
373 {
374   maybe_print_line (cpp_get_line (pfile)->output_line);
375   fputs ("#define ", print.outf);
376
377   /* -dD command line option.  */
378   if (options->dump_macros == dump_definitions)
379     fputs ((const char *) cpp_macro_definition (pfile, node), print.outf);
380   else
381     fputs ((const char *) NODE_NAME (node), print.outf);
382
383   putc ('\n', print.outf);
384   print.lineno++;
385 }
386
387 static void
388 cb_undef (pfile, node)
389      cpp_reader *pfile;
390      cpp_hashnode *node;
391 {
392   maybe_print_line (cpp_get_line (pfile)->output_line);
393   fprintf (print.outf, "#undef %s\n", NODE_NAME (node));
394   print.lineno++;
395 }
396
397 static void
398 cb_include (pfile, dir, header)
399      cpp_reader *pfile ATTRIBUTE_UNUSED;
400      const unsigned char *dir;
401      const cpp_token *header;
402 {
403   maybe_print_line (cpp_get_line (pfile)->output_line);
404   fprintf (print.outf, "#%s %s\n", dir, cpp_token_as_text (pfile, header));
405   print.lineno++;
406 }
407
408 static void
409 cb_file_change (pfile, fc)
410      cpp_reader *pfile ATTRIBUTE_UNUSED;
411      const cpp_file_change *fc;
412 {
413   /* Bring current file to correct line (except first file).  */
414   if (fc->reason == FC_ENTER && fc->from.filename)
415     maybe_print_line (fc->from.lineno);
416
417   print.last_fname = fc->to.filename;
418   if (fc->externc)
419     print.syshdr_flags = " 3 4";
420   else if (fc->sysp)
421     print.syshdr_flags = " 3";
422   else
423     print.syshdr_flags = "";
424
425   if (print.lineno)
426     {
427       const char *flags = "";
428
429       print.lineno = fc->to.lineno;
430       if (fc->reason == FC_ENTER)
431         flags = " 1";
432       else if (fc->reason == FC_LEAVE)
433         flags = " 2";
434
435       if (! options->no_line_commands)
436         print_line (flags);
437     }
438 }
439
440 static void
441 cb_def_pragma (pfile)
442      cpp_reader *pfile;
443 {
444   maybe_print_line (cpp_get_line (pfile)->output_line);
445   fputs ("#pragma ", print.outf);
446   cpp_output_line (pfile, print.outf);
447   print.lineno++;
448 }
449
450 /* Dump out the hash table.  */
451 static int
452 dump_macro (pfile, node, v)
453      cpp_reader *pfile;
454      cpp_hashnode *node;
455      void *v ATTRIBUTE_UNUSED;
456 {
457   if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN))
458     {
459       fputs ("#define ", print.outf);
460       fputs ((const char *) cpp_macro_definition (pfile, node), print.outf);
461       putc ('\n', print.outf);
462       print.lineno++;
463     }
464
465   return 1;
466 }