* doc/sdccman.lyx: documented #pragma sdcc_hash
[fw/sdcc] / support / cpp2 / sdcpp.c
1 /*-------------------------------------------------------------------------
2     sdcppmain.c - sdcpp: SDCC preprocessor main file, using cpplib.
3
4     Written by Borut Razem, 2006.
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
25 #include "config.h"
26 #include "system.h"
27 #include "cpplib.h"
28 #include "internal.h"
29 #include "version.h"
30 #include "mkdeps.h"
31 #include "opts.h"
32 #include "intl.h"
33 #include "c-pretty-print.h"
34 #include "diagnostic.h"
35
36 #define CPP_FATAL_LIMIT 1000
37 /* True if we have seen a "fatal" error.  */
38 #define CPP_FATAL_ERRORS(PFILE) (cpp_errors (PFILE) >= CPP_FATAL_LIMIT)
39
40 const char *progname;           /* Needs to be global.  */
41
42 /* From laghooks-def.h */
43 /* The whole thing.  The structure is defined in langhooks.h.  */
44 #define LANG_HOOKS_INITIALIZER { \
45   LANG_HOOKS_INIT_OPTIONS, \
46   LANG_HOOKS_INITIALIZE_DIAGNOSTICS, \
47   LANG_HOOKS_HANDLE_OPTION, \
48   LANG_HOOKS_MISSING_ARGUMENT, \
49   LANG_HOOKS_POST_OPTIONS, \
50   LANG_HOOKS_INIT, \
51   LANG_HOOKS_FINISH, \
52   LANG_HOOKS_PRINT_ERROR_FUNCTION, \
53 }
54
55 /* From c-lang.c */
56 #define LANG_HOOKS_INIT_OPTIONS sdcpp_init_options
57 #define LANG_HOOKS_INITIALIZE_DIAGNOSTICS sdcpp_initialize_diagnostics
58 #define LANG_HOOKS_HANDLE_OPTION sdcpp_common_handle_option
59 #define LANG_HOOKS_MISSING_ARGUMENT sdcpp_common_missing_argument
60 #define LANG_HOOKS_POST_OPTIONS sdcpp_common_post_options
61 #define LANG_HOOKS_INIT sdcpp_common_init
62 #define LANG_HOOKS_FINISH sdcpp_common_finish
63 #define LANG_HOOKS_PRINT_ERROR_FUNCTION sdcpp_print_error_function
64
65 static unsigned int sdcpp_init_options (unsigned int argc, const char **argv);
66 static void sdcpp_initialize_diagnostics (diagnostic_context *context);
67 static void sdcpp_print_error_function (diagnostic_context *context, const char *file);
68
69 /* Each front end provides its own lang hook initializer.  */
70 const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
71
72 /* Name of top-level original source file (what was input to cpp).
73    This comes from the #-command at the beginning of the actual input.
74    If there isn't any there, then this is the cc1 input file name.  */
75
76 const char *main_input_filename;
77
78 #ifndef USE_MAPPED_LOCATION
79 location_t unknown_location = { NULL, 0 };
80 #endif
81
82 /* Current position in real source file.  */
83
84 location_t input_location;
85
86 struct line_maps line_table;
87
88 /* Stack of currently pending input files.  */
89
90 struct file_stack *input_file_stack;
91
92 /* Incremented on each change to input_file_stack.  */
93 int input_file_stack_tick;
94
95 /* Temporarily suppress certain warnings.
96    This is set while reading code from a system header file.  */
97
98 int in_system_header = 0;
99
100 /* Nonzero means change certain warnings into errors.
101    Usually these are warnings about failure to conform to some standard.  */
102
103 int flag_pedantic_errors = 0;
104
105 cpp_reader *parse_in;           /* Declared in c-pragma.h.  */
106
107 /* Nonzero means `char' should be signed.  */
108
109 int flag_signed_char;
110
111 /* Nonzero means don't output line number information.  */
112
113 char flag_no_line_commands;
114
115 /* Nonzero causes -E output not to be done, but directives such as
116    #define that have side effects are still obeyed.  */
117
118 char flag_no_output;
119
120 /* Nonzero means dump macros in some fashion.  */
121
122 char flag_dump_macros;
123
124 /* Nonzero means pass #include lines through to the output.  */
125
126 char flag_dump_includes;
127
128 /* 0 means we want the preprocessor to not emit line directives for
129    the current working directory.  1 means we want it to do it.  -1
130    means we should decide depending on whether debugging information
131    is being emitted or not.  */
132
133 int flag_working_directory = -1;
134
135 /* The current working directory of a translation.  It's generally the
136    directory from which compilation was initiated, but a preprocessed
137    file may specify the original directory in which it was
138    created.  */
139
140 static const char *src_pwd;
141
142 /* Initialize src_pwd with the given string, and return true.  If it
143    was already initialized, return false.  As a special case, it may
144    be called with a NULL argument to test whether src_pwd has NOT been
145    initialized yet.  */
146
147 /* From intl.c */
148 /* Opening quotation mark for diagnostics.  */
149 const char *open_quote = "'";
150
151 /* Closing quotation mark for diagnostics.  */
152 const char *close_quote = "'";
153 /* ----------- */
154
155 bool
156 set_src_pwd (const char *pwd)
157 {
158   if (src_pwd)
159     return false;
160
161   src_pwd = xstrdup (pwd);
162   return true;
163 }
164
165 /* Return the directory from which the translation unit was initiated,
166    in case set_src_pwd() was not called before to assign it a
167    different value.  */
168
169 const char *
170 get_src_pwd (void)
171 {
172   if (! src_pwd)
173     src_pwd = getpwd ();
174
175    return src_pwd;
176 }
177
178 /* SDCPP specific pragmas */
179 /* SDCC specific
180    sdcc_hash pragma */
181 static void
182 do_pragma_sdcc_hash (cpp_reader *pfile)
183 {
184     const cpp_token *tok = _cpp_lex_token (pfile);
185
186     if (tok->type == CPP_PLUS)
187     {
188         CPP_OPTION(pfile, allow_naked_hash)++;
189     }
190     else if (tok->type == CPP_MINUS)
191     {
192         CPP_OPTION(pfile, allow_naked_hash)--;
193     }
194     else
195     {
196         cpp_error (pfile, CPP_DL_ERROR,
197                    "invalid #pragma sdcc_hash directive, need '+' or '-'");
198     }
199 }
200
201 /* SDCC specific
202    pedantic_parse_number pragma */
203 static void
204 do_pragma_pedantic_parse_number (cpp_reader *pfile)
205 {
206     const cpp_token *tok = _cpp_lex_token (pfile);
207
208   if (tok->type == CPP_PLUS)
209     {
210       CPP_OPTION(pfile, pedantic_parse_number)++;
211     }
212   else if (tok->type == CPP_MINUS)
213     {
214       CPP_OPTION(pfile, pedantic_parse_number)--;
215     }
216   else
217     {
218       cpp_error (pfile, CPP_DL_ERROR,
219                  "invalid #pragma pedantic_parse_number directive, need '+' or '-'");
220     }
221 }
222
223 /* SDCC _asm specific
224    switch _asm block preprocessing on / off */
225 static void
226 do_pragma_preproc_asm (cpp_reader *pfile)
227 {
228   const cpp_token *tok = _cpp_lex_token (pfile);
229
230   if (tok->type == CPP_PLUS)
231     {
232       CPP_OPTION(pfile, preproc_asm)++;
233     }
234   else if (tok->type == CPP_MINUS)
235     {
236       CPP_OPTION(pfile, preproc_asm)--;
237     }
238   else
239     {
240       cpp_error (pfile, CPP_DL_ERROR,
241                  "invalid #pragma preproc_asm directive, need '+' or '-'");
242     }
243 }
244
245 /* SDCPP specific option initialization */
246 static unsigned int
247 sdcpp_init_options (unsigned int argc, const char **argv)
248 {
249   unsigned int ret = sdcpp_common_init_options(argc, argv);
250
251   CPP_OPTION (parse_in, allow_naked_hash) = 0;
252   CPP_OPTION (parse_in, preproc_asm) = 1;
253   CPP_OPTION (parse_in, pedantic_parse_number) = 0;
254   CPP_OPTION (parse_in, obj_ext) = NULL;
255
256   /* Kevin abuse for SDCC. */
257   cpp_register_pragma(parse_in, 0, "sdcc_hash", do_pragma_sdcc_hash, false);
258   /* SDCC _asm specific */
259   cpp_register_pragma(parse_in, 0, "preproc_asm", do_pragma_preproc_asm, false);
260   /* SDCC specific */
261   cpp_register_pragma(parse_in, 0, "pedantic_parse_number", do_pragma_pedantic_parse_number, false);
262
263   /* SDCC _asm specific */
264   parse_in->spec_nodes.n__asm = cpp_lookup (parse_in, DSC("_asm"));
265
266   return ret;
267 }
268
269 static void
270 sdcpp_initialize_diagnostics (diagnostic_context *context)
271 {
272   pretty_printer *base = context->printer;
273   c_pretty_printer *pp = xmalloc (sizeof (c_pretty_printer));
274   memcpy (pp_base (pp), base, sizeof (pretty_printer));
275   pp_c_pretty_printer_init (pp);
276   context->printer = (pretty_printer *) pp;
277
278   /* It is safe to free this object because it was previously malloc()'d.  */
279   free (base);
280 }
281
282 /* The default function to print out name of current function that caused
283    an error.  */
284 static void
285 sdcpp_print_error_function (diagnostic_context *context, const char *file)
286 {
287 }
288
289 /* Initialize the PRETTY-PRINTER for handling C codes.  */
290
291 void
292 pp_c_pretty_printer_init (c_pretty_printer *pp)
293 {
294 }
295
296 void
297 print_version (FILE *file, const char *indent)
298 {
299   fprintf (file, _("GNU CPP version %s (cpplib)"), version_string);
300 #ifdef TARGET_VERSION
301   TARGET_VERSION;
302 #endif
303   fputc ('\n', file);
304 }
305
306 /* Initialization of the front end environment, before command line
307    options are parsed.  Signal handlers, internationalization etc.
308    ARGV0 is main's argv[0].  */
309 static void
310 general_init (const char *argv0)
311 {
312   const char *p;
313
314   p = argv0 + strlen (argv0);
315   while (p != argv0 && !IS_DIR_SEPARATOR (p[-1]))
316     --p;
317   progname = p;
318
319   xmalloc_set_program_name (progname);
320
321   hex_init ();
322
323   gcc_init_libintl ();
324
325   /* Initialize the diagnostics reporting machinery, so option parsing
326      can give warnings and errors.  */
327   diagnostic_initialize (global_dc);
328 }
329
330 /* Process the options that have been parsed.  */
331 static void
332 process_options (void)
333 {
334   /* Allow the front end to perform consistency checks and do further
335      initialization based on the command line options.  This hook also
336      sets the original filename if appropriate (e.g. foo.i -> foo.c)
337      so we can correctly initialize debug output.  */
338   /*no_backend =*/ (*lang_hooks.post_options) (&main_input_filename);
339   input_filename = main_input_filename;
340 }
341
342 #if 0
343 /* A warning.  Use this for code which is correct according to the
344    relevant language specification but is likely to be buggy anyway.  */
345 void
346 warning (const char *msgid, ...)
347 {
348   va_list ap;
349
350   va_start (ap, msgid);
351   fprintf (stderr, "%s: error: ", progname);
352   vfprintf (stderr, msgid, ap);
353   va_end (ap);
354 }
355
356 /* A hard error: the code is definitely ill-formed, and an object file
357    will not be produced.  */
358 void
359 error (const char *msgid, ...)
360 {
361   va_list ap;
362
363   va_start (ap, msgid);
364   fprintf (stderr, "%s: warning: ", progname);
365   vfprintf (stderr, msgid, ap);
366   va_end (ap);
367 }
368
369 /* Print a fatal I/O error message.  Argument are like printf.
370    Also include a system error message based on `errno'.  */
371 void
372 fatal_io_error (const char *msgid, ...)
373 {
374   va_list ap;
375
376   va_start (ap, msgid);
377   fprintf (stderr, "%s: %s: ", progname, xstrerror (errno));
378   vfprintf(stderr, msgid, ap);
379   va_end (ap);
380   exit (FATAL_EXIT_CODE);
381 }
382 #endif
383
384 /* Parse a -d... command line switch.  */
385
386 void
387 decode_d_option (const char *arg)
388 {
389   int c;
390
391   while (*arg)
392     switch (c = *arg++)
393       {
394       case 'D': /* These are handled by the preprocessor.  */
395       case 'I':
396       case 'M':
397       case 'N':
398         break;
399
400       default:
401         warning (0, "unrecognized gcc debugging option: %c", c);
402         break;
403       }
404 }
405
406 /* Language-dependent initialization.  Returns nonzero on success.  */
407 static int
408 lang_dependent_init (const char *name)
409 {
410   /* Other front-end initialization.  */
411   if ((*lang_hooks.init) () == 0)
412     return 0;
413
414   return 1;
415 }
416
417 /* Clean up: close opened files, etc.  */
418
419 static void
420 finalize (void)
421 {
422   /* Language-specific end of compilation actions.  */
423   (*lang_hooks.finish) ();
424 }
425
426 /* Initialize the compiler, and compile the input file.  */
427 static void
428 do_compile (void)
429 {
430   process_options ();
431
432   /* Don't do any more if an error has already occurred.  */
433   if (!errorcount)
434     {
435       /* Language-dependent initialization.  Returns true on success.  */
436       lang_dependent_init (main_input_filename);
437
438       finalize ();
439     }
440 }
441
442 /* Entry point of cc1, cc1plus, jc1, f771, etc.
443    Exit code is FATAL_EXIT_CODE if can't open files or if there were
444    any errors, or SUCCESS_EXIT_CODE if compilation succeeded.
445
446    It is not safe to call this function more than once.  */
447
448 int
449 main (unsigned int argc, const char **argv)
450 {
451   /* Initialization of GCC's environment, and diagnostics.  */
452   general_init (argv[0]);
453
454   /* Parse the options and do minimal processing; basically just
455      enough to default flags appropriately.  */
456   decode_options (argc, argv);
457
458   /* Exit early if we can (e.g. -help).  */
459   if (!exit_after_options)
460     do_compile ();
461
462   if (errorcount || sorrycount)
463     return (FATAL_EXIT_CODE);
464
465   return (SUCCESS_EXIT_CODE);
466 }