|
|
1.1 root 1: /* C Compatible Compiler Preprocessor (CCCP)
2: Copyright (C) 1986, 1987, 1989, 1992 Free Software Foundation, Inc.
3: Written by Paul Rubin, June 1986
4: Adapted to ANSI C, Richard Stallman, Jan 1987
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, 675 Mass Ave, Cambridge, MA 02139, 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: typedef unsigned char U_CHAR;
25:
26: #ifdef EMACS
27: #define NO_SHORTNAMES
28: #include "../src/config.h"
29: #ifdef open
30: #undef open
31: #undef read
32: #undef write
33: #endif /* open */
34: #endif /* EMACS */
35:
36: /* The macro EMACS is defined when cpp is distributed as part of Emacs,
37: for the sake of machines with limited C compilers. */
38: #ifndef EMACS
39: #include "config.h"
40: #endif /* not EMACS */
41:
42: #ifndef STANDARD_INCLUDE_DIR
43: #define STANDARD_INCLUDE_DIR "/usr/include"
44: #endif
45:
46: #ifndef LOCAL_INCLUDE_DIR
47: #define LOCAL_INCLUDE_DIR "/usr/local/include"
48: #endif
49:
50: #include "pcp.h"
51:
52: #ifndef STDC_VALUE
53: #define STDC_VALUE 1
54: #endif
55:
56: /* In case config.h defines these. */
57: #undef bcopy
58: #undef bzero
59: #undef bcmp
60:
61: #include <sys/types.h>
62: #include <sys/stat.h>
63: #include <ctype.h>
64: #include <stdio.h>
65: #include <signal.h>
66:
67: #ifndef VMS
68: #include <sys/file.h>
69: #ifndef USG
70: #include <sys/time.h> /* for __DATE__ and __TIME__ */
71: #include <sys/resource.h>
72: #else
73: #define index strchr
74: #define rindex strrchr
75: #include <time.h>
76: #include <fcntl.h>
77: #endif /* USG */
78: #endif /* not VMS */
79:
80: extern char *index ();
81: extern char *rindex ();
82:
83: /* VMS-specific definitions */
84: #ifdef VMS
85: #include <time.h>
86: #include <errno.h> /* This defines "errno" properly */
87: #include <perror.h> /* This defines sys_errlist/sys_nerr properly */
88: #include <descrip.h>
89: #define O_RDONLY 0 /* Open arg for Read/Only */
90: #define O_WRONLY 1 /* Open arg for Write/Only */
91: #define read(fd,buf,size) VMS_read(fd,buf,size)
92: #define write(fd,buf,size) VMS_write(fd,buf,size)
93: #define open(fname,mode,prot) VMS_open(fname,mode,prot)
94: #define fopen(fname,mode) VMS_fopen(fname,mode)
95: #define freopen(fname,mode,ofile) VMS_freopen(fname,mode,ofile)
96: static int VMS_read ();
97: static int VMS_write ();
98: static int VMS_open ();
99: static FILE * VMS_fopen ();
100: static FILE * VMS_freopen ();
101: static void hack_vms_include_specification ();
102: typedef struct { unsigned :16, :16, :16; } vms_ino_t;
103: #define ino_t vms_ino_t
104: #ifdef __GNUC__
105: #define BSTRING /* VMS/GCC supplies the bstring routines */
106: #endif /* __GNUC__ */
107: #endif /* VMS */
108:
109: #ifndef O_RDONLY
110: #define O_RDONLY 0
111: #endif
112:
113: #undef MIN
114: #undef MAX
115: #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
116: #define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
117:
118: #ifndef S_ISREG
119: #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
120: #endif
121:
122: /* Exported declarations. */
123:
124: char *xmalloc ();
125: void error ();
126: void warning ();
127:
128: /* External declarations. */
129:
130: extern char *getenv ();
131: extern FILE *fdopen ();
132: extern char *version_string;
133: extern struct tm *localtime ();
134: extern int sys_nerr;
135: extern char *sys_errlist[];
136:
137: #ifndef errno
138: extern int errno;
139: #endif
140:
141: /* Forward declarations. */
142:
143: struct directive;
144: struct file_buf;
145: struct arglist;
146: struct argdata;
147:
148: #if defined(USG) || defined(VMS)
149: #ifndef BSTRING
150: void bcopy ();
151: void bzero ();
152: int bcmp ();
153: #endif
154: #endif
155:
156: /* These functions are declared to return int instead of void since they
157: are going to be placed in a table and some old compilers have trouble with
158: pointers to functions returning void. */
159:
160: static int do_define ();
161: static int do_line ();
162: static int do_include ();
163: static int do_undef ();
164: static int do_error ();
165: static int do_pragma ();
166: static int do_ident ();
167: static int do_if ();
168: static int do_xifdef ();
169: static int do_else ();
170: static int do_elif ();
171: static int do_endif ();
172: static int do_sccs ();
173: static int do_once ();
174: static int do_assert ();
175: static int do_unassert ();
176: static int do_warning ();
177:
178: static void add_import ();
179: static void deps_output ();
180: static void make_undef ();
181: static void make_definition ();
182: static void make_assertion ();
183: static void path_include ();
184: static void initialize_builtins ();
185: static void initialize_char_syntax ();
186: static void dump_arg_n ();
187: static void dump_defn_1 ();
188: static void delete_macro ();
189: static void trigraph_pcp ();
190: static void rescan ();
191: static void finclude ();
192: static void validate_else ();
193: static int comp_def_part ();
194: static void error_from_errno ();
195: static void error_with_line ();
196: void pedwarn ();
197: static void pedwarn_with_file_and_line ();
198: static void fatal ();
199: void fancy_abort ();
200: static void pfatal_with_name ();
201: static void perror_with_name ();
202: static void print_containing_files ();
203: static int lookup_import ();
1.1.1.2 ! root 204: static int lookup_include ();
1.1 root 205: static int check_preconditions ();
206: static void pcfinclude ();
207: static void pcstring_used ();
208: static void write_output ();
209: static int check_macro_name ();
210: static int compare_defs ();
211: static int compare_token_lists ();
212: static int eval_if_expression ();
213: static int discard_comments ();
214: static int delete_newlines ();
215: static int line_for_error ();
216: static int hashf ();
217: static int file_size_and_mode ();
218:
219: static struct arglist *read_token_list ();
220: static void free_token_list ();
221:
222: static struct hashnode *install ();
223: struct hashnode *lookup ();
224:
225: static struct assertion_hashnode *assertion_install ();
226: static struct assertion_hashnode *assertion_lookup ();
227:
228: static char *xrealloc ();
229: static char *xcalloc ();
230: static char *savestring ();
231:
232: static void delete_assertion ();
233: static void macroexpand ();
234: static void dump_all_macros ();
235: static void conditional_skip ();
236: static void skip_if_group ();
237: static void output_line_command ();
238:
239: /* Last arg to output_line_command. */
240: enum file_change_code {same_file, enter_file, leave_file};
241:
242: static int grow_outbuf ();
243: static int handle_directive ();
244: static void memory_full ();
245:
246: static U_CHAR *macarg1 ();
247: static char *macarg ();
248:
249: static U_CHAR *skip_to_end_of_comment ();
250: static U_CHAR *skip_quoted_string ();
251: static U_CHAR *skip_paren_group ();
252:
253: static char *check_precompiled ();
254: static struct macrodef create_definition ();
255: static void dump_single_macro ();
256:
257: #ifndef FAILURE_EXIT_CODE
258: #define FAILURE_EXIT_CODE 33 /* gnu cc command understands this */
259: #endif
260:
261: #ifndef SUCCESS_EXIT_CODE
262: #define SUCCESS_EXIT_CODE 0 /* 0 means success on Unix. */
263: #endif
264:
265: /* Name under which this program was invoked. */
266:
267: static char *progname;
268:
269: /* Nonzero means handle C++ comment syntax and use
270: extra default include directories for C++. */
271:
272: static int cplusplus;
273:
274: /* Nonzero means handle #import, for objective C. */
275:
276: static int objc;
277:
278: /* Nonzero means this is an assembly file, and allow
279: unknown directives, which could be comments. */
280:
281: static int lang_asm;
282:
283: /* Current maximum length of directory names in the search path
284: for include files. (Altered as we get more of them.) */
285:
286: static int max_include_len;
287:
288: /* Nonzero means turn NOTREACHED into #pragma NOTREACHED etc */
289:
290: static int lint = 0;
291:
292: /* Nonzero means copy comments into the output file. */
293:
294: static int put_out_comments = 0;
295:
296: /* Nonzero means don't process the ANSI trigraph sequences. */
297:
298: static int no_trigraphs = 0;
299:
300: /* Nonzero means print the names of included files rather than
301: the preprocessed output. 1 means just the #include "...",
302: 2 means #include <...> as well. */
303:
304: static int print_deps = 0;
305:
306: /* Nonzero means print names of header files (-H). */
307:
308: static int print_include_names = 0;
309:
310: /* Nonzero means don't output line number information. */
311:
312: static int no_line_commands;
313:
314: /* dump_only means inhibit output of the preprocessed text
315: and instead output the definitions of all user-defined
316: macros in a form suitable for use as input to cccp.
317: dump_names means pass #define and the macro name through to output.
318: dump_definitions means pass the whole definition (plus #define) through
319: */
320:
321: static enum {dump_none, dump_only, dump_names, dump_definitions}
322: dump_macros = dump_none;
323:
324: /* Nonzero means pass all #define and #undef directives which we actually
325: process through to the output stream. This feature is used primarily
326: to allow cc1 to record the #defines and #undefs for the sake of
327: debuggers which understand about preprocessor macros, but it may
328: also be useful with -E to figure out how symbols are defined, and
329: where they are defined. */
330: static int debug_output = 0;
331:
332: /* Holds local startup time. */
333: static struct tm *timebuf = NULL;
334:
335: /* Nonzero indicates special processing used by the pcp program. The
336: special effects of this mode are:
337:
338: Inhibit all macro expansion, except those inside #if directives.
339:
340: Process #define directives normally, and output their contents
341: to the output file.
342:
343: Output preconditions to pcp_outfile indicating all the relevant
344: preconditions for use of this file in a later cpp run.
345: */
346: static FILE *pcp_outfile;
347:
348: /* Nonzero means we are inside an IF during a -pcp run. In this mode
349: macro expansion is done, and preconditions are output for all macro
350: uses requiring them. */
351: static int pcp_inside_if;
352:
353: /* Nonzero means never to include precompiled files. */
354: static int no_precomp;
355:
356: /* Nonzero means give all the error messages the ANSI standard requires. */
357:
358: int pedantic;
359:
360: /* Nonzero means try to make failure to fit ANSI C an error. */
361:
362: static int pedantic_errors;
363:
364: /* Nonzero means don't print warning messages. -w. */
365:
366: static int inhibit_warnings = 0;
367:
368: /* Nonzero means warn if slash-star appears in a comment. */
369:
370: static int warn_comments;
371:
372: /* Nonzero means warn if a macro argument is (or would be)
373: stringified with -traditional. */
374:
375: static int warn_stringify;
376:
377: /* Nonzero means warn if there are any trigraphs. */
378:
379: static int warn_trigraphs;
380:
1.1.1.2 ! root 381: /* Nonzero means warn if #import is used. */
! 382:
! 383: static int warn_import = 1;
! 384:
1.1 root 385: /* Nonzero means turn warnings into errors. */
386:
387: static int warnings_are_errors;
388:
389: /* Nonzero means try to imitate old fashioned non-ANSI preprocessor. */
390:
391: int traditional;
392:
393: /* Nonzero causes output not to be done,
394: but directives such as #define that have side effects
395: are still obeyed. */
396:
397: static int no_output;
398:
399: /* Nonzero means that we have finished processing the command line options.
400: This flag is used to decide whether or not to issue certain errors
401: and/or warnings. */
402:
403: static int done_initializing = 0;
404:
405: /* I/O buffer structure.
406: The `fname' field is nonzero for source files and #include files
407: and for the dummy text used for -D and -U.
408: It is zero for rescanning results of macro expansion
409: and for expanding macro arguments. */
410: #define INPUT_STACK_MAX 200
411: static struct file_buf {
412: char *fname;
413: /* Filename specified with #line command. */
414: char *nominal_fname;
415: /* Record where in the search path this file was found.
416: For #include_next. */
417: struct file_name_list *dir;
418: int lineno;
419: int length;
420: U_CHAR *buf;
421: U_CHAR *bufp;
422: /* Macro that this level is the expansion of.
423: Included so that we can reenable the macro
424: at the end of this level. */
425: struct hashnode *macro;
426: /* Value of if_stack at start of this file.
427: Used to prohibit unmatched #endif (etc) in an include file. */
428: struct if_stack *if_stack;
429: /* Object to be freed at end of input at this level. */
430: U_CHAR *free_ptr;
431: /* True if this is a header file included using <FILENAME>. */
432: char system_header_p;
433: } instack[INPUT_STACK_MAX];
434:
435: static int last_error_tick; /* Incremented each time we print it. */
436: static int input_file_stack_tick; /* Incremented when the status changes. */
437:
438: /* Current nesting level of input sources.
439: `instack[indepth]' is the level currently being read. */
440: static int indepth = -1;
441: #define CHECK_DEPTH(code) \
442: if (indepth >= (INPUT_STACK_MAX - 1)) \
443: { \
444: error_with_line (line_for_error (instack[indepth].lineno), \
445: "macro or `#include' recursion too deep"); \
446: code; \
447: }
448:
449: /* Current depth in #include directives that use <...>. */
450: static int system_include_depth = 0;
451:
452: typedef struct file_buf FILE_BUF;
453:
454: /* The output buffer. Its LENGTH field is the amount of room allocated
455: for the buffer, not the number of chars actually present. To get
456: that, subtract outbuf.buf from outbuf.bufp. */
457:
458: #define OUTBUF_SIZE 10 /* initial size of output buffer */
459: static FILE_BUF outbuf;
460:
461: /* Grow output buffer OBUF points at
462: so it can hold at least NEEDED more chars. */
463:
464: #define check_expand(OBUF, NEEDED) \
465: (((OBUF)->length - ((OBUF)->bufp - (OBUF)->buf) <= (NEEDED)) \
466: ? grow_outbuf ((OBUF), (NEEDED)) : 0)
467:
468: struct file_name_list
469: {
470: struct file_name_list *next;
471: char *fname;
472: /* If the following is nonzero, it is a macro name.
473: Don't include the file again if that macro is defined. */
474: U_CHAR *control_macro;
475: };
476:
477: /* #include "file" looks in source file dir, then stack. */
478: /* #include <file> just looks in the stack. */
479: /* -I directories are added to the end, then the defaults are added. */
480: static struct default_include { char *fname; int cplusplus; } include_defaults_array[]
481: #ifdef INCLUDE_DEFAULTS
482: = INCLUDE_DEFAULTS;
483: #else
484: = {
485: /* Pick up GNU C++ specific include files. */
486: { GPLUSPLUS_INCLUDE_DIR, 1},
487: { GCC_INCLUDE_DIR, 0},
488: #ifdef CROSS_COMPILE
489: /* For cross-compilation, this dir name is generated
490: automatically in Makefile.in. */
491: { CROSS_INCLUDE_DIR, 0 },
492: #else /* not CROSS_COMPILE */
493: { LOCAL_INCLUDE_DIR, 0},
494: /* Some systems have an extra dir of include files. */
495: #ifdef SYSTEM_INCLUDE_DIR
496: { SYSTEM_INCLUDE_DIR, 0},
497: #endif
498: { STANDARD_INCLUDE_DIR, 0},
499: #endif /* not CROSS_COMPILE */
500: { 0, 0}
501: };
502: #endif /* no INCLUDE_DEFAULTS */
503:
504: /* The code looks at the defaults through this pointer, rather than through
505: the constant structure above. This pointer gets changed if an environment
506: variable specifies other defaults. */
507: static struct default_include *include_defaults = include_defaults_array;
508:
509: static struct file_name_list *include = 0; /* First dir to search */
510: /* First dir to search for <file> */
511: static struct file_name_list *first_bracket_include = 0;
512: static struct file_name_list *last_include = 0; /* Last in chain */
513:
514: /* Chain of include directories to put at the end of the other chain. */
515: static struct file_name_list *after_include = 0;
516: static struct file_name_list *last_after_include = 0; /* Last in chain */
517:
518: /* List of included files that contained #pragma once. */
519: static struct file_name_list *dont_repeat_files = 0;
520:
521: /* List of other included files.
522: If ->control_macro if nonzero, the file had a #ifndef
523: around the entire contents, and ->control_macro gives the macro name. */
524: static struct file_name_list *all_include_files = 0;
525:
526: /* Global list of strings read in from precompiled files. This list
527: is kept in the order the strings are read in, with new strings being
528: added at the end through stringlist_tailp. We use this list to output
529: the strings at the end of the run.
530: */
531: static STRINGDEF *stringlist;
532: static STRINGDEF **stringlist_tailp = &stringlist;
533:
534:
535: /* Structure returned by create_definition */
536: typedef struct macrodef MACRODEF;
537: struct macrodef
538: {
539: struct definition *defn;
540: U_CHAR *symnam;
541: int symlen;
542: };
543:
544:
545: /* Structure allocated for every #define. For a simple replacement
546: such as
547: #define foo bar ,
548: nargs = -1, the `pattern' list is null, and the expansion is just
549: the replacement text. Nargs = 0 means a functionlike macro with no args,
550: e.g.,
551: #define getchar() getc (stdin) .
552: When there are args, the expansion is the replacement text with the
553: args squashed out, and the reflist is a list describing how to
554: build the output from the input: e.g., "3 chars, then the 1st arg,
555: then 9 chars, then the 3rd arg, then 0 chars, then the 2nd arg".
556: The chars here come from the expansion. Whatever is left of the
557: expansion after the last arg-occurrence is copied after that arg.
558: Note that the reflist can be arbitrarily long---
559: its length depends on the number of times the arguments appear in
560: the replacement text, not how many args there are. Example:
561: #define f(x) x+x+x+x+x+x+x would have replacement text "++++++" and
562: pattern list
563: { (0, 1), (1, 1), (1, 1), ..., (1, 1), NULL }
564: where (x, y) means (nchars, argno). */
565:
566: typedef struct definition DEFINITION;
567: struct definition {
568: int nargs;
569: int length; /* length of expansion string */
570: int predefined; /* True if the macro was builtin or */
571: /* came from the command line */
572: U_CHAR *expansion;
573: int line; /* Line number of definition */
574: char *file; /* File of definition */
575: struct reflist {
576: struct reflist *next;
577: char stringify; /* nonzero if this arg was preceded by a
578: # operator. */
579: char raw_before; /* Nonzero if a ## operator before arg. */
580: char raw_after; /* Nonzero if a ## operator after arg. */
581: int nchars; /* Number of literal chars to copy before
582: this arg occurrence. */
583: int argno; /* Number of arg to substitute (origin-0) */
584: } *pattern;
585: union {
586: /* Names of macro args, concatenated in reverse order
587: with comma-space between them.
588: The only use of this is that we warn on redefinition
589: if this differs between the old and new definitions. */
590: U_CHAR *argnames;
591: } args;
592: };
593:
594: /* different kinds of things that can appear in the value field
595: of a hash node. Actually, this may be useless now. */
596: union hashval {
597: int ival;
598: char *cpval;
599: DEFINITION *defn;
600: KEYDEF *keydef;
601: };
602:
603:
604: /* The structure of a node in the hash table. The hash table
605: has entries for all tokens defined by #define commands (type T_MACRO),
606: plus some special tokens like __LINE__ (these each have their own
607: type, and the appropriate code is run when that type of node is seen.
608: It does not contain control words like "#define", which are recognized
609: by a separate piece of code. */
610:
611: /* different flavors of hash nodes --- also used in keyword table */
612: enum node_type {
613: T_DEFINE = 1, /* the `#define' keyword */
614: T_INCLUDE, /* the `#include' keyword */
615: T_INCLUDE_NEXT, /* the `#include_next' keyword */
616: T_IMPORT, /* the `#import' keyword */
617: T_IFDEF, /* the `#ifdef' keyword */
618: T_IFNDEF, /* the `#ifndef' keyword */
619: T_IF, /* the `#if' keyword */
620: T_ELSE, /* `#else' */
621: T_PRAGMA, /* `#pragma' */
622: T_ELIF, /* `#elif' */
623: T_UNDEF, /* `#undef' */
624: T_LINE, /* `#line' */
625: T_ERROR, /* `#error' */
626: T_WARNING, /* `#warning' */
627: T_ENDIF, /* `#endif' */
628: T_SCCS, /* `#sccs', used on system V. */
629: T_IDENT, /* `#ident', used on system V. */
630: T_ASSERT, /* `#assert', taken from system V. */
631: T_UNASSERT, /* `#unassert', taken from system V. */
632: T_SPECLINE, /* special symbol `__LINE__' */
633: T_DATE, /* `__DATE__' */
634: T_FILE, /* `__FILE__' */
635: T_BASE_FILE, /* `__BASE_FILE__' */
636: T_INCLUDE_LEVEL, /* `__INCLUDE_LEVEL__' */
637: T_VERSION, /* `__VERSION__' */
638: T_SIZE_TYPE, /* `__SIZE_TYPE__' */
639: T_PTRDIFF_TYPE, /* `__PTRDIFF_TYPE__' */
640: T_WCHAR_TYPE, /* `__WCHAR_TYPE__' */
641: T_TIME, /* `__TIME__' */
642: T_CONST, /* Constant value, used by `__STDC__' */
643: T_MACRO, /* macro defined by `#define' */
644: T_DISABLED, /* macro temporarily turned off for rescan */
645: T_SPEC_DEFINED, /* special `defined' macro for use in #if statements */
646: T_PCSTRING, /* precompiled string (hashval is KEYDEF *) */
647: T_UNUSED /* Used for something not defined. */
648: };
649:
650: struct hashnode {
651: struct hashnode *next; /* double links for easy deletion */
652: struct hashnode *prev;
653: struct hashnode **bucket_hdr; /* also, a back pointer to this node's hash
654: chain is kept, in case the node is the head
655: of the chain and gets deleted. */
656: enum node_type type; /* type of special token */
657: int length; /* length of token, for quick comparison */
658: U_CHAR *name; /* the actual name */
659: union hashval value; /* pointer to expansion, or whatever */
660: };
661:
662: typedef struct hashnode HASHNODE;
663:
664: /* Some definitions for the hash table. The hash function MUST be
665: computed as shown in hashf () below. That is because the rescan
666: loop computes the hash value `on the fly' for most tokens,
667: in order to avoid the overhead of a lot of procedure calls to
668: the hashf () function. Hashf () only exists for the sake of
669: politeness, for use when speed isn't so important. */
670:
671: #define HASHSIZE 1403
672: static HASHNODE *hashtab[HASHSIZE];
673: #define HASHSTEP(old, c) ((old << 2) + c)
674: #define MAKE_POS(v) (v & 0x7fffffff) /* make number positive */
675:
676: /* Symbols to predefine. */
677:
678: #ifdef CPP_PREDEFINES
679: static char *predefs = CPP_PREDEFINES;
680: #else
681: static char *predefs = "";
682: #endif
683:
684: /* We let tm.h override the types used here, to handle trivial differences
685: such as the choice of unsigned int or long unsigned int for size_t.
686: When machines start needing nontrivial differences in the size type,
687: it would be best to do something here to figure out automatically
688: from other information what type to use. */
689:
690: /* The string value for __size_type__. */
691:
692: #ifndef SIZE_TYPE
693: #define SIZE_TYPE "long unsigned int"
694: #endif
695:
696: /* The string value for __ptrdiff_type__. */
697:
698: #ifndef PTRDIFF_TYPE
699: #define PTRDIFF_TYPE "long int"
700: #endif
701:
702: /* The string value for __wchar_type__. */
703:
704: #ifndef WCHAR_TYPE
705: #define WCHAR_TYPE "int"
706: #endif
707:
708: /* In the definition of a #assert name, this structure forms
709: a list of the individual values asserted.
710: Each value is itself a list of "tokens".
711: These are strings that are compared by name. */
712:
713: struct tokenlist_list {
714: struct tokenlist_list *next;
715: struct arglist *tokens;
716: };
717:
718: struct assertion_hashnode {
719: struct assertion_hashnode *next; /* double links for easy deletion */
720: struct assertion_hashnode *prev;
721: /* also, a back pointer to this node's hash
722: chain is kept, in case the node is the head
723: of the chain and gets deleted. */
724: struct assertion_hashnode **bucket_hdr;
725: int length; /* length of token, for quick comparison */
726: U_CHAR *name; /* the actual name */
727: /* List of token-sequences. */
728: struct tokenlist_list *value;
729: };
730:
731: typedef struct assertion_hashnode ASSERTION_HASHNODE;
732:
733: /* Some definitions for the hash table. The hash function MUST be
734: computed as shown in hashf () below. That is because the rescan
735: loop computes the hash value `on the fly' for most tokens,
736: in order to avoid the overhead of a lot of procedure calls to
737: the hashf () function. Hashf () only exists for the sake of
738: politeness, for use when speed isn't so important. */
739:
740: #define ASSERTION_HASHSIZE 37
741: static ASSERTION_HASHNODE *assertion_hashtab[ASSERTION_HASHSIZE];
742:
743: /* Nonzero means inhibit macroexpansion of what seem to be
744: assertion tests, in rescan. For #if. */
745: static int assertions_flag;
746:
747: /* `struct directive' defines one #-directive, including how to handle it. */
748:
749: struct directive {
750: int length; /* Length of name */
751: int (*func)(); /* Function to handle directive */
752: char *name; /* Name of directive */
753: enum node_type type; /* Code which describes which directive. */
754: char angle_brackets; /* Nonzero => <...> is special. */
755: char traditional_comments; /* Nonzero: keep comments if -traditional. */
756: char pass_thru; /* Copy preprocessed directive to output file. */
757: };
758:
759: /* Here is the actual list of #-directives, most-often-used first. */
760:
761: static struct directive directive_table[] = {
762: { 6, do_define, "define", T_DEFINE, 0, 1},
763: { 2, do_if, "if", T_IF},
764: { 5, do_xifdef, "ifdef", T_IFDEF},
765: { 6, do_xifdef, "ifndef", T_IFNDEF},
766: { 5, do_endif, "endif", T_ENDIF},
767: { 4, do_else, "else", T_ELSE},
768: { 4, do_elif, "elif", T_ELIF},
769: { 4, do_line, "line", T_LINE},
770: { 7, do_include, "include", T_INCLUDE, 1},
771: { 12, do_include, "include_next", T_INCLUDE_NEXT, 1},
772: { 6, do_include, "import", T_IMPORT, 1},
773: { 5, do_undef, "undef", T_UNDEF},
774: { 5, do_error, "error", T_ERROR},
775: { 7, do_warning, "warning", T_WARNING},
776: #ifdef SCCS_DIRECTIVE
777: { 4, do_sccs, "sccs", T_SCCS},
778: #endif
779: { 6, do_pragma, "pragma", T_PRAGMA, 0, 0, 1},
780: { 5, do_ident, "ident", T_IDENT, 0, 0, 1},
781: { 6, do_assert, "assert", T_ASSERT},
782: { 8, do_unassert, "unassert", T_UNASSERT},
783: { -1, 0, "", T_UNUSED},
784: };
785:
786: /* When a directive handler is called,
787: this points to the # that started the directive. */
788: U_CHAR *directive_start;
789:
790: /* table to tell if char can be part of a C identifier. */
791: U_CHAR is_idchar[256];
792: /* table to tell if char can be first char of a c identifier. */
793: U_CHAR is_idstart[256];
794: /* table to tell if c is horizontal space. */
795: U_CHAR is_hor_space[256];
796: /* table to tell if c is horizontal or vertical space. */
797: static U_CHAR is_space[256];
798:
799: #define SKIP_WHITE_SPACE(p) do { while (is_hor_space[*p]) p++; } while (0)
800: #define SKIP_ALL_WHITE_SPACE(p) do { while (is_space[*p]) p++; } while (0)
801:
802: static int errors = 0; /* Error counter for exit code */
803:
804: /* Zero means dollar signs are punctuation.
805: -$ stores 0; -traditional may store 1. Default is 1 for VMS, 0 otherwise.
806: This must be 0 for correct processing of this ANSI C program:
807: #define foo(a) #a
808: #define lose(b) foo(b)
809: #define test$
810: lose(test) */
811: static int dollars_in_ident;
812: #ifndef DOLLARS_IN_IDENTIFIERS
813: #define DOLLARS_IN_IDENTIFIERS 1
814: #endif
815:
816: static FILE_BUF expand_to_temp_buffer ();
817:
818: static DEFINITION *collect_expansion ();
819:
820: /* Stack of conditionals currently in progress
821: (including both successful and failing conditionals). */
822:
823: struct if_stack {
824: struct if_stack *next; /* for chaining to the next stack frame */
825: char *fname; /* copied from input when frame is made */
826: int lineno; /* similarly */
827: int if_succeeded; /* true if a leg of this if-group
828: has been passed through rescan */
829: U_CHAR *control_macro; /* For #ifndef at start of file,
830: this is the macro name tested. */
831: enum node_type type; /* type of last directive seen in this group */
832: };
833: typedef struct if_stack IF_STACK_FRAME;
834: static IF_STACK_FRAME *if_stack = NULL;
835:
836: /* Buffer of -M output. */
837: static char *deps_buffer;
838:
839: /* Number of bytes allocated in above. */
840: static int deps_allocated_size;
841:
842: /* Number of bytes used. */
843: static int deps_size;
844:
845: /* Number of bytes since the last newline. */
846: static int deps_column;
847:
848: /* File name which deps are being written to.
849: This is 0 if deps are being written to stdout. */
850: static char *deps_file = 0;
851:
852: /* Nonzero means -I- has been seen,
853: so don't look for #include "foo" the source-file directory. */
854: static int ignore_srcdir;
855:
856: /* Handler for SIGPIPE. */
857:
858: static void
859: pipe_closed (signo)
860: /* If this is missing, some compilers complain. */
861: int signo;
862: {
863: fatal ("output pipe has been closed");
864: }
865:
866: int
867: main (argc, argv)
868: int argc;
869: char **argv;
870: {
871: int st_mode;
872: long st_size;
873: char *in_fname, *out_fname;
874: char *p;
875: int f, i;
876: FILE_BUF *fp;
877: char **pend_files = (char **) xmalloc (argc * sizeof (char *));
878: char **pend_defs = (char **) xmalloc (argc * sizeof (char *));
879: char **pend_undefs = (char **) xmalloc (argc * sizeof (char *));
880: char **pend_assertions = (char **) xmalloc (argc * sizeof (char *));
881: char **pend_includes = (char **) xmalloc (argc * sizeof (char *));
882:
883: /* Record the option used with each element of pend_assertions.
884: This is preparation for supporting more than one option for making
885: an assertion. */
886: char **pend_assertion_options = (char **) xmalloc (argc * sizeof (char *));
887: int inhibit_predefs = 0;
888: int no_standard_includes = 0;
889: int missing_newline = 0;
890:
891: /* Non-0 means don't output the preprocessed program. */
892: int inhibit_output = 0;
893:
894: /* Stream on which to print the dependency information. */
895: FILE *deps_stream = 0;
896: /* Target-name to write with the dependency information. */
897: char *deps_target = 0;
898:
899: #ifdef RLIMIT_STACK
900: /* Get rid of any avoidable limit on stack size. */
901: {
902: struct rlimit rlim;
903:
904: /* Set the stack limit huge so that alloca (particularly stringtab
905: * in dbxread.c) does not fail. */
906: getrlimit (RLIMIT_STACK, &rlim);
907: rlim.rlim_cur = rlim.rlim_max;
908: setrlimit (RLIMIT_STACK, &rlim);
909: }
910: #endif /* RLIMIT_STACK defined */
911:
912: progname = argv[0];
913: #ifdef VMS
914: {
915: /* Remove directories from PROGNAME. */
916: char *s;
917:
918: progname = savestring (argv[0]);
919:
920: if (!(s = rindex (progname, ']')))
921: s = rindex (progname, ':');
922: if (s)
923: strcpy (progname, s+1);
924: if (s = rindex (progname, '.'))
925: *s = '\0';
926: }
927: #endif
928:
929: in_fname = NULL;
930: out_fname = NULL;
931:
932: /* Initialize is_idchar to allow $. */
933: dollars_in_ident = 1;
934: initialize_char_syntax ();
935: dollars_in_ident = DOLLARS_IN_IDENTIFIERS > 0;
936:
937: no_line_commands = 0;
938: no_trigraphs = 1;
939: dump_macros = dump_none;
940: no_output = 0;
941: cplusplus = 0;
942:
943: #ifdef SIGPIPE
944: signal (SIGPIPE, pipe_closed);
945: #endif
946:
947: for (i = 0; include_defaults[i].fname; i++)
948: max_include_len = MAX (max_include_len,
949: strlen (include_defaults[i].fname));
950: /* Leave room for making file name longer when converting to VMS syntax. */
951: #ifdef VMS
952: max_include_len += 10;
953: #endif
954:
955: bzero (pend_files, argc * sizeof (char *));
956: bzero (pend_defs, argc * sizeof (char *));
957: bzero (pend_undefs, argc * sizeof (char *));
958: bzero (pend_assertions, argc * sizeof (char *));
959: bzero (pend_includes, argc * sizeof (char *));
960:
961: /* Process switches and find input file name. */
962:
963: for (i = 1; i < argc; i++) {
964: if (argv[i][0] != '-') {
965: if (out_fname != NULL)
966: fatal ("Usage: %s [switches] input output", argv[0]);
967: else if (in_fname != NULL)
968: out_fname = argv[i];
969: else
970: in_fname = argv[i];
971: } else {
972: switch (argv[i][1]) {
973:
974: case 'i':
975: if (!strcmp (argv[i], "-include")) {
976: if (i + 1 == argc)
977: fatal ("Filename missing after -include option");
978: else
979: pend_includes[i] = argv[i+1], i++;
980: }
981: if (!strcmp (argv[i], "-imacros")) {
982: if (i + 1 == argc)
983: fatal ("Filename missing after -imacros option");
984: else
985: pend_files[i] = argv[i+1], i++;
986: }
987: /* Add directory to end of path for includes. */
988: if (!strcmp (argv[i], "-idirafter")) {
989: struct file_name_list *dirtmp;
990:
991: dirtmp = (struct file_name_list *)
992: xmalloc (sizeof (struct file_name_list));
993: dirtmp->next = 0; /* New one goes on the end */
994: dirtmp->control_macro = 0;
995: if (after_include == 0)
996: after_include = dirtmp;
997: else
998: last_after_include->next = dirtmp;
999: last_after_include = dirtmp; /* Tail follows the last one */
1000:
1001: if (i + 1 == argc)
1002: fatal ("Directory name missing after -idirafter option");
1003: else
1004: dirtmp->fname = argv[++i];
1005:
1006: if (strlen (dirtmp->fname) > max_include_len)
1007: max_include_len = strlen (dirtmp->fname);
1008: }
1009: break;
1010:
1011: case 'o':
1012: if (out_fname != NULL)
1013: fatal ("Output filename specified twice");
1014: if (i + 1 == argc)
1015: fatal ("Filename missing after -o option");
1016: out_fname = argv[++i];
1017: if (!strcmp (out_fname, "-"))
1018: out_fname = "";
1019: break;
1020:
1021: case 'p':
1022: if (!strcmp (argv[i], "-pedantic"))
1023: pedantic = 1;
1024: else if (!strcmp (argv[i], "-pedantic-errors")) {
1025: pedantic = 1;
1026: pedantic_errors = 1;
1027: } else if (!strcmp (argv[i], "-pcp")) {
1028: char *pcp_fname = argv[++i];
1029: pcp_outfile =
1030: ((pcp_fname[0] != '-' || pcp_fname[1] != '\0')
1031: ? fopen (pcp_fname, "w")
1032: : fdopen (dup (fileno (stdout)), "w"));
1033: if (pcp_outfile == 0)
1034: pfatal_with_name (pcp_fname);
1035: no_precomp = 1;
1036: }
1037: break;
1038:
1039: case 't':
1040: if (!strcmp (argv[i], "-traditional")) {
1041: traditional = 1;
1042: if (dollars_in_ident > 0)
1043: dollars_in_ident = 1;
1044: } else if (!strcmp (argv[i], "-trigraphs")) {
1045: no_trigraphs = 0;
1046: }
1047: break;
1048:
1049: case 'l':
1050: if (! strcmp (argv[i], "-lang-c"))
1051: cplusplus = 0, objc = 0;
1052: if (! strcmp (argv[i], "-lang-c++"))
1053: cplusplus = 1, objc = 0;
1054: if (! strcmp (argv[i], "-lang-objc"))
1055: objc = 1, cplusplus = 0;
1056: if (! strcmp (argv[i], "-lang-objc++"))
1057: objc = 1, cplusplus = 1;
1058: if (! strcmp (argv[i], "-lang-asm"))
1059: lang_asm = 1;
1060: if (! strcmp (argv[i], "-lint"))
1061: lint = 1;
1062: break;
1063:
1064: case '+':
1065: cplusplus = 1;
1066: break;
1067:
1068: case 'w':
1069: inhibit_warnings = 1;
1070: break;
1071:
1072: case 'W':
1073: if (!strcmp (argv[i], "-Wtrigraphs"))
1074: warn_trigraphs = 1;
1075: else if (!strcmp (argv[i], "-Wno-trigraphs"))
1076: warn_trigraphs = 0;
1077: else if (!strcmp (argv[i], "-Wcomment"))
1078: warn_comments = 1;
1079: else if (!strcmp (argv[i], "-Wno-comment"))
1080: warn_comments = 0;
1081: else if (!strcmp (argv[i], "-Wcomments"))
1082: warn_comments = 1;
1083: else if (!strcmp (argv[i], "-Wno-comments"))
1084: warn_comments = 0;
1085: else if (!strcmp (argv[i], "-Wtraditional"))
1086: warn_stringify = 1;
1087: else if (!strcmp (argv[i], "-Wno-traditional"))
1088: warn_stringify = 0;
1.1.1.2 ! root 1089: else if (!strcmp (argv[i], "-Wimport"))
! 1090: warn_import = 1;
! 1091: else if (!strcmp (argv[i], "-Wno-import"))
! 1092: warn_import = 0;
1.1 root 1093: else if (!strcmp (argv[i], "-Werror"))
1094: warnings_are_errors = 1;
1095: else if (!strcmp (argv[i], "-Wno-error"))
1096: warnings_are_errors = 0;
1097: else if (!strcmp (argv[i], "-Wall"))
1098: {
1099: warn_trigraphs = 1;
1100: warn_comments = 1;
1101: }
1102: break;
1103:
1104: case 'M':
1105: if (!strcmp (argv[i], "-M"))
1106: print_deps = 2;
1107: else if (!strcmp (argv[i], "-MM"))
1108: print_deps = 1;
1109: else if (!strcmp (argv[i], "-MD"))
1110: print_deps = 2;
1111: else if (!strcmp (argv[i], "-MMD"))
1112: print_deps = 1;
1113: /* For -MD and -MMD options, write deps on file named by next arg. */
1114: if (!strcmp (argv[i], "-MD")
1115: || !strcmp (argv[i], "-MMD")) {
1116: i++;
1117: deps_file = argv[i];
1118: deps_stream = fopen (argv[i], "a");
1119: if (deps_stream == 0)
1120: pfatal_with_name (argv[i]);
1121: } else {
1122: /* For -M and -MM, write deps on standard output
1123: and suppress the usual output. */
1124: deps_stream = stdout;
1125: inhibit_output = 1;
1126: }
1127: break;
1128:
1129: case 'd':
1130: {
1131: char *p = argv[i] + 2;
1132: char c;
1133: while (c = *p++) {
1134: /* Arg to -d specifies what parts of macros to dump */
1135: switch (c) {
1136: case 'M':
1137: dump_macros = dump_only;
1138: no_output = 1;
1139: break;
1140: case 'N':
1141: dump_macros = dump_names;
1142: break;
1143: case 'D':
1144: dump_macros = dump_definitions;
1145: break;
1146: }
1147: }
1148: }
1149: break;
1150:
1151: case 'g':
1152: if (argv[i][2] == '3')
1153: debug_output = 1;
1154: break;
1155:
1156: case 'v':
1157: fprintf (stderr, "GNU CPP version %s", version_string);
1158: #ifdef TARGET_VERSION
1159: TARGET_VERSION;
1160: #endif
1161: fprintf (stderr, "\n");
1162: break;
1163:
1164: case 'H':
1165: print_include_names = 1;
1166: break;
1167:
1168: case 'D':
1169: {
1170: char *p, *p1;
1171:
1172: if (argv[i][2] != 0)
1173: p = argv[i] + 2;
1174: else if (i + 1 == argc)
1175: fatal ("Macro name missing after -D option");
1176: else
1177: p = argv[++i];
1178:
1179: pend_defs[i] = p;
1180: }
1181: break;
1182:
1183: case 'A':
1184: {
1185: char *p, *p1;
1186:
1187: if (argv[i][2] != 0)
1188: p = argv[i] + 2;
1189: else if (i + 1 == argc)
1190: fatal ("Assertion missing after -A option");
1191: else
1192: p = argv[++i];
1193:
1194: if (!strcmp (p, "-")) {
1195: /* -A- eliminates all predefined macros and assertions.
1196: Let's include also any that were specified earlier
1197: on the command line. That way we can get rid of any
1198: that were passed automatically in from GCC. */
1199: int j;
1200: inhibit_predefs = 1;
1201: for (j = 0; j < i; j++)
1202: pend_defs[j] = pend_assertions[j] = 0;
1203: } else {
1204: pend_assertions[i] = p;
1205: pend_assertion_options[i] = "-A";
1206: }
1207: }
1208: break;
1209:
1210: case 'U': /* JF #undef something */
1211: if (argv[i][2] != 0)
1212: pend_undefs[i] = argv[i] + 2;
1213: else if (i + 1 == argc)
1214: fatal ("Macro name missing after -U option");
1215: else
1216: pend_undefs[i] = argv[i+1], i++;
1217: break;
1218:
1219: case 'C':
1220: put_out_comments = 1;
1221: break;
1222:
1223: case 'E': /* -E comes from cc -E; ignore it. */
1224: break;
1225:
1226: case 'P':
1227: no_line_commands = 1;
1228: break;
1229:
1230: case '$': /* Don't include $ in identifiers. */
1231: dollars_in_ident = 0;
1232: break;
1233:
1234: case 'I': /* Add directory to path for includes. */
1235: {
1236: struct file_name_list *dirtmp;
1237:
1238: if (! ignore_srcdir && !strcmp (argv[i] + 2, "-"))
1239: ignore_srcdir = 1;
1240: else {
1241: dirtmp = (struct file_name_list *)
1242: xmalloc (sizeof (struct file_name_list));
1243: dirtmp->next = 0; /* New one goes on the end */
1244: dirtmp->control_macro = 0;
1245: if (include == 0)
1246: include = dirtmp;
1247: else
1248: last_include->next = dirtmp;
1249: last_include = dirtmp; /* Tail follows the last one */
1250: if (argv[i][2] != 0)
1251: dirtmp->fname = argv[i] + 2;
1252: else if (i + 1 == argc)
1253: fatal ("Directory name missing after -I option");
1254: else
1255: dirtmp->fname = argv[++i];
1256: if (strlen (dirtmp->fname) > max_include_len)
1257: max_include_len = strlen (dirtmp->fname);
1258: if (ignore_srcdir && first_bracket_include == 0)
1259: first_bracket_include = dirtmp;
1260: }
1261: }
1262: break;
1263:
1264: case 'n':
1265: if (!strcmp (argv[i], "-nostdinc"))
1266: /* -nostdinc causes no default include directories.
1267: You must specify all include-file directories with -I. */
1268: no_standard_includes = 1;
1269: else if (!strcmp (argv[i], "-noprecomp"))
1270: no_precomp = 1;
1271: break;
1272:
1273: case 'u':
1274: /* Sun compiler passes undocumented switch "-undef".
1275: Let's assume it means to inhibit the predefined symbols. */
1276: inhibit_predefs = 1;
1277: break;
1278:
1279: case '\0': /* JF handle '-' as file name meaning stdin or stdout */
1280: if (in_fname == NULL) {
1281: in_fname = "";
1282: break;
1283: } else if (out_fname == NULL) {
1284: out_fname = "";
1285: break;
1286: } /* else fall through into error */
1287:
1288: default:
1289: fatal ("Invalid option `%s'", argv[i]);
1290: }
1291: }
1292: }
1293:
1294: /* Add dirs from CPATH after dirs from -I. */
1295: /* There seems to be confusion about what CPATH should do,
1296: so for the moment it is not documented. */
1297: /* Some people say that CPATH should replace the standard include dirs,
1298: but that seems pointless: it comes before them, so it overrides them
1299: anyway. */
1300: p = (char *) getenv ("CPATH");
1301: if (p != 0 && ! no_standard_includes)
1302: path_include (p);
1303:
1304: /* Now that dollars_in_ident is known, initialize is_idchar. */
1305: initialize_char_syntax ();
1306:
1307: /* Initialize output buffer */
1308:
1309: outbuf.buf = (U_CHAR *) xmalloc (OUTBUF_SIZE);
1310: outbuf.bufp = outbuf.buf;
1311: outbuf.length = OUTBUF_SIZE;
1312:
1313: /* Do partial setup of input buffer for the sake of generating
1314: early #line directives (when -g is in effect). */
1315:
1316: fp = &instack[++indepth];
1317: if (in_fname == NULL)
1318: in_fname = "";
1319: fp->nominal_fname = fp->fname = in_fname;
1320: fp->lineno = 0;
1321:
1322: /* Install __LINE__, etc. Must follow initialize_char_syntax
1323: and option processing. */
1324: initialize_builtins (fp, &outbuf);
1325:
1326: /* Do standard #defines and assertions
1327: that identify system and machine type. */
1328:
1329: if (!inhibit_predefs) {
1330: char *p = (char *) alloca (strlen (predefs) + 1);
1331: strcpy (p, predefs);
1332: while (*p) {
1333: char *q;
1334: while (*p == ' ' || *p == '\t')
1335: p++;
1336: /* Handle -D options. */
1337: if (p[0] == '-' && p[1] == 'D') {
1338: q = &p[2];
1339: while (*p && *p != ' ' && *p != '\t')
1340: p++;
1341: if (*p != 0)
1342: *p++= 0;
1343: if (debug_output)
1344: output_line_command (fp, &outbuf, 0, same_file);
1345: make_definition (q, &outbuf);
1346: while (*p == ' ' || *p == '\t')
1347: p++;
1348: } else if (p[0] == '-' && p[1] == 'A') {
1349: /* Handle -A options (assertions). */
1350: char *assertion;
1351: char *past_name;
1352: char *value;
1353: char *past_value;
1354: char *termination;
1355: int save_char;
1356:
1357: assertion = &p[2];
1358: past_name = assertion;
1359: /* Locate end of name. */
1360: while (*past_name && *past_name != ' '
1361: && *past_name != '\t' && *past_name != '(')
1362: past_name++;
1363: /* Locate `(' at start of value. */
1364: value = past_name;
1365: while (*value && (*value == ' ' || *value == '\t'))
1366: value++;
1367: if (*value++ != '(')
1368: abort ();
1369: while (*value && (*value == ' ' || *value == '\t'))
1370: value++;
1371: past_value = value;
1372: /* Locate end of value. */
1373: while (*past_value && *past_value != ' '
1374: && *past_value != '\t' && *past_value != ')')
1375: past_value++;
1376: termination = past_value;
1377: while (*termination && (*termination == ' ' || *termination == '\t'))
1378: termination++;
1379: if (*termination++ != ')')
1380: abort ();
1381: if (*termination && *termination != ' ' && *termination != '\t')
1382: abort ();
1383: /* Temporarily null-terminate the value. */
1384: save_char = *termination;
1385: *termination = '\0';
1386: /* Install the assertion. */
1387: make_assertion ("-A", assertion);
1388: *termination = (char) save_char;
1389: p = termination;
1390: while (*p == ' ' || *p == '\t')
1391: p++;
1392: } else {
1393: abort ();
1394: }
1395: }
1396: }
1397:
1398: /* Now handle the command line options. */
1399:
1400: /* Do assertions specified with -A. */
1401: for (i = 1; i < argc; i++)
1402: if (pend_assertions[i])
1403: make_assertion (pend_assertion_options[i], pend_assertions[i]);
1404:
1405: /* Do defines specified with -D. */
1406: for (i = 1; i < argc; i++)
1407: if (pend_defs[i]) {
1408: if (debug_output)
1409: output_line_command (fp, &outbuf, 0, same_file);
1410: make_definition (pend_defs[i], &outbuf);
1411: }
1412:
1413: /* Do undefines specified with -U. */
1414: for (i = 1; i < argc; i++)
1415: if (pend_undefs[i]) {
1416: if (debug_output)
1417: output_line_command (fp, &outbuf, 0, same_file);
1418: make_undef (pend_undefs[i], &outbuf);
1419: }
1420:
1421: done_initializing = 1;
1422:
1423: { /* read the appropriate environment variable and if it exists
1424: replace include_defaults with the listed path. */
1425: char *epath = 0;
1426: switch ((objc << 1) + cplusplus)
1427: {
1428: case 0:
1429: epath = getenv ("C_INCLUDE_PATH");
1430: break;
1431: case 1:
1.1.1.2 ! root 1432: epath = getenv ("CPLUS_INCLUDE_PATH");
1.1 root 1433: break;
1434: case 2:
1435: epath = getenv ("OBJC_INCLUDE_PATH");
1436: break;
1437: case 3:
1.1.1.2 ! root 1438: epath = getenv ("OBJCPLUS_INCLUDE_PATH");
1.1 root 1439: break;
1440: }
1441: /* If the environment var for this language is set,
1442: add to the default list of include directories. */
1443: if (epath) {
1444: char *nstore = (char *) alloca (strlen (epath) + 2);
1445: int num_dirs;
1446: char *startp, *endp;
1447:
1448: for (num_dirs = 1, startp = epath; *startp; startp++)
1449: if (*startp == ':')
1450: num_dirs++;
1451: include_defaults
1452: = (struct default_include *) xmalloc ((num_dirs
1453: * sizeof (struct default_include))
1454: + sizeof (include_defaults_array));
1455: startp = endp = epath;
1456: num_dirs = 0;
1457: while (1) {
1.1.1.2 ! root 1458: /* Handle cases like c:/usr/lib:d:/gcc/lib */
! 1459: if ((*endp == ':'
! 1460: #ifdef __MSDOS__
! 1461: && (endp-startp != 1 || !isalpha (*startp)))
! 1462: #endif
! 1463: )
! 1464: || (*endp == 0)) {
1.1 root 1465: strncpy (nstore, startp, endp-startp);
1466: if (endp == startp)
1467: strcpy (nstore, ".");
1468: else
1469: nstore[endp-startp] = '\0';
1470:
1471: max_include_len = MAX (max_include_len, endp-startp+2);
1472: include_defaults[num_dirs].fname = savestring (nstore);
1473: include_defaults[num_dirs].cplusplus = cplusplus;
1474: num_dirs++;
1475: if (*endp == '\0')
1476: break;
1477: endp = startp = endp + 1;
1478: } else
1479: endp++;
1480: }
1481: /* Put the usual defaults back in at the end. */
1482: bcopy (include_defaults_array, &include_defaults[num_dirs],
1483: sizeof (include_defaults_array));
1484: }
1485: }
1486:
1487: /* Unless -fnostdinc,
1488: tack on the standard include file dirs to the specified list */
1489: if (!no_standard_includes) {
1490: struct default_include *p = include_defaults;
1491: char *specd_prefix = getenv ("GCC_EXEC_PREFIX");
1492: char *default_prefix = savestring (GCC_INCLUDE_DIR);
1493: int default_len = 0;
1494: /* Remove the `include' from /usr/local/lib/gcc.../include. */
1495: if (!strcmp (default_prefix + strlen (default_prefix) - 8, "/include")) {
1496: default_len = strlen (default_prefix) - 7;
1497: default_prefix[default_len] = 0;
1498: }
1499: /* Search "translated" versions of GNU directories.
1500: These have /usr/local/lib/gcc... replaced by specd_prefix. */
1501: if (specd_prefix != 0 && default_len != 0)
1502: for (p = include_defaults; p->fname; p++) {
1503: /* Some standard dirs are only for C++. */
1504: if (!p->cplusplus || cplusplus) {
1505: /* Does this dir start with the prefix? */
1506: if (!strncmp (p->fname, default_prefix, default_len)) {
1507: /* Yes; change prefix and add to search list. */
1508: struct file_name_list *new
1509: = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
1510: int this_len = strlen (specd_prefix) + strlen (p->fname) - default_len;
1511: char *str = (char *) xmalloc (this_len + 1);
1512: strcpy (str, specd_prefix);
1513: strcat (str, p->fname + default_len);
1514: new->fname = str;
1515: new->control_macro = 0;
1516:
1517: /* Add elt to tail of list. */
1518: if (include == 0)
1519: include = new;
1520: else
1521: last_include->next = new;
1522: /* Make sure list for #include <...> also has the standard dirs. */
1523: if (ignore_srcdir && first_bracket_include == 0)
1524: first_bracket_include = new;
1525: /* Record new tail. */
1526: last_include = new;
1527: /* Update max_include_len if necessary. */
1528: if (this_len > max_include_len)
1529: max_include_len = this_len;
1530: }
1531: }
1532: }
1533: /* Search ordinary names for GNU include directories. */
1534: for (p = include_defaults; p->fname; p++) {
1535: /* Some standard dirs are only for C++. */
1536: if (!p->cplusplus || cplusplus) {
1537: struct file_name_list *new
1538: = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
1539: new->control_macro = 0;
1540: /* Add elt to tail of list. */
1541: if (include == 0)
1542: include = new;
1543: else
1544: last_include->next = new;
1545: /* Make sure list for #include <...> also has the standard dirs. */
1546: if (ignore_srcdir && first_bracket_include == 0)
1547: first_bracket_include = new;
1548: /* Record new tail. */
1549: last_include = new;
1550: new->fname = p->fname;
1551: }
1552: }
1553: }
1554:
1555: /* Tack the after_include chain at the end of the include chain. */
1556: if (last_include)
1557: last_include->next = after_include;
1558: else
1559: include = after_include;
1560: if (ignore_srcdir && first_bracket_include == 0)
1561: first_bracket_include = after_include;
1562:
1563: /* Terminate the after_include chain. */
1564: if (last_after_include)
1565: last_after_include->next = 0;
1566:
1567: /* Scan the -imacros files before the main input.
1568: Much like #including them, but with no_output set
1569: so that only their macro definitions matter. */
1570:
1571: no_output++;
1572: for (i = 1; i < argc; i++)
1573: if (pend_files[i]) {
1574: int fd = open (pend_files[i], O_RDONLY, 0666);
1575: if (fd < 0) {
1576: perror_with_name (pend_files[i]);
1577: return FAILURE_EXIT_CODE;
1578: }
1579: finclude (fd, pend_files[i], &outbuf, 0, 0);
1580: }
1581: no_output--;
1582:
1583: /* Copy the entire contents of the main input file into
1584: the stacked input buffer previously allocated for it. */
1585:
1586: /* JF check for stdin */
1587: if (in_fname == NULL || *in_fname == 0) {
1588: in_fname = "";
1589: f = 0;
1590: } else if ((f = open (in_fname, O_RDONLY, 0666)) < 0)
1591: goto perror;
1592:
1593: /* Either of two environment variables can specify output of deps.
1594: Its value is either "OUTPUT_FILE" or "OUTPUT_FILE DEPS_TARGET",
1595: where OUTPUT_FILE is the file to write deps info to
1596: and DEPS_TARGET is the target to mention in the deps. */
1597:
1598: if (print_deps == 0
1599: && (getenv ("SUNPRO_DEPENDENCIES") != 0
1600: || getenv ("DEPENDENCIES_OUTPUT") != 0)) {
1601: char *spec = getenv ("DEPENDENCIES_OUTPUT");
1602: char *s;
1603: char *output_file;
1604:
1605: if (spec == 0) {
1606: spec = getenv ("SUNPRO_DEPENDENCIES");
1607: print_deps = 2;
1608: }
1609: else
1610: print_deps = 1;
1611:
1612: s = spec;
1613: /* Find the space before the DEPS_TARGET, if there is one. */
1614: /* Don't use `index'; that causes trouble on USG. */
1615: while (*s != 0 && *s != ' ') s++;
1616: if (*s != 0) {
1617: deps_target = s + 1;
1618: output_file = (char *) xmalloc (s - spec + 1);
1619: bcopy (spec, output_file, s - spec);
1620: output_file[s - spec] = 0;
1621: }
1622: else {
1623: deps_target = 0;
1624: output_file = spec;
1625: }
1626:
1627: deps_file = output_file;
1628: deps_stream = fopen (output_file, "a");
1629: if (deps_stream == 0)
1630: pfatal_with_name (output_file);
1631: }
1632:
1633: /* For -M, print the expected object file name
1634: as the target of this Make-rule. */
1635: if (print_deps) {
1636: deps_allocated_size = 200;
1637: deps_buffer = (char *) xmalloc (deps_allocated_size);
1638: deps_buffer[0] = 0;
1639: deps_size = 0;
1640: deps_column = 0;
1641:
1642: if (deps_target) {
1643: deps_output (deps_target, 0);
1644: deps_output (":", 0);
1645: } else if (*in_fname == 0)
1646: deps_output ("-: ", 0);
1647: else {
1648: int len;
1649: char *p = in_fname;
1650: char *p1 = p;
1651: /* Discard all directory prefixes from P. */
1652: while (*p1) {
1653: if (*p1 == '/')
1654: p = p1 + 1;
1655: p1++;
1656: }
1657: /* Output P, but remove known suffixes. */
1658: len = strlen (p);
1659: if (p[len - 2] == '.' && p[len - 1] == 'c')
1660: deps_output (p, len - 2);
1661: else if (p[len - 2] == '.' && p[len - 1] == 'C')
1662: deps_output (p, len - 2);
1663: else if (p[len - 3] == '.'
1664: && p[len - 2] == 'c'
1665: && p[len - 1] == 'c')
1666: deps_output (p, len - 3);
1667: else if (p[len - 2] == '.' && p[len - 1] == 's')
1668: deps_output (p, len - 2);
1669: else if (p[len - 2] == '.' && p[len - 1] == 'S')
1670: deps_output (p, len - 2);
1671: else if (p[len - 2] == '.' && p[len - 1] == 'm')
1672: deps_output (p, len - 2);
1673: else
1674: deps_output (p, 0);
1675: /* Supply our own suffix. */
1676: deps_output (".o : ", 0);
1677: deps_output (in_fname, 0);
1678: deps_output (" ", 0);
1679: }
1680: }
1681:
1682: file_size_and_mode (f, &st_mode, &st_size);
1683: fp->nominal_fname = fp->fname = in_fname;
1684: fp->lineno = 1;
1685: fp->system_header_p = 0;
1686: /* JF all this is mine about reading pipes and ttys */
1687: if (! S_ISREG (st_mode)) {
1688: /* Read input from a file that is not a normal disk file.
1689: We cannot preallocate a buffer with the correct size,
1690: so we must read in the file a piece at the time and make it bigger. */
1691: int size;
1692: int bsize;
1693: int cnt;
1694: U_CHAR *bufp;
1695:
1696: bsize = 2000;
1697: size = 0;
1698: fp->buf = (U_CHAR *) xmalloc (bsize + 2);
1699: bufp = fp->buf;
1700: for (;;) {
1701: cnt = read (f, bufp, bsize - size);
1702: if (cnt < 0) goto perror; /* error! */
1703: if (cnt == 0) break; /* End of file */
1704: size += cnt;
1705: bufp += cnt;
1706: if (bsize == size) { /* Buffer is full! */
1707: bsize *= 2;
1708: fp->buf = (U_CHAR *) xrealloc (fp->buf, bsize + 2);
1709: bufp = fp->buf + size; /* May have moved */
1710: }
1711: }
1712: fp->length = size;
1713: } else {
1714: /* Read a file whose size we can determine in advance.
1715: For the sake of VMS, st_size is just an upper bound. */
1716: long i;
1717: fp->length = 0;
1718: fp->buf = (U_CHAR *) xmalloc (st_size + 2);
1719:
1720: while (st_size > 0) {
1721: i = read (f, fp->buf + fp->length, st_size);
1722: if (i <= 0) {
1723: if (i == 0) break;
1724: goto perror;
1725: }
1726: fp->length += i;
1727: st_size -= i;
1728: }
1729: }
1730: fp->bufp = fp->buf;
1731: fp->if_stack = if_stack;
1732:
1733: /* Make sure data ends with a newline. And put a null after it. */
1734:
1735: if ((fp->length > 0 && fp->buf[fp->length - 1] != '\n')
1736: /* Backslash-newline at end is not good enough. */
1737: || (fp->length > 1 && fp->buf[fp->length - 2] == '\\')) {
1738: fp->buf[fp->length++] = '\n';
1739: missing_newline = 1;
1740: }
1741: fp->buf[fp->length] = '\0';
1742:
1743: /* Unless inhibited, convert trigraphs in the input. */
1744:
1745: if (!no_trigraphs)
1746: trigraph_pcp (fp);
1747:
1748: /* Now that we know the input file is valid, open the output. */
1749:
1750: if (!out_fname || !strcmp (out_fname, ""))
1751: out_fname = "stdout";
1752: else if (! freopen (out_fname, "w", stdout))
1753: pfatal_with_name (out_fname);
1754:
1755: output_line_command (fp, &outbuf, 0, same_file);
1756:
1757: /* Scan the -include files before the main input. */
1758:
1759: for (i = 1; i < argc; i++)
1760: if (pend_includes[i]) {
1761: int fd = open (pend_includes[i], O_RDONLY, 0666);
1762: if (fd < 0) {
1763: perror_with_name (pend_includes[i]);
1764: return FAILURE_EXIT_CODE;
1765: }
1766: finclude (fd, pend_includes[i], &outbuf, 0, 0);
1767: }
1768:
1769: /* Scan the input, processing macros and directives. */
1770:
1771: rescan (&outbuf, 0);
1772:
1773: if (pedantic && missing_newline)
1774: pedwarn ("file does not end in newline");
1775:
1776: /* Now we have processed the entire input
1777: Write whichever kind of output has been requested. */
1778:
1779: if (dump_macros == dump_only)
1780: dump_all_macros ();
1781: else if (! inhibit_output) {
1782: write_output ();
1783: }
1784:
1785: if (print_deps) {
1786: /* Don't actually write the deps file if compilation has failed.
1787: Delete it instead. */
1788: if (errors > 0 && deps_file != 0)
1789: unlink (deps_file);
1790: else {
1791: fputs (deps_buffer, deps_stream);
1792: putc ('\n', deps_stream);
1793: if (deps_stream != stdout) {
1794: fclose (deps_stream);
1795: if (ferror (deps_stream))
1796: fatal ("I/O error on output");
1797: }
1798: }
1799: }
1800:
1801: if (ferror (stdout))
1802: fatal ("I/O error on output");
1803:
1804: if (errors)
1805: exit (FAILURE_EXIT_CODE);
1806: exit (SUCCESS_EXIT_CODE);
1807:
1808: perror:
1809: pfatal_with_name (in_fname);
1810: return 0;
1811: }
1812:
1813: /* Given a colon-separated list of file names PATH,
1814: add all the names to the search path for include files. */
1815:
1816: static void
1817: path_include (path)
1818: char *path;
1819: {
1820: char *p;
1821:
1822: p = path;
1823:
1824: if (*p)
1825: while (1) {
1826: char *q = p;
1827: char *name;
1828: struct file_name_list *dirtmp;
1829:
1830: /* Find the end of this name. */
1.1.1.2 ! root 1831: #ifdef __MSDOS__
! 1832: /* Handle cases like c:/usr/lib:d:/gcc/lib */
! 1833: while (*q != 0 && (*q != ':' || (q - p == 1 && isalpha (*p)))) q++;
! 1834: #else
1.1 root 1835: while (*q != 0 && *q != ':') q++;
1.1.1.2 ! root 1836: #endif
1.1 root 1837: if (p == q) {
1838: /* An empty name in the path stands for the current directory. */
1839: name = (char *) xmalloc (2);
1840: name[0] = '.';
1841: name[1] = 0;
1842: } else {
1843: /* Otherwise use the directory that is named. */
1844: name = (char *) xmalloc (q - p + 1);
1845: bcopy (p, name, q - p);
1846: name[q - p] = 0;
1847: }
1848:
1849: dirtmp = (struct file_name_list *)
1850: xmalloc (sizeof (struct file_name_list));
1851: dirtmp->next = 0; /* New one goes on the end */
1852: dirtmp->control_macro = 0;
1853: if (include == 0)
1854: include = dirtmp;
1855: else
1856: last_include->next = dirtmp;
1857: last_include = dirtmp; /* Tail follows the last one */
1858: dirtmp->fname = name;
1859: if (strlen (dirtmp->fname) > max_include_len)
1860: max_include_len = strlen (dirtmp->fname);
1861: if (ignore_srcdir && first_bracket_include == 0)
1862: first_bracket_include = dirtmp;
1863:
1864: /* Advance past this name. */
1865: p = q;
1866: if (*p == 0)
1867: break;
1868: /* Skip the colon. */
1869: p++;
1870: }
1871: }
1872:
1873: /* Pre-C-Preprocessor to translate ANSI trigraph idiocy in BUF
1874: before main CCCP processing. Name `pcp' is also in honor of the
1875: drugs the trigraph designers must have been on.
1876:
1877: Using an extra pass through the buffer takes a little extra time,
1878: but is infinitely less hairy than trying to handle trigraphs inside
1879: strings, etc. everywhere, and also makes sure that trigraphs are
1880: only translated in the top level of processing. */
1881:
1882: static void
1883: trigraph_pcp (buf)
1884: FILE_BUF *buf;
1885: {
1886: register U_CHAR c, *fptr, *bptr, *sptr;
1887: int len;
1888:
1889: fptr = bptr = sptr = buf->buf;
1890: while ((sptr = (U_CHAR *) index (sptr, '?')) != NULL) {
1891: if (*++sptr != '?')
1892: continue;
1893: switch (*++sptr) {
1894: case '=':
1895: c = '#';
1896: break;
1897: case '(':
1898: c = '[';
1899: break;
1900: case '/':
1901: c = '\\';
1902: break;
1903: case ')':
1904: c = ']';
1905: break;
1906: case '\'':
1907: c = '^';
1908: break;
1909: case '<':
1910: c = '{';
1911: break;
1912: case '!':
1913: c = '|';
1914: break;
1915: case '>':
1916: c = '}';
1917: break;
1918: case '-':
1919: c = '~';
1920: break;
1921: case '?':
1922: sptr--;
1923: continue;
1924: default:
1925: continue;
1926: }
1927: len = sptr - fptr - 2;
1928: if (bptr != fptr && len > 0)
1929: bcopy (fptr, bptr, len); /* BSD doc says bcopy () works right
1930: for overlapping strings. In ANSI
1931: C, this will be memmove (). */
1932: bptr += len;
1933: *bptr++ = c;
1934: fptr = ++sptr;
1935: }
1936: len = buf->length - (fptr - buf->buf);
1937: if (bptr != fptr && len > 0)
1938: bcopy (fptr, bptr, len);
1939: buf->length -= fptr - bptr;
1940: buf->buf[buf->length] = '\0';
1941: if (warn_trigraphs && fptr != bptr)
1942: warning ("%d trigraph(s) encountered", (fptr - bptr) / 2);
1943: }
1944:
1945: /* Move all backslash-newline pairs out of embarrassing places.
1946: Exchange all such pairs following BP
1.1.1.2 ! root 1947: with any potentially-embarrassing characters that follow them.
1.1 root 1948: Potentially-embarrassing characters are / and *
1949: (because a backslash-newline inside a comment delimiter
1950: would cause it not to be recognized). */
1951:
1952: static void
1953: newline_fix (bp)
1954: U_CHAR *bp;
1955: {
1956: register U_CHAR *p = bp;
1957: register int count = 0;
1958:
1959: /* First count the backslash-newline pairs here. */
1960:
1961: while (1) {
1962: if (p[0] == '\\') {
1963: if (p[1] == '\n')
1964: p += 2, count++;
1965: else if (p[1] == '\r' && p[2] == '\n')
1966: p += 3, count++;
1967: else
1968: break;
1969: } else
1970: break;
1971: }
1972:
1973: /* What follows the backslash-newlines is not embarrassing. */
1974:
1975: if (count == 0 || (*p != '/' && *p != '*'))
1976: return;
1977:
1978: /* Copy all potentially embarrassing characters
1979: that follow the backslash-newline pairs
1980: down to where the pairs originally started. */
1981:
1982: while (*p == '*' || *p == '/')
1983: *bp++ = *p++;
1984:
1985: /* Now write the same number of pairs after the embarrassing chars. */
1986: while (count-- > 0) {
1987: *bp++ = '\\';
1988: *bp++ = '\n';
1989: }
1990: }
1991:
1992: /* Like newline_fix but for use within a directive-name.
1993: Move any backslash-newlines up past any following symbol constituents. */
1994:
1995: static void
1996: name_newline_fix (bp)
1997: U_CHAR *bp;
1998: {
1999: register U_CHAR *p = bp;
2000: register int count = 0;
2001:
2002: /* First count the backslash-newline pairs here. */
2003: while (1) {
2004: if (p[0] == '\\') {
2005: if (p[1] == '\n')
2006: p += 2, count++;
2007: else if (p[1] == '\r' && p[2] == '\n')
2008: p += 3, count++;
2009: else
2010: break;
2011: } else
2012: break;
2013: }
2014:
2015: /* What follows the backslash-newlines is not embarrassing. */
2016:
2017: if (count == 0 || !is_idchar[*p])
2018: return;
2019:
2020: /* Copy all potentially embarrassing characters
2021: that follow the backslash-newline pairs
2022: down to where the pairs originally started. */
2023:
2024: while (is_idchar[*p])
2025: *bp++ = *p++;
2026:
2027: /* Now write the same number of pairs after the embarrassing chars. */
2028: while (count-- > 0) {
2029: *bp++ = '\\';
2030: *bp++ = '\n';
2031: }
2032: }
2033:
2034: /* Look for lint commands in comments.
2035:
2036: When we come in here, ibp points into a comment. Limit is as one expects.
2037: scan within the comment -- it should start, after lwsp, with a lint command.
2038: If so that command is returned as a (constant) string.
2039:
2040: Upon return, any arg will be pointed to with argstart and will be
2041: arglen long. Note that we don't parse that arg since it will just
2042: be printed out again.
2043: */
2044:
2045: static char *
2046: get_lintcmd (ibp, limit, argstart, arglen, cmdlen)
2047: register U_CHAR *ibp;
2048: register U_CHAR *limit;
2049: U_CHAR **argstart; /* point to command arg */
2050: int *arglen, *cmdlen; /* how long they are */
2051: {
2052: long linsize;
2053: register U_CHAR *numptr; /* temp for arg parsing */
2054:
2055: *arglen = 0;
2056:
2057: SKIP_WHITE_SPACE (ibp);
2058:
2059: if (ibp >= limit) return NULL;
2060:
2061: linsize = limit - ibp;
2062:
2063: /* Oh, I wish C had lexical functions... hell, I'll just open-code the set */
2064: if ((linsize >= 10) && !strncmp (ibp, "NOTREACHED", 10)) {
2065: *cmdlen = 10;
2066: return "NOTREACHED";
2067: }
2068: if ((linsize >= 8) && !strncmp (ibp, "ARGSUSED", 8)) {
2069: *cmdlen = 8;
2070: return "ARGSUSED";
2071: }
2072: if ((linsize >= 11) && !strncmp (ibp, "LINTLIBRARY", 8)) {
2073: *cmdlen = 8;
2074: return "LINTLIBRARY";
2075: }
2076: if ((linsize >= 7) && !strncmp (ibp, "VARARGS", 7)) {
2077: *cmdlen = 7;
2078: ibp += 7; linsize -= 7;
2079: if ((linsize == 0) || ! isdigit (*ibp)) return "VARARGS";
2080:
2081: /* OK, read a number */
2082: for (numptr = *argstart = ibp; (numptr < limit) && isdigit (*numptr);
2083: numptr++);
2084: *arglen = numptr - *argstart;
2085: return "VARARGS";
2086: }
2087: return NULL;
2088: }
2089:
2090: /*
2091: * The main loop of the program.
2092: *
2093: * Read characters from the input stack, transferring them to the
2094: * output buffer OP.
2095: *
2096: * Macros are expanded and push levels on the input stack.
2097: * At the end of such a level it is popped off and we keep reading.
2098: * At the end of any other kind of level, we return.
2099: * #-directives are handled, except within macros.
2100: *
2101: * If OUTPUT_MARKS is nonzero, keep Newline markers found in the input
2102: * and insert them when appropriate. This is set while scanning macro
2103: * arguments before substitution. It is zero when scanning for final output.
2104: * There are three types of Newline markers:
2105: * * Newline - follows a macro name that was not expanded
2106: * because it appeared inside an expansion of the same macro.
2107: * This marker prevents future expansion of that identifier.
2108: * When the input is rescanned into the final output, these are deleted.
2109: * These are also deleted by ## concatenation.
2110: * * Newline Space (or Newline and any other whitespace character)
2111: * stands for a place that tokens must be separated or whitespace
2112: * is otherwise desirable, but where the ANSI standard specifies there
2113: * is no whitespace. This marker turns into a Space (or whichever other
2114: * whitespace char appears in the marker) in the final output,
2115: * but it turns into nothing in an argument that is stringified with #.
2116: * Such stringified arguments are the only place where the ANSI standard
2117: * specifies with precision that whitespace may not appear.
2118: *
2119: * During this function, IP->bufp is kept cached in IBP for speed of access.
2120: * Likewise, OP->bufp is kept in OBP. Before calling a subroutine
2121: * IBP, IP and OBP must be copied back to memory. IP and IBP are
2122: * copied back with the RECACHE macro. OBP must be copied back from OP->bufp
2123: * explicitly, and before RECACHE, since RECACHE uses OBP.
2124: */
2125:
2126: static void
2127: rescan (op, output_marks)
2128: FILE_BUF *op;
2129: int output_marks;
2130: {
2131: /* Character being scanned in main loop. */
2132: register U_CHAR c;
2133:
2134: /* Length of pending accumulated identifier. */
2135: register int ident_length = 0;
2136:
2137: /* Hash code of pending accumulated identifier. */
2138: register int hash = 0;
2139:
2140: /* Current input level (&instack[indepth]). */
2141: FILE_BUF *ip;
2142:
2143: /* Pointer for scanning input. */
2144: register U_CHAR *ibp;
2145:
2146: /* Pointer to end of input. End of scan is controlled by LIMIT. */
2147: register U_CHAR *limit;
2148:
2149: /* Pointer for storing output. */
2150: register U_CHAR *obp;
2151:
2152: /* REDO_CHAR is nonzero if we are processing an identifier
2153: after backing up over the terminating character.
2154: Sometimes we process an identifier without backing up over
2155: the terminating character, if the terminating character
2156: is not special. Backing up is done so that the terminating character
2157: will be dispatched on again once the identifier is dealt with. */
2158: int redo_char = 0;
2159:
2160: /* 1 if within an identifier inside of which a concatenation
2161: marker (Newline -) has been seen. */
2162: int concatenated = 0;
2163:
2164: /* While scanning a comment or a string constant,
2165: this records the line it started on, for error messages. */
2166: int start_line;
2167:
2168: /* Line where a newline was first seen in a string constant. */
2169: int multiline_string_line = 0;
2170:
2171: /* Record position of last `real' newline. */
2172: U_CHAR *beg_of_line;
2173:
2174: /* Pop the innermost input stack level, assuming it is a macro expansion. */
2175:
2176: #define POPMACRO \
2177: do { ip->macro->type = T_MACRO; \
2178: if (ip->free_ptr) free (ip->free_ptr); \
2179: --indepth; } while (0)
2180:
2181: /* Reload `rescan's local variables that describe the current
2182: level of the input stack. */
2183:
2184: #define RECACHE \
2185: do { ip = &instack[indepth]; \
2186: ibp = ip->bufp; \
2187: limit = ip->buf + ip->length; \
2188: op->bufp = obp; \
2189: check_expand (op, limit - ibp); \
2190: beg_of_line = 0; \
2191: obp = op->bufp; } while (0)
2192:
2193: if (no_output && instack[indepth].fname != 0)
2194: skip_if_group (&instack[indepth], 1);
2195:
2196: obp = op->bufp;
2197: RECACHE;
2198: beg_of_line = ibp;
2199:
2200: /* Our caller must always put a null after the end of
2201: the input at each input stack level. */
2202: if (*limit != 0)
2203: abort ();
2204:
2205: while (1) {
2206: c = *ibp++;
2207: *obp++ = c;
2208:
2209: switch (c) {
2210: case '\\':
2211: if (ibp >= limit)
2212: break;
2213: if (*ibp == '\n') {
2214: /* Always merge lines ending with backslash-newline,
2215: even in middle of identifier. */
2216: ++ibp;
2217: ++ip->lineno;
2218: --obp; /* remove backslash from obuf */
2219: break;
2220: }
2221: /* Otherwise, backslash suppresses specialness of following char,
2222: so copy it here to prevent the switch from seeing it.
2223: But first get any pending identifier processed. */
2224: if (ident_length > 0)
2225: goto specialchar;
2226: *obp++ = *ibp++;
2227: break;
2228:
2229: case '#':
2230: if (assertions_flag) {
2231: /* Copy #foo (bar lose) without macro expansion. */
2232: SKIP_WHITE_SPACE (ibp);
2233: while (is_idchar[*ibp])
2234: *obp++ = *ibp++;
2235: SKIP_WHITE_SPACE (ibp);
2236: if (*ibp == '(') {
2237: ip->bufp = ibp;
2238: skip_paren_group (ip);
2239: bcopy (ibp, obp, ip->bufp - ibp);
2240: obp += ip->bufp - ibp;
2241: ibp = ip->bufp;
2242: }
2243: }
2244:
2245: /* If this is expanding a macro definition, don't recognize
2246: preprocessor directives. */
2247: if (ip->macro != 0)
2248: goto randomchar;
2249: if (ident_length)
2250: goto specialchar;
2251:
2252: /* # keyword: a # must be first nonblank char on the line */
2253: if (beg_of_line == 0)
2254: goto randomchar;
2255: {
2256: U_CHAR *bp;
2257:
2258: /* Scan from start of line, skipping whitespace, comments
2259: and backslash-newlines, and see if we reach this #.
2260: If not, this # is not special. */
2261: bp = beg_of_line;
2262: while (1) {
2263: if (is_hor_space[*bp])
2264: bp++;
2265: else if (*bp == '\\' && bp[1] == '\n')
2266: bp += 2;
2267: else if (*bp == '/' && bp[1] == '*') {
2268: bp += 2;
2269: while (!(*bp == '*' && bp[1] == '/'))
2270: bp++;
2271: bp += 2;
2272: }
2273: else if ((cplusplus || objc) && *bp == '/' && bp[1] == '/') {
2274: bp += 2;
2275: while (*bp++ != '\n') ;
2276: }
2277: else break;
2278: }
2279: if (bp + 1 != ibp)
2280: goto randomchar;
2281: }
2282:
2283: /* This # can start a directive. */
2284:
2285: --obp; /* Don't copy the '#' */
2286:
2287: ip->bufp = ibp;
2288: op->bufp = obp;
2289: if (! handle_directive (ip, op)) {
2290: #ifdef USE_C_ALLOCA
2291: alloca (0);
2292: #endif
2293: /* Not a known directive: treat it as ordinary text.
2294: IP, OP, IBP, etc. have not been changed. */
2295: if (no_output && instack[indepth].fname) {
2296: /* If not generating expanded output,
2297: what we do with ordinary text is skip it.
2298: Discard everything until next # directive. */
2299: skip_if_group (&instack[indepth], 1);
2300: RECACHE;
2301: beg_of_line = ibp;
2302: break;
2303: }
2304: ++obp; /* Copy the '#' after all */
2305: goto randomchar;
2306: }
2307: #ifdef USE_C_ALLOCA
2308: alloca (0);
2309: #endif
2310: /* A # directive has been successfully processed. */
2311: /* If not generating expanded output, ignore everything until
2312: next # directive. */
2313: if (no_output && instack[indepth].fname)
2314: skip_if_group (&instack[indepth], 1);
2315: obp = op->bufp;
2316: RECACHE;
2317: beg_of_line = ibp;
2318: break;
2319:
2320: case '\"': /* skip quoted string */
2321: case '\'':
2322: /* A single quoted string is treated like a double -- some
2323: programs (e.g., troff) are perverse this way */
2324:
2325: if (ident_length)
2326: goto specialchar;
2327:
2328: start_line = ip->lineno;
2329:
2330: /* Skip ahead to a matching quote. */
2331:
2332: while (1) {
2333: if (ibp >= limit) {
2334: if (traditional) {
2335: if (ip->macro != 0) {
2336: /* try harder: this string crosses a macro expansion boundary */
2337: POPMACRO;
2338: RECACHE;
2339: continue;
2340: }
2341: } else {
2342: error_with_line (line_for_error (start_line),
2343: "unterminated string or character constant");
2344: error_with_line (multiline_string_line,
2345: "possible real start of unterminated constant");
2346: multiline_string_line = 0;
2347: }
2348: break;
2349: }
2350: *obp++ = *ibp;
2351: switch (*ibp++) {
2352: case '\n':
2353: ++ip->lineno;
2354: ++op->lineno;
2355: /* Traditionally, end of line ends a string constant with no error.
2356: So exit the loop and record the new line. */
2357: if (traditional) {
2358: beg_of_line = ibp;
2359: goto while2end;
2360: }
2361: if (pedantic || c == '\'') {
2362: error_with_line (line_for_error (start_line),
2363: "unterminated string or character constant");
2364: goto while2end;
2365: }
2366: if (multiline_string_line == 0)
2367: multiline_string_line = ip->lineno - 1;
2368: break;
2369:
2370: case '\\':
2371: if (ibp >= limit)
2372: break;
2373: if (*ibp == '\n') {
2374: /* Backslash newline is replaced by nothing at all,
2375: but keep the line counts correct. */
2376: --obp;
2377: ++ibp;
2378: ++ip->lineno;
2379: } else {
2380: /* ANSI stupidly requires that in \\ the second \
2381: is *not* prevented from combining with a newline. */
2382: while (*ibp == '\\' && ibp[1] == '\n') {
2383: ibp += 2;
2384: ++ip->lineno;
2385: }
2386: *obp++ = *ibp++;
2387: }
2388: break;
2389:
2390: case '\"':
2391: case '\'':
2392: if (ibp[-1] == c)
2393: goto while2end;
2394: break;
2395: }
2396: }
2397: while2end:
2398: break;
2399:
2400: case '/':
2401: if (*ibp == '\\' && ibp[1] == '\n')
2402: newline_fix (ibp);
2403:
2404: if (*ibp != '*'
2405: && !((cplusplus || objc) && *ibp == '/'))
2406: goto randomchar;
2407: if (ip->macro != 0)
2408: goto randomchar;
2409: if (ident_length)
2410: goto specialchar;
2411:
2412: if (*ibp == '/') {
2413: /* C++ style comment... */
2414: start_line = ip->lineno;
2415:
2416: --ibp; /* Back over the slash */
2417: --obp;
2418:
2419: /* Comments are equivalent to spaces. */
2420: if (! put_out_comments)
2421: *obp++ = ' ';
2422: else {
2423: /* must fake up a comment here */
2424: *obp++ = '/';
2425: *obp++ = '/';
2426: }
2427: {
2428: U_CHAR *before_bp = ibp+2;
2429:
2430: while (ibp < limit) {
2431: if (*ibp++ == '\n') {
2432: ibp--;
2433: if (put_out_comments) {
2434: bcopy (before_bp, obp, ibp - before_bp);
2435: obp += ibp - before_bp;
2436: }
2437: break;
2438: }
2439: }
2440: break;
2441: }
2442: }
2443:
2444: /* Ordinary C comment. Skip it, optionally copying it to output. */
2445:
2446: start_line = ip->lineno;
2447:
2448: ++ibp; /* Skip the star. */
2449:
2450: /* If this cpp is for lint, we peek inside the comments: */
2451: if (lint) {
2452: U_CHAR *argbp;
2453: int cmdlen, arglen;
2454: char *lintcmd = get_lintcmd (ibp, limit, &argbp, &arglen, &cmdlen);
2455:
2456: if (lintcmd != NULL) {
2457: /* I believe it is always safe to emit this newline: */
2458: obp[-1] = '\n';
2459: bcopy ("#pragma lint ", obp, 13);
2460: obp += 13;
2461: bcopy (lintcmd, obp, cmdlen);
2462: obp += cmdlen;
2463:
2464: if (arglen != 0) {
2465: *(obp++) = ' ';
2466: bcopy (argbp, obp, arglen);
2467: obp += arglen;
2468: }
2469:
2470: /* OK, now bring us back to the state we were in before we entered
2471: this branch. We need #line b/c the newline for the pragma
2472: could fuck things up. */
2473: output_line_command (ip, op, 0, same_file);
2474: *(obp++) = ' '; /* just in case, if comments are copied thru */
2475: *(obp++) = '/';
2476: }
2477: }
2478:
2479: /* Comments are equivalent to spaces.
2480: Note that we already output the slash; we might not want it.
2481: For -traditional, a comment is equivalent to nothing. */
2482: if (! put_out_comments) {
2483: if (traditional)
2484: obp--;
2485: else
2486: obp[-1] = ' ';
2487: }
2488: else
2489: *obp++ = '*';
2490:
2491: {
2492: U_CHAR *before_bp = ibp;
2493:
2494: while (ibp < limit) {
2495: switch (*ibp++) {
2496: case '/':
2497: if (warn_comments && ibp < limit && *ibp == '*')
2498: warning("`/*' within comment");
2499: break;
2500: case '*':
2501: if (*ibp == '\\' && ibp[1] == '\n')
2502: newline_fix (ibp);
2503: if (ibp >= limit || *ibp == '/')
2504: goto comment_end;
2505: break;
2506: case '\n':
2507: ++ip->lineno;
2508: /* Copy the newline into the output buffer, in order to
2509: avoid the pain of a #line every time a multiline comment
2510: is seen. */
2511: if (!put_out_comments)
2512: *obp++ = '\n';
2513: ++op->lineno;
2514: }
2515: }
2516: comment_end:
2517:
2518: if (ibp >= limit)
2519: error_with_line (line_for_error (start_line),
2520: "unterminated comment");
2521: else {
2522: ibp++;
2523: if (put_out_comments) {
2524: bcopy (before_bp, obp, ibp - before_bp);
2525: obp += ibp - before_bp;
2526: }
2527: }
2528: }
2529: break;
2530:
2531: case '$':
2532: if (!dollars_in_ident)
2533: goto randomchar;
2534: goto letter;
2535:
2536: case '0': case '1': case '2': case '3': case '4':
2537: case '5': case '6': case '7': case '8': case '9':
2538: /* If digit is not part of identifier, it starts a number,
2539: which means that following letters are not an identifier.
2540: "0x5" does not refer to an identifier "x5".
2541: So copy all alphanumerics that follow without accumulating
2542: as an identifier. Periods also, for sake of "3.e7". */
2543:
2544: if (ident_length == 0) {
2545: while (ibp < limit) {
2546: while (ibp < limit && ibp[0] == '\\' && ibp[1] == '\n') {
2547: ++ip->lineno;
2548: ibp += 2;
2549: }
2550: c = *ibp++;
2551: /* ".." terminates a preprocessing number. This is useless for C
2552: code but useful for preprocessing other things. */
2553: if (!isalnum (c) && (c != '.' || *ibp == '.') && c != '_') {
2554: --ibp;
2555: break;
2556: }
2557: *obp++ = c;
2558: /* A sign can be part of a preprocessing number
2559: if it follows an e. */
2560: if (c == 'e' || c == 'E') {
2561: while (ibp < limit && ibp[0] == '\\' && ibp[1] == '\n') {
2562: ++ip->lineno;
2563: ibp += 2;
2564: }
2565: if (ibp < limit && (*ibp == '+' || *ibp == '-')) {
2566: *obp++ = *ibp++;
2567: /* But traditional C does not let the token go past the sign. */
2568: if (traditional)
2569: break;
2570: }
2571: }
2572: }
2573: break;
2574: }
2575: /* fall through */
2576:
2577: case '_':
2578: case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
2579: case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
2580: case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
2581: case 's': case 't': case 'u': case 'v': case 'w': case 'x':
2582: case 'y': case 'z':
2583: case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
2584: case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
2585: case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
2586: case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
2587: case 'Y': case 'Z':
2588: letter:
2589: ident_length++;
2590: /* Compute step of hash function, to avoid a proc call on every token */
2591: hash = HASHSTEP (hash, c);
2592: break;
2593:
2594: case '\n':
2595: /* If reprocessing a macro expansion, newline is a special marker. */
2596: if (ip->macro != 0) {
2597: /* Newline White is a "funny space" to separate tokens that are
2598: supposed to be separate but without space between.
2599: Here White means any whitespace character.
2600: Newline - marks a recursive macro use that is not
2601: supposed to be expandable. */
2602:
2603: if (*ibp == '-') {
2604: /* Newline - inhibits expansion of preceding token.
2605: If expanding a macro arg, we keep the newline -.
2606: In final output, it is deleted. */
2607: if (! concatenated) {
2608: ident_length = 0;
2609: hash = 0;
2610: }
2611: ibp++;
2612: if (!output_marks) {
2613: obp--;
2614: } else {
2615: /* If expanding a macro arg, keep the newline -. */
2616: *obp++ = '-';
2617: }
2618: } else if (is_space[*ibp]) {
2619: /* Newline Space does not prevent expansion of preceding token
2620: so expand the preceding token and then come back. */
2621: if (ident_length > 0)
2622: goto specialchar;
2623:
2624: /* If generating final output, newline space makes a space. */
2625: if (!output_marks) {
2626: obp[-1] = *ibp++;
2627: /* And Newline Newline makes a newline, so count it. */
2628: if (obp[-1] == '\n')
2629: op->lineno++;
2630: } else {
2631: /* If expanding a macro arg, keep the newline space.
2632: If the arg gets stringified, newline space makes nothing. */
2633: *obp++ = *ibp++;
2634: }
2635: } else abort (); /* Newline followed by something random? */
2636: break;
2637: }
2638:
2639: /* If there is a pending identifier, handle it and come back here. */
2640: if (ident_length > 0)
2641: goto specialchar;
2642:
2643: beg_of_line = ibp;
2644:
2645: /* Update the line counts and output a #line if necessary. */
2646: ++ip->lineno;
2647: ++op->lineno;
2648: if (ip->lineno != op->lineno) {
2649: op->bufp = obp;
2650: output_line_command (ip, op, 1, same_file);
2651: check_expand (op, ip->length - (ip->bufp - ip->buf));
2652: obp = op->bufp;
2653: }
2654: break;
2655:
2656: /* Come here either after (1) a null character that is part of the input
2657: or (2) at the end of the input, because there is a null there. */
2658: case 0:
2659: if (ibp <= limit)
2660: /* Our input really contains a null character. */
2661: goto randomchar;
2662:
2663: /* At end of a macro-expansion level, pop it and read next level. */
2664: if (ip->macro != 0) {
2665: obp--;
2666: ibp--;
2667: /* If traditional, and we have an identifier that ends here,
2668: process it now, so we get the right error for recursion. */
2669: if (traditional && ident_length
2670: && ! is_idchar[*instack[indepth - 1].bufp]) {
2671: redo_char = 1;
2672: goto randomchar;
2673: }
2674: POPMACRO;
2675: RECACHE;
2676: break;
2677: }
2678:
2679: /* If we don't have a pending identifier,
2680: return at end of input. */
2681: if (ident_length == 0) {
2682: obp--;
2683: ibp--;
2684: op->bufp = obp;
2685: ip->bufp = ibp;
2686: goto ending;
2687: }
2688:
2689: /* If we do have a pending identifier, just consider this null
2690: a special character and arrange to dispatch on it again.
2691: The second time, IDENT_LENGTH will be zero so we will return. */
2692:
2693: /* Fall through */
2694:
2695: specialchar:
2696:
2697: /* Handle the case of a character such as /, ', " or null
2698: seen following an identifier. Back over it so that
2699: after the identifier is processed the special char
2700: will be dispatched on again. */
2701:
2702: ibp--;
2703: obp--;
2704: redo_char = 1;
2705:
2706: default:
2707:
2708: randomchar:
2709:
2710: if (ident_length > 0) {
2711: register HASHNODE *hp;
2712:
2713: /* We have just seen an identifier end. If it's a macro, expand it.
2714:
2715: IDENT_LENGTH is the length of the identifier
2716: and HASH is its hash code.
2717:
2718: The identifier has already been copied to the output,
2719: so if it is a macro we must remove it.
2720:
2721: If REDO_CHAR is 0, the char that terminated the identifier
2722: has been skipped in the output and the input.
2723: OBP-IDENT_LENGTH-1 points to the identifier.
2724: If the identifier is a macro, we must back over the terminator.
2725:
2726: If REDO_CHAR is 1, the terminating char has already been
2727: backed over. OBP-IDENT_LENGTH points to the identifier. */
2728:
2729: if (!pcp_outfile || pcp_inside_if) {
2730: startagain:
2731: for (hp = hashtab[MAKE_POS (hash) % HASHSIZE]; hp != NULL;
2732: hp = hp->next) {
2733:
2734: if (hp->length == ident_length) {
2735: int obufp_before_macroname;
2736: int op_lineno_before_macroname;
2737: register int i = ident_length;
2738: register U_CHAR *p = hp->name;
2739: register U_CHAR *q = obp - i;
2740: int disabled;
2741:
2742: if (! redo_char)
2743: q--;
2744:
2745: do { /* All this to avoid a strncmp () */
2746: if (*p++ != *q++)
2747: goto hashcollision;
2748: } while (--i);
2749:
2750: /* We found a use of a macro name.
2751: see if the context shows it is a macro call. */
2752:
2753: /* Back up over terminating character if not already done. */
2754: if (! redo_char) {
2755: ibp--;
2756: obp--;
2757: }
2758:
2759: /* Save this as a displacement from the beginning of the output
2760: buffer. We can not save this as a position in the output
2761: buffer, because it may get realloc'ed by RECACHE. */
2762: obufp_before_macroname = (obp - op->buf) - ident_length;
2763: op_lineno_before_macroname = op->lineno;
2764:
2765: if (hp->type == T_PCSTRING) {
2766: pcstring_used (hp); /* Mark the definition of this key
2767: as needed, ensuring that it
2768: will be output. */
2769: break; /* Exit loop, since the key cannot have a
2770: definition any longer. */
2771: }
2772:
2773: /* Record whether the macro is disabled. */
2774: disabled = hp->type == T_DISABLED;
2775:
2776: /* This looks like a macro ref, but if the macro was disabled,
2777: just copy its name and put in a marker if requested. */
2778:
2779: if (disabled) {
2780: #if 0
2781: /* This error check caught useful cases such as
2782: #define foo(x,y) bar(x(y,0), y)
2783: foo(foo, baz) */
2784: if (traditional)
2785: error ("recursive use of macro `%s'", hp->name);
2786: #endif
2787:
2788: if (output_marks) {
2789: check_expand (op, limit - ibp + 2);
2790: *obp++ = '\n';
2791: *obp++ = '-';
2792: }
2793: break;
2794: }
2795:
2796: /* If macro wants an arglist, verify that a '(' follows.
2797: first skip all whitespace, copying it to the output
2798: after the macro name. Then, if there is no '(',
2799: decide this is not a macro call and leave things that way. */
2800: if ((hp->type == T_MACRO || hp->type == T_DISABLED)
2801: && hp->value.defn->nargs >= 0)
2802: {
2803: U_CHAR *old_ibp = ibp;
2804: U_CHAR *old_obp = obp;
2805: int old_iln = ip->lineno;
2806: int old_oln = op->lineno;
2807:
2808: while (1) {
2809: /* Scan forward over whitespace, copying it to the output. */
2810: if (ibp == limit && ip->macro != 0) {
2811: POPMACRO;
2812: RECACHE;
2813: old_ibp = ibp;
2814: old_obp = obp;
2815: old_iln = ip->lineno;
2816: old_oln = op->lineno;
2817: }
2818: /* A comment: copy it unchanged or discard it. */
2819: else if (*ibp == '/' && ibp+1 != limit && ibp[1] == '*') {
2820: if (put_out_comments) {
2821: *obp++ = '/';
2822: *obp++ = '*';
2823: } else if (! traditional) {
2824: *obp++ = ' ';
2825: }
2826: ibp += 2;
2827: while (ibp + 1 != limit
2828: && !(ibp[0] == '*' && ibp[1] == '/')) {
2829: /* We need not worry about newline-marks,
2830: since they are never found in comments. */
2831: if (*ibp == '\n') {
2832: /* Newline in a file. Count it. */
2833: ++ip->lineno;
2834: ++op->lineno;
2835: }
2836: if (put_out_comments)
2837: *obp++ = *ibp++;
2838: else
2839: ibp++;
2840: }
2841: ibp += 2;
2842: if (put_out_comments) {
2843: *obp++ = '*';
2844: *obp++ = '/';
2845: }
2846: }
2847: else if (is_space[*ibp]) {
2848: *obp++ = *ibp++;
2849: if (ibp[-1] == '\n') {
2850: if (ip->macro == 0) {
2851: /* Newline in a file. Count it. */
2852: ++ip->lineno;
2853: ++op->lineno;
2854: } else if (!output_marks) {
2855: /* A newline mark, and we don't want marks
2856: in the output. If it is newline-hyphen,
2857: discard it entirely. Otherwise, it is
2858: newline-whitechar, so keep the whitechar. */
2859: obp--;
2860: if (*ibp == '-')
2861: ibp++;
2862: else {
2863: if (*ibp == '\n')
2864: ++op->lineno;
2865: *obp++ = *ibp++;
2866: }
2867: } else {
2868: /* A newline mark; copy both chars to the output. */
2869: *obp++ = *ibp++;
2870: }
2871: }
2872: }
2873: else break;
2874: }
2875: if (*ibp != '(') {
2876: /* It isn't a macro call.
2877: Put back the space that we just skipped. */
2878: ibp = old_ibp;
2879: obp = old_obp;
2880: ip->lineno = old_iln;
2881: op->lineno = old_oln;
2882: /* Exit the for loop. */
2883: break;
2884: }
2885: }
2886:
2887: /* This is now known to be a macro call.
2888: Discard the macro name from the output,
2889: along with any following whitespace just copied. */
2890: obp = op->buf + obufp_before_macroname;
2891: op->lineno = op_lineno_before_macroname;
2892:
2893: /* Expand the macro, reading arguments as needed,
2894: and push the expansion on the input stack. */
2895: ip->bufp = ibp;
2896: op->bufp = obp;
2897: macroexpand (hp, op);
2898:
2899: /* Reexamine input stack, since macroexpand has pushed
2900: a new level on it. */
2901: obp = op->bufp;
2902: RECACHE;
2903: break;
2904: }
2905: hashcollision:
2906: ;
2907: } /* End hash-table-search loop */
2908: }
2909: ident_length = hash = 0; /* Stop collecting identifier */
2910: redo_char = 0;
2911: concatenated = 0;
2912: } /* End if (ident_length > 0) */
2913: } /* End switch */
2914: } /* End per-char loop */
2915:
2916: /* Come here to return -- but first give an error message
2917: if there was an unterminated successful conditional. */
2918: ending:
2919: if (if_stack != ip->if_stack) {
2920: char *str;
2921: switch (if_stack->type) {
2922: case T_IF:
2923: str = "if";
2924: break;
2925: case T_IFDEF:
2926: str = "ifdef";
2927: break;
2928: case T_IFNDEF:
2929: str = "ifndef";
2930: break;
2931: case T_ELSE:
2932: str = "else";
2933: break;
2934: case T_ELIF:
2935: str = "elif";
2936: break;
2937: }
2938: error_with_line (line_for_error (if_stack->lineno),
2939: "unterminated `#%s' conditional", str);
2940: }
2941: if_stack = ip->if_stack;
2942: }
2943:
2944: /*
2945: * Rescan a string into a temporary buffer and return the result
2946: * as a FILE_BUF. Note this function returns a struct, not a pointer.
2947: *
2948: * OUTPUT_MARKS nonzero means keep Newline markers found in the input
2949: * and insert such markers when appropriate. See `rescan' for details.
2950: * OUTPUT_MARKS is 1 for macroexpanding a macro argument separately
2951: * before substitution; it is 0 for other uses.
2952: */
2953: static FILE_BUF
2954: expand_to_temp_buffer (buf, limit, output_marks, assertions)
2955: U_CHAR *buf, *limit;
2956: int output_marks, assertions;
2957: {
2958: register FILE_BUF *ip;
2959: FILE_BUF obuf;
2960: int length = limit - buf;
2961: U_CHAR *buf1;
2962: int odepth = indepth;
2963: int save_assertions_flag = assertions_flag;
2964:
2965: assertions_flag = assertions;
2966:
2967: if (length < 0)
2968: abort ();
2969:
2970: /* Set up the input on the input stack. */
2971:
2972: buf1 = (U_CHAR *) alloca (length + 1);
2973: {
2974: register U_CHAR *p1 = buf;
2975: register U_CHAR *p2 = buf1;
2976:
2977: while (p1 != limit)
2978: *p2++ = *p1++;
2979: }
2980: buf1[length] = 0;
2981:
2982: /* Set up to receive the output. */
2983:
2984: obuf.length = length * 2 + 100; /* Usually enough. Why be stingy? */
2985: obuf.bufp = obuf.buf = (U_CHAR *) xmalloc (obuf.length);
2986: obuf.fname = 0;
2987: obuf.macro = 0;
2988: obuf.free_ptr = 0;
2989:
2990: CHECK_DEPTH ({return obuf;});
2991:
2992: ++indepth;
2993:
2994: ip = &instack[indepth];
2995: ip->fname = 0;
2996: ip->nominal_fname = 0;
2997: ip->system_header_p = 0;
2998: ip->macro = 0;
2999: ip->free_ptr = 0;
3000: ip->length = length;
3001: ip->buf = ip->bufp = buf1;
3002: ip->if_stack = if_stack;
3003:
3004: ip->lineno = obuf.lineno = 1;
3005:
3006: /* Scan the input, create the output. */
3007: rescan (&obuf, output_marks);
3008:
3009: /* Pop input stack to original state. */
3010: --indepth;
3011:
3012: if (indepth != odepth)
3013: abort ();
3014:
3015: /* Record the output. */
3016: obuf.length = obuf.bufp - obuf.buf;
3017:
3018: assertions_flag = save_assertions_flag;
3019: return obuf;
3020: }
3021:
3022: /*
3023: * Process a # directive. Expects IP->bufp to point after the '#', as in
3024: * `#define foo bar'. Passes to the command handler
3025: * (do_define, do_include, etc.): the addresses of the 1st and
3026: * last chars of the command (starting immediately after the #
3027: * keyword), plus op and the keyword table pointer. If the command
3028: * contains comments it is copied into a temporary buffer sans comments
3029: * and the temporary buffer is passed to the command handler instead.
3030: * Likewise for backslash-newlines.
3031: *
3032: * Returns nonzero if this was a known # directive.
3033: * Otherwise, returns zero, without advancing the input pointer.
3034: */
3035:
3036: static int
3037: handle_directive (ip, op)
3038: FILE_BUF *ip, *op;
3039: {
3040: register U_CHAR *bp, *cp;
3041: register struct directive *kt;
3042: register int ident_length;
3043: U_CHAR *resume_p;
3044:
3045: /* Nonzero means we must copy the entire command
3046: to get rid of comments or backslash-newlines. */
3047: int copy_command = 0;
3048:
3049: U_CHAR *ident, *after_ident;
3050:
3051: bp = ip->bufp;
3052:
3053: /* Record where the directive started. do_xifdef needs this. */
3054: directive_start = bp - 1;
3055:
3056: /* Skip whitespace and \-newline. */
3057: while (1) {
3058: if (is_hor_space[*bp]) {
3059: if ((*bp == '\f' || *bp == '\v') && pedantic)
3060: pedwarn ("%s in preprocessing directive",
3061: *bp == '\f' ? "formfeed" : "vertical tab");
3062: bp++;
3063: } else if (*bp == '/' && bp[1] == '*') {
3064: ip->bufp = bp;
1.1.1.2 ! root 3065: skip_to_end_of_comment (ip, &ip->lineno, 0);
1.1 root 3066: bp = ip->bufp;
3067: } else if (*bp == '\\' && bp[1] == '\n') {
3068: bp += 2; ip->lineno++;
3069: } else break;
3070: }
3071:
3072: /* Now find end of directive name.
3073: If we encounter a backslash-newline, exchange it with any following
3074: symbol-constituents so that we end up with a contiguous name. */
3075:
3076: cp = bp;
3077: while (1) {
3078: if (is_idchar[*cp])
3079: cp++;
3080: else {
3081: if (*cp == '\\' && cp[1] == '\n')
3082: name_newline_fix (cp);
3083: if (is_idchar[*cp])
3084: cp++;
3085: else break;
3086: }
3087: }
3088: ident_length = cp - bp;
3089: ident = bp;
3090: after_ident = cp;
3091:
3092: /* A line of just `#' becomes blank. */
3093:
3094: if (ident_length == 0 && *after_ident == '\n') {
3095: ip->bufp = after_ident;
3096: return 1;
3097: }
3098:
3099: if (ident_length == 0 || !is_idstart[*ident]) {
3100: U_CHAR *p = ident;
3101: while (is_idchar[*p]) {
3102: if (*p < '0' || *p > '9')
3103: break;
3104: p++;
3105: }
3106: /* Handle # followed by a line number. */
3107: if (p != ident && !is_idchar[*p]) {
3108: static struct directive line_directive_table[] = {
3109: { 4, do_line, "line", T_LINE},
3110: };
3111: if (pedantic)
3112: pedwarn ("`#' followed by integer");
3113: after_ident = ident;
3114: kt = line_directive_table;
3115: goto old_linenum;
3116: }
3117:
3118: /* Avoid error for `###' and similar cases unless -pedantic. */
3119: if (p == ident) {
3120: while (*p == '#' || is_hor_space[*p]) p++;
3121: if (*p == '\n') {
3122: if (pedantic && !lang_asm)
3123: warning ("invalid preprocessor directive");
3124: return 0;
3125: }
3126: }
3127:
3128: if (!lang_asm)
3129: error ("invalid preprocessor directive name");
3130:
3131: return 0;
3132: }
3133:
3134: /*
3135: * Decode the keyword and call the appropriate expansion
3136: * routine, after moving the input pointer up to the next line.
3137: */
3138: for (kt = directive_table; kt->length > 0; kt++) {
3139: if (kt->length == ident_length && !strncmp (kt->name, ident, ident_length)) {
3140: register U_CHAR *buf;
3141: register U_CHAR *limit;
3142: int unterminated;
3143: int junk;
3144: int *already_output = 0;
3145:
3146: /* Nonzero means do not delete comments within the directive.
3147: #define needs this when -traditional. */
3148: int keep_comments;
3149:
3150: old_linenum:
3151:
3152: limit = ip->buf + ip->length;
3153: unterminated = 0;
3154: keep_comments = traditional && kt->traditional_comments;
3155: /* #import is defined only in Objective C, or when on the NeXT. */
3156: if (kt->type == T_IMPORT && !(objc || lookup ("__NeXT__", -1, -1)))
3157: break;
3158:
3159: /* Find the end of this command (first newline not backslashed
3160: and not in a string or comment).
3161: Set COPY_COMMAND if the command must be copied
3162: (it contains a backslash-newline or a comment). */
3163:
3164: buf = bp = after_ident;
3165: while (bp < limit) {
3166: register U_CHAR c = *bp++;
3167: switch (c) {
3168: case '\\':
3169: if (bp < limit) {
3170: if (*bp == '\n') {
3171: ip->lineno++;
3172: copy_command = 1;
3173: }
3174: bp++;
3175: }
3176: break;
3177:
3178: case '\'':
3179: case '\"':
3180: bp = skip_quoted_string (bp - 1, limit, ip->lineno, &ip->lineno, ©_command, &unterminated);
3181: /* Don't bother calling the directive if we already got an error
3182: message due to unterminated string. Skip everything and pretend
3183: we called the directive. */
3184: if (unterminated) {
3185: if (traditional) {
3186: /* Traditional preprocessing permits unterminated strings. */
3187: ip->bufp = bp;
3188: goto endloop1;
3189: }
3190: ip->bufp = bp;
3191: return 1;
3192: }
3193: break;
3194:
3195: /* <...> is special for #include. */
3196: case '<':
3197: if (!kt->angle_brackets)
3198: break;
3199: while (*bp && *bp != '>') bp++;
3200: break;
3201:
3202: case '/':
3203: if (*bp == '\\' && bp[1] == '\n')
3204: newline_fix (bp);
3205: if (*bp == '*'
3206: || ((cplusplus || objc) && *bp == '/')) {
3207: U_CHAR *obp = bp - 1;
3208: ip->bufp = bp + 1;
1.1.1.2 ! root 3209: skip_to_end_of_comment (ip, &ip->lineno, 0);
1.1 root 3210: bp = ip->bufp;
3211: /* No need to copy the command because of a comment at the end;
3212: just don't include the comment in the directive. */
3213: if (bp == limit || *bp == '\n') {
3214: bp = obp;
3215: goto endloop1;
3216: }
3217: /* Don't remove the comments if -traditional. */
3218: if (! keep_comments)
3219: copy_command++;
3220: }
3221: break;
3222:
3223: case '\f':
3224: case '\v':
3225: if (pedantic)
3226: pedwarn ("%s in preprocessing directive",
3227: c == '\f' ? "formfeed" : "vertical tab");
3228: break;
3229:
3230: case '\n':
3231: --bp; /* Point to the newline */
3232: ip->bufp = bp;
3233: goto endloop1;
3234: }
3235: }
3236: ip->bufp = bp;
3237:
3238: endloop1:
3239: resume_p = ip->bufp;
3240: /* BP is the end of the directive.
3241: RESUME_P is the next interesting data after the directive.
3242: A comment may come between. */
3243:
3244: /* If a directive should be copied through, and -E was given,
3245: pass it through before removing comments. */
3246: if (!no_output && kt->pass_thru && put_out_comments) {
3247: int len;
3248:
3249: /* Output directive name. */
3250: check_expand (op, kt->length + 2);
3251: /* Make sure # is at the start of a line */
3252: if (op->bufp > op->buf && op->bufp[-1] != '\n') {
3253: op->lineno++;
3254: *op->bufp++ = '\n';
3255: }
3256: *op->bufp++ = '#';
3257: bcopy (kt->name, op->bufp, kt->length);
3258: op->bufp += kt->length;
3259:
3260: /* Output arguments. */
3261: len = (bp - buf);
3262: check_expand (op, len);
3263: bcopy (buf, op->bufp, len);
3264: op->bufp += len;
3265: /* Take account of any (escaped) newlines just output. */
3266: while (--len >= 0)
3267: if (buf[len] == '\n')
3268: op->lineno++;
3269:
3270: already_output = &junk;
3271: } /* Don't we need a newline or #line? */
3272:
3273: if (copy_command) {
3274: register U_CHAR *xp = buf;
3275: /* Need to copy entire command into temp buffer before dispatching */
3276:
3277: cp = (U_CHAR *) alloca (bp - buf + 5); /* room for cmd plus
3278: some slop */
3279: buf = cp;
3280:
3281: /* Copy to the new buffer, deleting comments
3282: and backslash-newlines (and whitespace surrounding the latter). */
3283:
3284: while (xp < bp) {
3285: register U_CHAR c = *xp++;
3286: *cp++ = c;
3287:
3288: switch (c) {
3289: case '\n':
3290: abort (); /* A bare newline should never part of the line. */
3291: break;
3292:
3293: /* <...> is special for #include. */
3294: case '<':
3295: if (!kt->angle_brackets)
3296: break;
3297: while (xp < bp && c != '>') {
3298: c = *xp++;
3299: if (c == '\\' && xp < bp && *xp == '\n')
3300: xp++;
3301: else
3302: *cp++ = c;
3303: }
3304: break;
3305:
3306: case '\\':
3307: if (*xp == '\n') {
3308: xp++;
3309: cp--;
3310: if (cp != buf && is_space[cp[-1]]) {
3311: while (cp != buf && is_space[cp[-1]]) cp--;
3312: cp++;
3313: SKIP_WHITE_SPACE (xp);
3314: } else if (is_space[*xp]) {
3315: *cp++ = *xp++;
3316: SKIP_WHITE_SPACE (xp);
3317: }
3318: }
3319: break;
3320:
3321: case '\'':
3322: case '\"':
3323: {
3324: register U_CHAR *bp1
3325: = skip_quoted_string (xp - 1, limit, ip->lineno, 0, 0, 0);
3326: while (xp != bp1)
3327: if (*xp == '\\') {
3328: if (*++xp != '\n')
3329: *cp++ = '\\';
3330: else
3331: xp++;
3332: } else
3333: *cp++ = *xp++;
3334: }
3335: break;
3336:
3337: case '/':
3338: if (*xp == '*'
3339: || ((cplusplus || objc) && *xp == '/')) {
3340: ip->bufp = xp + 1;
3341: /* If we already copied the command through,
3342: already_output != 0 prevents outputting comment now. */
1.1.1.2 ! root 3343: skip_to_end_of_comment (ip, already_output, 0);
1.1 root 3344: if (keep_comments)
3345: while (xp != ip->bufp)
3346: *cp++ = *xp++;
3347: /* Delete or replace the slash. */
3348: else if (traditional)
3349: cp--;
3350: else
3351: cp[-1] = ' ';
3352: xp = ip->bufp;
3353: }
3354: }
3355: }
3356:
3357: /* Null-terminate the copy. */
3358:
3359: *cp = 0;
3360: } else
3361: cp = bp;
3362:
3363: ip->bufp = resume_p;
3364:
3365: /* Some directives should be written out for cc1 to process,
3366: just as if they were not defined. And sometimes we're copying
3367: definitions through. */
3368:
3369: if (!no_output && already_output == 0
3370: && (kt->pass_thru
3371: || (kt->type == T_DEFINE
3372: && (dump_macros == dump_names
3373: || dump_macros == dump_definitions)))) {
3374: int len;
3375:
3376: /* Output directive name. */
3377: check_expand (op, kt->length + 1);
3378: *op->bufp++ = '#';
3379: bcopy (kt->name, op->bufp, kt->length);
3380: op->bufp += kt->length;
3381:
3382: if (kt->pass_thru || dump_macros == dump_definitions) {
3383: /* Output arguments. */
3384: len = (cp - buf);
3385: check_expand (op, len);
3386: bcopy (buf, op->bufp, len);
3387: op->bufp += len;
3388: }
3389: } /* Don't we need a newline or #line? */
3390:
3391: /* Call the appropriate command handler. buf now points to
3392: either the appropriate place in the input buffer, or to
3393: the temp buffer if it was necessary to make one. cp
3394: points to the first char after the contents of the (possibly
3395: copied) command, in either case. */
3396: (*kt->func) (buf, cp, op, kt);
3397: check_expand (op, ip->length - (ip->bufp - ip->buf));
3398:
3399: return 1;
3400: }
3401: }
3402:
3403: /* It is deliberate that we don't warn about undefined directives.
3404: That is the responsibility of cc1. */
3405: return 0;
3406: }
3407:
3408: static char *monthnames[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
3409: "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
3410: };
3411:
3412: /*
3413: * expand things like __FILE__. Place the expansion into the output
3414: * buffer *without* rescanning.
3415: */
3416:
3417: static void
3418: special_symbol (hp, op)
3419: HASHNODE *hp;
3420: FILE_BUF *op;
3421: {
3422: char *buf;
3423: int i, len;
3424: int true_indepth;
3425: FILE_BUF *ip = NULL;
3426:
3427: int paren = 0; /* For special `defined' keyword */
3428:
3429: if (pcp_outfile && pcp_inside_if
3430: && hp->type != T_SPEC_DEFINED && hp->type != T_CONST)
3431: error ("Predefined macro `%s' used inside `#if' during precompilation",
3432: hp->name);
3433:
3434: for (i = indepth; i >= 0; i--)
3435: if (instack[i].fname != NULL) {
3436: ip = &instack[i];
3437: break;
3438: }
3439: if (ip == NULL) {
3440: error ("cccp error: not in any file?!");
3441: return; /* the show must go on */
3442: }
3443:
3444: switch (hp->type) {
3445: case T_FILE:
3446: case T_BASE_FILE:
3447: {
3448: char *string;
3449: if (hp->type == T_FILE)
3450: string = ip->nominal_fname;
3451: else
3452: string = instack[0].nominal_fname;
3453:
3454: if (string)
3455: {
3456: buf = (char *) alloca (3 + strlen (string));
3457: sprintf (buf, "\"%s\"", string);
3458: }
3459: else
3460: buf = "\"\"";
3461:
3462: break;
3463: }
3464:
3465: case T_INCLUDE_LEVEL:
3466: true_indepth = 0;
3467: for (i = indepth; i >= 0; i--)
3468: if (instack[i].fname != NULL)
3469: true_indepth++;
3470:
3471: buf = (char *) alloca (8); /* Eight bytes ought to be more than enough */
3472: sprintf (buf, "%d", true_indepth - 1);
3473: break;
3474:
3475: case T_VERSION:
3476: buf = (char *) alloca (3 + strlen (version_string));
3477: sprintf (buf, "\"%s\"", version_string);
3478: break;
3479:
3480: case T_SIZE_TYPE:
3481: buf = (char *) alloca (3 + strlen (SIZE_TYPE));
3482: sprintf (buf, "%s", SIZE_TYPE);
3483: break;
3484:
3485: case T_PTRDIFF_TYPE:
3486: buf = (char *) alloca (3 + strlen (PTRDIFF_TYPE));
3487: sprintf (buf, "%s", PTRDIFF_TYPE);
3488: break;
3489:
3490: case T_WCHAR_TYPE:
3491: buf = (char *) alloca (3 + strlen (WCHAR_TYPE));
3492: sprintf (buf, "%s", WCHAR_TYPE);
3493: break;
3494:
3495: case T_CONST:
3496: buf = (char *) alloca (4 * sizeof (int));
3497: sprintf (buf, "%d", hp->value.ival);
3498: if (pcp_inside_if && pcp_outfile)
3499: /* Output a precondition for this macro use */
3500: fprintf (pcp_outfile, "#define %s %d\n", hp->name, hp->value.ival);
3501: break;
3502:
3503: case T_SPECLINE:
3504: buf = (char *) alloca (10);
3505: sprintf (buf, "%d", ip->lineno);
3506: break;
3507:
3508: case T_DATE:
3509: case T_TIME:
3510: buf = (char *) alloca (20);
3511: if (hp->type == T_DATE)
3512: sprintf (buf, "\"%s %2d %4d\"", monthnames[timebuf->tm_mon],
3513: timebuf->tm_mday, timebuf->tm_year + 1900);
3514: else
3515: sprintf (buf, "\"%02d:%02d:%02d\"", timebuf->tm_hour, timebuf->tm_min,
3516: timebuf->tm_sec);
3517: break;
3518:
3519: case T_SPEC_DEFINED:
3520: buf = " 0 "; /* Assume symbol is not defined */
3521: ip = &instack[indepth];
3522: SKIP_WHITE_SPACE (ip->bufp);
3523: if (*ip->bufp == '(') {
3524: paren++;
3525: ip->bufp++; /* Skip over the paren */
3526: SKIP_WHITE_SPACE (ip->bufp);
3527: }
3528:
3529: if (!is_idstart[*ip->bufp])
3530: goto oops;
3531: if (hp = lookup (ip->bufp, -1, -1)) {
3532: if (pcp_outfile && pcp_inside_if
3533: && hp->value.defn->predefined)
3534: /* Output a precondition for this macro use. */
3535: fprintf (pcp_outfile, "#define %s\n", hp->name);
3536: buf = " 1 ";
3537: }
3538: else
3539: if (pcp_outfile && pcp_inside_if) {
3540: /* Output a precondition for this macro use */
3541: U_CHAR *cp = ip->bufp;
3542: fprintf (pcp_outfile, "#undef ");
3543: while (is_idchar[*cp]) /* Ick! */
3544: fputc (*cp++, pcp_outfile);
3545: putc ('\n', pcp_outfile);
3546: }
3547: while (is_idchar[*ip->bufp])
3548: ++ip->bufp;
3549: SKIP_WHITE_SPACE (ip->bufp);
3550: if (paren) {
3551: if (*ip->bufp != ')')
3552: goto oops;
3553: ++ip->bufp;
3554: }
3555: break;
3556:
3557: oops:
3558:
3559: error ("`defined' without an identifier");
3560: break;
3561:
3562: default:
3563: error ("cccp error: invalid special hash type"); /* time for gdb */
3564: abort ();
3565: }
3566: len = strlen (buf);
3567: check_expand (op, len);
3568: bcopy (buf, op->bufp, len);
3569: op->bufp += len;
3570:
3571: return;
3572: }
3573:
3574:
3575: /* Routines to handle #directives */
3576:
3577: /* Handle #include and #import.
3578: This function expects to see "fname" or <fname> on the input. */
3579:
3580: static int
3581: do_include (buf, limit, op, keyword)
3582: U_CHAR *buf, *limit;
3583: FILE_BUF *op;
3584: struct directive *keyword;
3585: {
3586: int importing = (keyword->type == T_IMPORT);
3587: int skip_dirs = (keyword->type == T_INCLUDE_NEXT);
3588: static int import_warning = 0;
3589: char *fname; /* Dynamically allocated fname buffer */
3590: char *pcftry;
3591: char *pcfname;
3592: U_CHAR *fbeg, *fend; /* Beginning and end of fname */
3593:
3594: struct file_name_list *search_start = include; /* Chain of dirs to search */
3595: struct file_name_list dsp[1]; /* First in chain, if #include "..." */
3596: struct file_name_list *searchptr;
3597: int flen;
3598:
3599: int f; /* file number */
3600:
3601: int retried = 0; /* Have already tried macro
3602: expanding the include line*/
3603: FILE_BUF trybuf; /* It got expanded into here */
3604: int system_header_p = 0; /* 0 for "...", 1 for <...> */
3605: int pcf = -1;
3606: char *pcfbuf;
3607: int pcfbuflimit;
3608: int pcfnum;
3609: f= -1; /* JF we iz paranoid! */
3610:
1.1.1.2 ! root 3611: if (importing && warn_import
! 3612: && !instack[indepth].system_header_p && !import_warning) {
1.1 root 3613: import_warning = 1;
3614: warning ("using `#import' is not recommended");
3615: fprintf (stderr, "The fact that a certain header file need not be processed more than once\n");
3616: fprintf (stderr, "should be indicated in the header file, not where it is used.\n");
3617: fprintf (stderr, "The best way to do this is with a conditional of this form:\n\n");
3618: fprintf (stderr, " #ifndef _FOO_H_INCLUDED\n");
3619: fprintf (stderr, " #define _FOO_H_INCLUDED\n");
3620: fprintf (stderr, " ... <real contents of file> ...\n");
3621: fprintf (stderr, " #endif /* Not _FOO_H_INCLUDED */\n\n");
3622: fprintf (stderr, "Then users can use `#include' any number of times.\n");
3623: fprintf (stderr, "GNU C automatically avoids processing the file more than once\n");
3624: fprintf (stderr, "when it is equipped with such a conditional.\n");
3625: }
3626:
3627: get_filename:
3628:
3629: fbeg = buf;
3630: SKIP_WHITE_SPACE (fbeg);
3631: /* Discard trailing whitespace so we can easily see
3632: if we have parsed all the significant chars we were given. */
3633: while (limit != fbeg && is_hor_space[limit[-1]]) limit--;
3634:
3635: switch (*fbeg++) {
3636: case '\"':
3637: fend = fbeg;
3638: while (fend != limit && *fend != '\"')
3639: fend++;
3640: if (*fend == '\"' && fend + 1 == limit) {
3641: FILE_BUF *fp;
3642:
3643: /* We have "filename". Figure out directory this source
3644: file is coming from and put it on the front of the list. */
3645:
3646: /* If -I- was specified, don't search current dir, only spec'd ones. */
3647: if (ignore_srcdir) break;
3648:
3649: for (fp = &instack[indepth]; fp >= instack; fp--)
3650: {
3651: int n;
3652: char *ep,*nam;
3653:
3654: if ((nam = fp->nominal_fname) != NULL) {
3655: /* Found a named file. Figure out dir of the file,
3656: and put it in front of the search list. */
3657: dsp[0].next = search_start;
3658: search_start = dsp;
3659: #ifndef VMS
3660: ep = rindex (nam, '/');
3661: #else /* VMS */
3662: ep = rindex (nam, ']');
3663: if (ep == NULL) ep = rindex (nam, '>');
3664: if (ep == NULL) ep = rindex (nam, ':');
3665: if (ep != NULL) ep++;
3666: #endif /* VMS */
3667: if (ep != NULL) {
3668: n = ep - nam;
3669: dsp[0].fname = (char *) alloca (n + 1);
3670: strncpy (dsp[0].fname, nam, n);
3671: dsp[0].fname[n] = '\0';
3672: if (n > max_include_len) max_include_len = n;
3673: } else {
3674: dsp[0].fname = 0; /* Current directory */
3675: }
3676: break;
3677: }
3678: }
3679: break;
3680: }
3681: goto fail;
3682:
3683: case '<':
3684: fend = fbeg;
3685: while (fend != limit && *fend != '>') fend++;
3686: if (*fend == '>' && fend + 1 == limit) {
3687: system_header_p = 1;
3688: /* If -I-, start with the first -I dir after the -I-. */
3689: if (first_bracket_include)
3690: search_start = first_bracket_include;
3691: break;
3692: }
3693: goto fail;
3694:
3695: default:
3696: fail:
3697: if (retried) {
3698: if (importing)
3699: error ("`#import' expects \"fname\" or <fname>");
3700: else
3701: error ("`#include' expects \"fname\" or <fname>");
3702: return 0;
3703: } else {
3704: trybuf = expand_to_temp_buffer (buf, limit, 0, 0);
3705: buf = (U_CHAR *) alloca (trybuf.bufp - trybuf.buf + 1);
3706: bcopy (trybuf.buf, buf, trybuf.bufp - trybuf.buf);
3707: limit = buf + (trybuf.bufp - trybuf.buf);
3708: free (trybuf.buf);
3709: retried++;
3710: goto get_filename;
3711: }
3712: }
3713:
3714: /* For #include_next, skip in the search path
3715: past the dir in which the containing file was found. */
3716: if (skip_dirs) {
3717: FILE_BUF *fp;
3718: for (fp = &instack[indepth]; fp >= instack; fp--)
3719: if (fp->fname != NULL) {
3720: /* fp->dir is null if the containing file was specified
3721: with an absolute file name. In that case, don't skip anything. */
3722: if (fp->dir)
3723: search_start = fp->dir->next;
3724: break;
3725: }
3726: }
3727:
3728: flen = fend - fbeg;
3729: /* Allocate this permanently, because it gets stored in the definitions
3730: of macros. */
3731: fname = (char *) xmalloc (max_include_len + flen + 2);
3732: /* + 2 above for slash and terminating null. */
3733:
3734: /* If specified file name is absolute, just open it. */
3735:
3736: if (*fbeg == '/') {
3737: strncpy (fname, fbeg, flen);
3738: fname[flen] = 0;
1.1.1.2 ! root 3739: if (lookup_include (fname))
! 3740: return 0;
1.1 root 3741: if (importing)
3742: f = lookup_import (fname);
3743: else
3744: f = open (fname, O_RDONLY, 0666);
3745: if (f == -2)
3746: return 0; /* Already included this file */
3747: } else {
3748: /* Search directory path, trying to open the file.
3749: Copy each filename tried into FNAME. */
3750:
3751: for (searchptr = search_start; searchptr; searchptr = searchptr->next) {
3752: if (searchptr->fname) {
3753: /* The empty string in a search path is ignored.
3754: This makes it possible to turn off entirely
3755: a standard piece of the list. */
3756: if (searchptr->fname[0] == 0)
3757: continue;
3758: strcpy (fname, searchptr->fname);
3759: strcat (fname, "/");
3760: fname[strlen (fname) + flen] = 0;
3761: } else {
3762: fname[0] = 0;
3763: }
3764: strncat (fname, fbeg, flen);
3765: #ifdef VMS
3766: /* Change this 1/2 Unix 1/2 VMS file specification into a
3767: full VMS file specification */
3768: if (searchptr->fname && (searchptr->fname[0] != 0)) {
3769: /* Fix up the filename */
3770: hack_vms_include_specification (fname);
3771: } else {
3772: /* This is a normal VMS filespec, so use it unchanged. */
3773: strncpy (fname, fbeg, flen);
3774: fname[flen] = 0;
3775: }
3776: #endif /* VMS */
3777: if (importing)
3778: f = lookup_import (fname);
3779: else
3780: f = open (fname, O_RDONLY, 0666);
3781: if (f == -2)
3782: return 0; /* Already included this file */
1.1.1.2 ! root 3783: if (lookup_include (fname)) {
! 3784: close (f);
! 3785: return 0;
! 3786: }
1.1 root 3787: if (f >= 0)
3788: break;
3789: }
3790: }
3791:
3792: if (f < 0) {
3793: /* A file that was not found. */
3794:
3795: strncpy (fname, fbeg, flen);
3796: fname[flen] = 0;
3797: error_from_errno (fname);
3798:
3799: /* For -M, add this file to the dependencies. */
3800: if (print_deps > (system_header_p || (system_include_depth > 0))) {
3801: /* Break the line before this. */
3802: deps_output ("", 0);
3803:
3804: /* If it was requested as a system header file,
3805: then assume it belongs in the first place to look for such. */
3806: if (system_header_p) {
3807: for (searchptr = search_start; searchptr; searchptr = searchptr->next) {
3808: if (searchptr->fname) {
3809: if (searchptr->fname[0] == 0)
3810: continue;
3811: deps_output (searchptr->fname, 0);
3812: deps_output ("/", 0);
3813: break;
3814: }
3815: }
3816: }
3817: /* Otherwise, omit the directory, as if the file existed
3818: in the directory with the source. */
3819: deps_output (fbeg, flen);
3820: deps_output (" ", 0);
3821: }
3822: } else {
3823: struct stat stat_f;
3824:
3825: /* Check to see if this include file is a once-only include file.
3826: If so, give up. */
3827:
3828: struct file_name_list* ptr;
3829:
3830: for (ptr = dont_repeat_files; ptr; ptr = ptr->next) {
3831: if (!strcmp (ptr->fname, fname)) {
3832: close (f);
3833: return 0; /* This file was once'd. */
3834: }
3835: }
3836:
3837: for (ptr = all_include_files; ptr; ptr = ptr->next) {
3838: if (!strcmp (ptr->fname, fname))
3839: break; /* This file was included before. */
3840: }
3841:
3842: if (ptr == 0) {
3843: /* This is the first time for this file. */
3844: /* Add it to list of files included. */
3845:
3846: ptr = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
3847: ptr->control_macro = 0;
3848: ptr->next = all_include_files;
3849: all_include_files = ptr;
3850: ptr->fname = savestring (fname);
3851:
3852: /* For -M, add this file to the dependencies. */
3853: if (print_deps > (system_header_p || (system_include_depth > 0))) {
3854: deps_output ("", 0);
3855: deps_output (fname, 0);
3856: deps_output (" ", 0);
3857: }
3858: }
3859:
3860: /* Handle -H option. */
3861: if (print_include_names)
3862: fprintf (stderr, "%s\n", fname);
3863:
3864: if (system_header_p)
3865: system_include_depth++;
3866:
3867: /* Actually process the file. */
3868: add_import (f, fname); /* Record file on "seen" list for #import. */
3869:
3870: pcftry = (char *) alloca (strlen (fname) + 30);
3871: pcfbuf = 0;
3872: pcfnum = 0;
3873:
3874: fstat (f, &stat_f);
3875:
3876: if (!no_precomp)
3877: do {
3878: sprintf (pcftry, "%s%d", fname, pcfnum++);
3879:
3880: pcf = open (pcftry, O_RDONLY, 0666);
3881: if (pcf != -1)
3882: {
3883: struct stat s;
3884:
3885: fstat (pcf, &s);
3886: if (bcmp (&stat_f.st_ino, &s.st_ino, sizeof (s.st_ino))
3887: || stat_f.st_dev != s.st_dev)
3888: {
3889: pcfbuf = check_precompiled (pcf, fname, &pcfbuflimit);
3890: /* Don't need it any more. */
3891: close (pcf);
3892: }
3893: else
3894: {
3895: /* Don't need it at all. */
3896: close (pcf);
3897: break;
3898: }
3899: }
3900: } while (pcf != -1 && !pcfbuf);
3901:
3902: /* Actually process the file */
3903: if (pcfbuf) {
3904: pcfname = xmalloc (strlen (pcftry) + 1);
3905: strcpy (pcfname, pcftry);
3906: pcfinclude (pcfbuf, pcfbuflimit, fname, op);
3907: }
3908: else
3909: finclude (f, fname, op, system_header_p, searchptr);
3910:
3911: if (system_header_p)
3912: system_include_depth--;
3913: }
3914: return 0;
3915: }
3916:
1.1.1.2 ! root 3917: /* Return nonzero if there is no need to include file NAME
! 3918: because it has already been included and it contains a conditional
! 3919: to make a repeated include do nothing. */
! 3920:
! 3921: static int
! 3922: lookup_include (name)
! 3923: char *name;
! 3924: {
! 3925: struct file_name_list *l = all_include_files;
! 3926: for (; l; l = l->next)
! 3927: if (! strcmp (name, l->fname)
! 3928: && l->control_macro
! 3929: && lookup (l->control_macro, -1, -1))
! 3930: return 1;
! 3931: return 0;
! 3932: }
! 3933:
1.1 root 3934: /* Process the contents of include file FNAME, already open on descriptor F,
3935: with output to OP.
3936: SYSTEM_HEADER_P is 1 if this file was specified using <...>.
3937: DIRPTR is the link in the dir path through which this file was found,
3938: or 0 if the file name was absolute. */
3939:
3940: static void
3941: finclude (f, fname, op, system_header_p, dirptr)
3942: int f;
3943: char *fname;
3944: FILE_BUF *op;
3945: int system_header_p;
3946: struct file_name_list *dirptr;
3947: {
3948: int st_mode;
3949: long st_size;
3950: long i;
3951: FILE_BUF *fp; /* For input stack frame */
3952: int missing_newline = 0;
3953:
3954: CHECK_DEPTH (return;);
3955:
3956: if (file_size_and_mode (f, &st_mode, &st_size) < 0)
3957: goto nope; /* Impossible? */
3958:
3959: fp = &instack[indepth + 1];
3960: bzero (fp, sizeof (FILE_BUF));
3961: fp->nominal_fname = fp->fname = fname;
3962: fp->length = 0;
3963: fp->lineno = 1;
3964: fp->if_stack = if_stack;
3965: fp->system_header_p = system_header_p;
3966: fp->dir = dirptr;
3967:
3968: if (S_ISREG (st_mode)) {
3969: fp->buf = (U_CHAR *) alloca (st_size + 2);
3970: fp->bufp = fp->buf;
3971:
3972: /* Read the file contents, knowing that st_size is an upper bound
3973: on the number of bytes we can read. */
3974: while (st_size > 0) {
3975: i = read (f, fp->buf + fp->length, st_size);
3976: if (i <= 0) {
3977: if (i == 0) break;
3978: goto nope;
3979: }
3980: fp->length += i;
3981: st_size -= i;
3982: }
3983: }
3984: else {
3985: /* Cannot count its file size before reading.
3986: First read the entire file into heap and
3987: copy them into buffer on stack. */
3988:
3989: U_CHAR *bufp;
3990: U_CHAR *basep;
3991: int bsize = 2000;
3992:
3993: st_size = 0;
3994: basep = (U_CHAR *) xmalloc (bsize + 2);
3995: bufp = basep;
3996:
3997: for (;;) {
3998: i = read (f, bufp, bsize - st_size);
3999: if (i < 0)
4000: goto nope; /* error! */
4001: if (i == 0)
4002: break; /* End of file */
4003: st_size += i;
4004: bufp += i;
4005: if (bsize == st_size) { /* Buffer is full! */
4006: bsize *= 2;
4007: basep = (U_CHAR *) xrealloc (basep, bsize + 2);
4008: bufp = basep + st_size; /* May have moved */
4009: }
4010: }
4011: fp->buf = (U_CHAR *) alloca (st_size + 2);
4012: fp->bufp = fp->buf;
4013: bcopy (basep, fp->buf, st_size);
4014: fp->length = st_size;
4015: free (basep);
4016: }
4017:
4018: /* Close descriptor now, so nesting does not use lots of descriptors. */
4019: close (f);
4020:
4021: if (!no_trigraphs)
4022: trigraph_pcp (fp);
4023:
4024: if ((fp->length > 0 && fp->buf[fp->length - 1] != '\n')
4025: /* Backslash-newline at end is not good enough. */
4026: || (fp->length > 1 && fp->buf[fp->length - 2] == '\\')) {
4027: fp->buf[fp->length++] = '\n';
4028: missing_newline = 1;
4029: }
4030: fp->buf[fp->length] = '\0';
4031:
4032: indepth++;
4033: input_file_stack_tick++;
4034:
4035: output_line_command (fp, op, 0, enter_file);
4036: rescan (op, 0);
4037:
4038: if (pedantic && missing_newline)
4039: pedwarn ("file does not end in newline");
4040:
4041: indepth--;
4042: input_file_stack_tick++;
4043: output_line_command (&instack[indepth], op, 0, leave_file);
4044: return;
4045:
4046: nope:
4047:
4048: perror_with_name (fname);
4049: close (f);
4050: }
4051:
4052: /* Record that inclusion of the file named FILE
4053: should be controlled by the macro named MACRO_NAME.
4054: This means that trying to include the file again
4055: will do something if that macro is defined. */
4056:
4057: static void
4058: record_control_macro (file, macro_name)
4059: char *file;
4060: U_CHAR *macro_name;
4061: {
4062: struct file_name_list *new;
4063:
4064: for (new = all_include_files; new; new = new->next) {
4065: if (!strcmp (new->fname, file)) {
4066: new->control_macro = macro_name;
4067: return;
4068: }
4069: }
4070:
4071: /* If the file is not in all_include_files, something's wrong. */
4072: abort ();
4073: }
4074:
4075: /* Maintain and search list of included files, for #import. */
4076:
4077: #define IMPORT_HASH_SIZE 31
4078:
4079: struct import_file {
4080: char *name;
4081: ino_t inode;
4082: dev_t dev;
4083: struct import_file *next;
4084: };
4085:
4086: /* Hash table of files already included with #include or #import. */
4087:
4088: static struct import_file *import_hash_table[IMPORT_HASH_SIZE];
4089:
4090: /* Hash a file name for import_hash_table. */
4091:
4092: static int
4093: import_hash (f)
4094: char *f;
4095: {
4096: int val = 0;
4097:
4098: while (*f) val += *f++;
4099: return (val%IMPORT_HASH_SIZE);
4100: }
4101:
4102: /* Search for file FILENAME in import_hash_table.
4103: Return -2 if found, either a matching name or a matching inode.
4104: Otherwise, open the file and return a file descriptor if successful
4105: or -1 if unsuccessful. */
4106:
4107: static int
4108: lookup_import (filename)
4109: char *filename;
4110: {
4111: struct import_file *i;
4112: int h;
4113: int hashval;
4114: struct stat sb;
4115: int fd;
4116:
4117: hashval = import_hash (filename);
4118:
4119: /* Attempt to find file in list of already included files */
4120: i = import_hash_table[hashval];
4121:
4122: while (i) {
4123: if (!strcmp (filename, i->name))
4124: return -2; /* return found */
4125: i = i->next;
4126: }
4127: /* Open it and try a match on inode/dev */
4128: fd = open (filename, O_RDONLY, 0666);
4129: if (fd < 0)
4130: return fd;
4131: fstat (fd, &sb);
4132: for (h = 0; h < IMPORT_HASH_SIZE; h++) {
4133: i = import_hash_table[h];
4134: while (i) {
4135: /* Compare the inode and the device.
4136: Supposedly on some systems the inode is not a scalar. */
4137: if (!bcmp (&i->inode, &sb.st_ino, sizeof (sb.st_ino))
4138: && i->dev == sb.st_dev) {
4139: close (fd);
4140: return -2; /* return found */
4141: }
4142: i = i->next;
4143: }
4144: }
4145: return fd; /* Not found, return open file */
4146: }
4147:
4148: /* Add the file FNAME, open on descriptor FD, to import_hash_table. */
4149:
4150: static void
4151: add_import (fd, fname)
4152: int fd;
4153: char *fname;
4154: {
4155: struct import_file *i;
4156: int hashval;
4157: struct stat sb;
4158:
4159: hashval = import_hash (fname);
4160: fstat (fd, &sb);
4161: i = (struct import_file *)xmalloc (sizeof (struct import_file));
4162: i->name = (char *)xmalloc (strlen (fname)+1);
4163: strcpy (i->name, fname);
4164: bcopy (&sb.st_ino, &i->inode, sizeof (sb.st_ino));
4165: i->dev = sb.st_dev;
4166: i->next = import_hash_table[hashval];
4167: import_hash_table[hashval] = i;
4168: }
4169:
4170: /* Load the specified precompiled header into core, and verify its
4171: preconditions. PCF indicates the file descriptor to read, which must
4172: be a regular file. FNAME indicates the file name of the original
4173: header. *LIMIT will be set to an address one past the end of the file.
4174: If the preconditions of the file are not satisfied, the buffer is
4175: freed and we return 0. If the preconditions are satisfied, return
4176: the address of the buffer following the preconditions. The buffer, in
4177: this case, should never be freed because various pieces of it will
4178: be referred to until all precompiled strings are output at the end of
4179: the run.
4180: */
4181: static char *
4182: check_precompiled (pcf, fname, limit)
4183: int pcf;
4184: char *fname;
4185: char **limit;
4186: {
4187: int st_mode;
4188: long st_size;
4189: int length = 0;
4190: char *buf;
4191: char *dollar_loc;
4192: int i;
4193: char *cp;
4194:
4195: if (pcp_outfile)
4196: return 0;
4197:
4198: if (file_size_and_mode (pcf, &st_mode, &st_size) < 0)
4199: return 0;
4200:
4201: if (S_ISREG (st_mode))
4202: {
4203: buf = xmalloc (st_size + 2);
4204: while (st_size > 0)
4205: {
4206: i = read (pcf, buf + length, st_size);
4207: if (i < 0)
4208: goto nope;
4209: if (i == 0)
4210: break;
4211: length += i;
4212: st_size -= i;
4213: }
4214: }
4215: else
4216: abort ();
4217:
4218: if (length > 0 && buf[length-1] != '\n')
4219: buf[length++] = '\n';
4220: buf[length] = '\0';
4221:
4222: *limit = buf + length;
4223:
4224: /* File is in core. Check the preconditions. */
4225: if (!check_preconditions (buf))
4226: goto nope;
4227: for (cp = buf; *cp; cp++)
4228: ;
4229: #ifdef DEBUG_PCP
4230: fprintf (stderr, "Using preinclude %s\n", fname);
4231: #endif
4232: return cp + 1;
4233:
4234: nope:
4235: #ifdef DEBUG_PCP
4236: fprintf (stderr, "Cannot use preinclude %s\n", fname);
4237: #endif
4238: free (buf);
4239: return 0;
4240: }
4241:
4242: /* PREC (null terminated) points to the preconditions of a
4243: precompiled header. These are a series of #define and #undef
4244: lines which must match the current contents of the hash
4245: table. */
4246: static int
4247: check_preconditions (prec)
4248: char *prec;
4249: {
4250: MACRODEF mdef;
4251: char *lineend;
4252:
4253: while (*prec) {
4254: lineend = (char *) index (prec, '\n');
4255:
4256: if (*prec++ != '#') {
4257: error ("Bad format encountered while reading precompiled file");
4258: return 0;
4259: }
4260: if (!strncmp (prec, "define", 6)) {
4261: HASHNODE *hp;
4262:
4263: prec += 6;
4264: mdef = create_definition (prec, lineend, 0);
4265:
4266: if (mdef.defn == 0)
4267: abort();
4268:
4269: if ((hp = lookup (mdef.symnam, mdef.symlen, -1)) == NULL
4270: || (hp->type != T_MACRO && hp->type != T_CONST)
4271: || (hp->type == T_MACRO
4272: && !compare_defs (mdef.defn, hp->value.defn)
4273: && (mdef.defn->length != 2
4274: || mdef.defn->expansion[0] != '\n'
4275: || mdef.defn->expansion[1] != ' ')))
4276: return 0;
4277: } else if (!strncmp (prec, "undef", 5)) {
4278: char *name;
4279: int len;
4280:
4281: prec += 5;
4282: while (is_hor_space[*prec])
4283: prec++;
4284: name = prec;
4285: while (is_idchar[*prec])
4286: prec++;
4287: len = prec - name;
4288:
4289: if (lookup (name, len, -1))
4290: return 0;
4291: } else {
4292: error ("Bad format encountered while reading precompiled file");
4293: return 0;
4294: }
4295: prec = lineend + 1;
4296: }
4297: /* They all passed successfully */
4298: return 1;
4299: }
4300:
4301: /* Process the main body of a precompiled file. BUF points to the
4302: string section of the file, following the preconditions. LIMIT is one
4303: character past the end. NAME is the name of the file being read
4304: in. OP is the main output buffer */
4305: static void
4306: pcfinclude (buf, limit, name, op)
4307: U_CHAR *buf, *limit, *name;
4308: FILE_BUF *op;
4309: {
4310: FILE_BUF tmpbuf;
4311: int nstrings;
4312: U_CHAR *cp = buf;
4313:
4314: /* First in the file comes 4 bytes indicating the number of strings, */
4315: /* in network byte order. (MSB first). */
4316: nstrings = *cp++;
4317: nstrings = (nstrings << 8) | *cp++;
4318: nstrings = (nstrings << 8) | *cp++;
4319: nstrings = (nstrings << 8) | *cp++;
4320:
4321: /* Looping over each string... */
4322: while (nstrings--) {
4323: U_CHAR *string_start;
4324: U_CHAR *endofthiskey;
4325: STRINGDEF *str;
4326: int nkeys;
4327:
4328: /* Each string starts with a STRINGDEF structure (str), followed */
4329: /* by the text of the string (string_start) */
4330:
4331: /* First skip to a longword boundary */
4332: if ((int)cp & 3)
4333: cp += 4 - ((int)cp & 3);
4334:
4335: /* Now get the string. */
4336: str = (STRINGDEF *) cp;
4337: string_start = cp += sizeof (STRINGDEF);
4338:
4339: for (; *cp; cp++) /* skip the string */
4340: ;
4341:
4342: /* We need to macro expand the string here to ensure that the
4343: proper definition environment is in place. If it were only
4344: expanded when we find out it is needed, macros necessary for
4345: its proper expansion might have had their definitions changed. */
4346: tmpbuf = expand_to_temp_buffer (string_start, cp++, 0, 0);
4347: /* Lineno is already set in the precompiled file */
4348: str->contents = tmpbuf.buf;
4349: str->len = tmpbuf.length;
4350: str->writeflag = 0;
4351: str->filename = name;
4352: str->output_mark = outbuf.bufp - outbuf.buf;
4353:
4354: str->chain = 0;
4355: *stringlist_tailp = str;
4356: stringlist_tailp = &str->chain;
4357:
4358: /* Next comes a fourbyte number indicating the number of keys */
4359: /* for this string. */
4360: nkeys = *cp++;
4361: nkeys = (nkeys << 8) | *cp++;
4362: nkeys = (nkeys << 8) | *cp++;
4363: nkeys = (nkeys << 8) | *cp++;
4364:
4365: /* If this number is -1, then the string is mandatory. */
4366: if (nkeys == -1)
4367: str->writeflag = 1;
4368: else
1.1.1.2 ! root 4369: /* Otherwise, for each key, */
1.1 root 4370: for (; nkeys--; free (tmpbuf.buf), cp = endofthiskey + 1) {
4371: KEYDEF *kp = (KEYDEF *) cp;
4372: HASHNODE *hp;
4373:
4374: /* It starts with a KEYDEF structure */
4375: cp += sizeof (KEYDEF);
4376:
4377: /* Find the end of the key. At the end of this for loop we
4378: advance CP to the start of the next key using this variable. */
4379: endofthiskey = cp + strlen (cp);
4380: kp->str = str;
4381:
4382: /* Expand the key, and enter it into the hash table. */
4383: tmpbuf = expand_to_temp_buffer (cp, endofthiskey, 0, 0);
4384: tmpbuf.bufp = tmpbuf.buf;
4385:
4386: while (is_hor_space[*tmpbuf.bufp])
4387: tmpbuf.bufp++;
4388: if (!is_idstart[*tmpbuf.bufp]
4389: || tmpbuf.bufp == tmpbuf.buf + tmpbuf.length) {
4390: str->writeflag = 1;
4391: continue;
4392: }
4393:
4394: hp = lookup (tmpbuf.bufp, -1, -1);
4395: if (hp == NULL) {
4396: kp->chain = 0;
4397: install (tmpbuf.bufp, -1, T_PCSTRING, (int) kp, -1);
4398: }
4399: else if (hp->type == T_PCSTRING) {
4400: kp->chain = hp->value.keydef;
4401: hp->value.keydef = kp;
4402: }
4403: else
4404: str->writeflag = 1;
4405: }
4406: }
4407: /* This output_line_command serves to switch us back to the current
4408: input file in case some of these strings get output (which will
4409: result in line commands for the header file being output). */
4410: output_line_command (&instack[indepth], op, 0, enter_file);
4411: }
4412:
4413: /* Called from rescan when it hits a key for strings. Mark them all */
4414: /* used and clean up. */
4415: static void
4416: pcstring_used (hp)
4417: HASHNODE *hp;
4418: {
4419: KEYDEF *kp, *tmp;
4420:
4421: for (kp = hp->value.keydef; kp; kp = kp->chain)
4422: kp->str->writeflag = 1;
4423: delete_macro (hp);
4424: }
4425:
4426: /* Write the output, interspersing precompiled strings in their */
4427: /* appropriate places. */
4428: static void
4429: write_output ()
4430: {
4431: STRINGDEF *next_string;
4432: U_CHAR *cur_buf_loc;
4433: int line_command_len = 80;
4434: char *line_command = xmalloc (line_command_len);
4435: int len;
4436:
4437: /* In each run through the loop, either cur_buf_loc == */
4438: /* next_string_loc, in which case we print a series of strings, or */
4439: /* it is less than next_string_loc, in which case we write some of */
4440: /* the buffer. */
4441: cur_buf_loc = outbuf.buf;
4442: next_string = stringlist;
4443:
4444: while (cur_buf_loc < outbuf.bufp || next_string) {
4445: if (next_string
4446: && cur_buf_loc - outbuf.buf == next_string->output_mark) {
4447: if (next_string->writeflag) {
4448: len = strlen (next_string->filename);
4449: if (len > line_command_len)
4450: line_command = xrealloc (line_command,
4451: line_command_len *= 2);
4452: sprintf (line_command, "\n# %d \"%s\"\n",
4453: next_string->lineno, next_string->filename);
4454: write (fileno (stdout), line_command,
4455: strlen (line_command));
4456: write (fileno (stdout),
4457: next_string->contents, next_string->len);
4458: }
4459: next_string = next_string->chain;
4460: }
4461: else {
4462: len = (next_string
4463: ? (next_string->output_mark
4464: - (cur_buf_loc - outbuf.buf))
4465: : outbuf.bufp - cur_buf_loc);
4466:
4467: write (fileno (stdout), cur_buf_loc, len);
4468: cur_buf_loc += len;
4469: }
4470: }
4471: }
4472:
4473: /* Pass a directive through to the output file.
1.1.1.2 ! root 4474: BUF points to the contents of the directive, as a contiguous string.
1.1 root 4475: LIMIT points to the first character past the end of the directive.
4476: KEYWORD is the keyword-table entry for the directive. */
4477:
4478: static void
4479: pass_thru_directive (buf, limit, op, keyword)
4480: U_CHAR *buf, *limit;
4481: FILE_BUF *op;
4482: struct directive *keyword;
4483: {
4484: register unsigned keyword_length = keyword->length;
4485:
4486: check_expand (op, 1 + keyword_length + (limit - buf));
4487: *op->bufp++ = '#';
4488: bcopy (keyword->name, op->bufp, keyword_length);
4489: op->bufp += keyword_length;
4490: if (limit != buf && buf[0] != ' ')
4491: *op->bufp++ = ' ';
4492: bcopy (buf, op->bufp, limit - buf);
4493: op->bufp += (limit - buf);
4494: *op->bufp++ = '\n';
4495: }
4496:
4497: /* The arglist structure is built by do_define to tell
4498: collect_definition where the argument names begin. That
4499: is, for a define like "#define f(x,y,z) foo+x-bar*y", the arglist
4500: would contain pointers to the strings x, y, and z.
4501: Collect_definition would then build a DEFINITION node,
4502: with reflist nodes pointing to the places x, y, and z had
4503: appeared. So the arglist is just convenience data passed
4504: between these two routines. It is not kept around after
4505: the current #define has been processed and entered into the
4506: hash table. */
4507:
4508: struct arglist {
4509: struct arglist *next;
4510: U_CHAR *name;
4511: int length;
4512: int argno;
4513: };
4514:
4515: /* Create a DEFINITION node from a #define directive. Arguments are
4516: as for do_define. */
4517: static MACRODEF
4518: create_definition (buf, limit, op)
4519: U_CHAR *buf, *limit;
4520: FILE_BUF *op;
4521: {
4522: U_CHAR *bp; /* temp ptr into input buffer */
4523: U_CHAR *symname; /* remember where symbol name starts */
4524: int sym_length; /* and how long it is */
4525: int line = instack[indepth].lineno;
4526: char *file = instack[indepth].nominal_fname;
4527:
4528: DEFINITION *defn;
4529: int arglengths = 0; /* Accumulate lengths of arg names
4530: plus number of args. */
4531: MACRODEF mdef;
4532:
4533: bp = buf;
4534:
4535: while (is_hor_space[*bp])
4536: bp++;
4537:
4538: symname = bp; /* remember where it starts */
4539: sym_length = check_macro_name (bp, "macro");
4540: bp += sym_length;
4541:
4542: /* Lossage will occur if identifiers or control keywords are broken
4543: across lines using backslash. This is not the right place to take
4544: care of that. */
4545:
4546: if (*bp == '(') {
4547: struct arglist *arg_ptrs = NULL;
4548: int argno = 0;
4549:
4550: bp++; /* skip '(' */
4551: SKIP_WHITE_SPACE (bp);
4552:
4553: /* Loop over macro argument names. */
4554: while (*bp != ')') {
4555: struct arglist *temp;
4556:
4557: temp = (struct arglist *) alloca (sizeof (struct arglist));
4558: temp->name = bp;
4559: temp->next = arg_ptrs;
4560: temp->argno = argno++;
4561: arg_ptrs = temp;
4562:
4563: if (!is_idstart[*bp])
4564: pedwarn ("parameter name starts with a digit in `#define'");
4565:
4566: /* Find the end of the arg name. */
4567: while (is_idchar[*bp]) {
4568: bp++;
4569: }
4570: temp->length = bp - temp->name;
4571: arglengths += temp->length + 2;
4572: SKIP_WHITE_SPACE (bp);
4573: if (temp->length == 0 || (*bp != ',' && *bp != ')')) {
4574: error ("badly punctuated parameter list in `#define'");
4575: goto nope;
4576: }
4577: if (*bp == ',') {
4578: bp++;
4579: SKIP_WHITE_SPACE (bp);
4580: }
4581: if (bp >= limit) {
4582: error ("unterminated parameter list in `#define'");
4583: goto nope;
4584: }
4585: {
4586: struct arglist *otemp;
4587:
4588: for (otemp = temp->next; otemp != NULL; otemp = otemp->next)
4589: if (temp->length == otemp->length &&
4590: strncmp(temp->name, otemp->name, temp->length) == 0) {
4591: U_CHAR *name;
4592:
4593: name = (U_CHAR *) alloca(temp->length + 1);
4594: (void) strncpy(name, temp->name, temp->length);
4595: name[temp->length] = '\0';
4596: error ("duplicate argument name `%s' in `#define'", name);
4597: goto nope;
4598: }
4599: }
4600: }
4601:
4602: ++bp; /* skip paren */
4603: /* Skip exactly one space or tab if any. */
4604: if (bp < limit && (*bp == ' ' || *bp == '\t')) ++bp;
4605: /* now everything from bp before limit is the definition. */
4606: defn = collect_expansion (bp, limit, argno, arg_ptrs);
4607:
4608: /* Now set defn->args.argnames to the result of concatenating
4609: the argument names in reverse order
4610: with comma-space between them. */
4611: defn->args.argnames = (U_CHAR *) xmalloc (arglengths + 1);
4612: {
4613: struct arglist *temp;
4614: int i = 0;
4615: for (temp = arg_ptrs; temp; temp = temp->next) {
4616: bcopy (temp->name, &defn->args.argnames[i], temp->length);
4617: i += temp->length;
4618: if (temp->next != 0) {
4619: defn->args.argnames[i++] = ',';
4620: defn->args.argnames[i++] = ' ';
4621: }
4622: }
4623: defn->args.argnames[i] = 0;
4624: }
4625: } else {
4626: /* simple expansion or empty definition; gobble it */
4627: if (is_hor_space[*bp])
4628: ++bp; /* skip exactly one blank/tab char */
4629: /* now everything from bp before limit is the definition. */
4630: defn = collect_expansion (bp, limit, -1, 0);
4631: defn->args.argnames = (U_CHAR *) "";
4632: }
4633:
4634: defn->line = line;
4635: defn->file = file;
4636:
4637: /* OP is null if this is a predefinition */
4638: defn->predefined = !op;
4639: mdef.defn = defn;
4640: mdef.symnam = symname;
4641: mdef.symlen = sym_length;
4642:
4643: return mdef;
4644:
4645: nope:
4646: mdef.defn = 0;
4647: return mdef;
4648: }
4649:
4650: /* Process a #define command.
1.1.1.2 ! root 4651: BUF points to the contents of the #define command, as a contiguous string.
1.1 root 4652: LIMIT points to the first character past the end of the definition.
4653: KEYWORD is the keyword-table entry for #define. */
4654:
4655: static int
4656: do_define (buf, limit, op, keyword)
4657: U_CHAR *buf, *limit;
4658: FILE_BUF *op;
4659: struct directive *keyword;
4660: {
4661: int hashcode;
4662: MACRODEF mdef;
4663:
4664: /* If this is a precompiler run (with -pcp) pass thru #define commands. */
4665: if (pcp_outfile && op)
4666: pass_thru_directive (buf, limit, op, keyword);
4667:
4668: mdef = create_definition (buf, limit, op);
4669: if (mdef.defn == 0)
4670: goto nope;
4671:
4672: hashcode = hashf (mdef.symnam, mdef.symlen, HASHSIZE);
4673:
4674: {
4675: HASHNODE *hp;
4676: if ((hp = lookup (mdef.symnam, mdef.symlen, hashcode)) != NULL) {
4677: int ok = 0;
4678: /* Redefining a precompiled key is ok. */
4679: if (hp->type == T_PCSTRING)
4680: ok = 1;
4681: /* Redefining a macro is ok if the definitions are the same. */
4682: else if (hp->type == T_MACRO)
4683: ok = ! compare_defs (mdef.defn, hp->value.defn);
4684: /* Redefining a constant is ok with -D. */
4685: else if (hp->type == T_CONST)
4686: ok = ! done_initializing;
4687: /* Print the warning if it's not ok. */
4688: if (!ok) {
4689: U_CHAR *msg; /* what pain... */
4690:
4691: /* If we are passing through #define and #undef directives, do
4692: that for this re-definition now. */
4693: if (debug_output && op)
4694: pass_thru_directive (buf, limit, op, keyword);
4695:
4696: msg = (U_CHAR *) alloca (mdef.symlen + 22);
4697: *msg = '`';
4698: bcopy (mdef.symnam, msg + 1, mdef.symlen);
4699: strcpy ((char *) (msg + mdef.symlen + 1), "' redefined");
4700: pedwarn (msg);
4701: if (hp->type == T_MACRO)
4702: pedwarn_with_file_and_line (hp->value.defn->file, hp->value.defn->line,
4703: "this is the location of the previous definition");
4704: }
4705: /* Replace the old definition. */
4706: hp->type = T_MACRO;
4707: hp->value.defn = mdef.defn;
4708: } else {
4709: /* If we are passing through #define and #undef directives, do
4710: that for this new definition now. */
4711: if (debug_output && op)
4712: pass_thru_directive (buf, limit, op, keyword);
4713: install (mdef.symnam, mdef.symlen, T_MACRO, mdef.defn, hashcode);
4714: }
4715: }
4716:
4717: return 0;
4718:
4719: nope:
4720:
4721: return 1;
4722: }
4723:
4724: /* Check a purported macro name SYMNAME, and yield its length.
4725: USAGE is the kind of name this is intended for. */
4726:
4727: static int
4728: check_macro_name (symname, usage)
4729: U_CHAR *symname;
4730: char *usage;
4731: {
4732: U_CHAR *p;
4733: int sym_length;
4734:
4735: for (p = symname; is_idchar[*p]; p++)
4736: ;
4737: sym_length = p - symname;
4738: if (sym_length == 0)
4739: error ("invalid %s name", usage);
4740: else if (!is_idstart[*symname]) {
4741: U_CHAR *msg; /* what pain... */
4742: msg = (U_CHAR *) alloca (sym_length + 1);
4743: bcopy (symname, msg, sym_length);
4744: msg[sym_length] = 0;
4745: error ("invalid %s name `%s'", usage, msg);
4746: } else {
4747: if (! strncmp (symname, "defined", 7) && sym_length == 7)
4748: error ("invalid %s name `defined'", usage);
4749: }
4750: return sym_length;
4751: }
4752:
4753: /*
4754: * return zero if two DEFINITIONs are isomorphic
4755: */
4756: static int
4757: compare_defs (d1, d2)
4758: DEFINITION *d1, *d2;
4759: {
4760: register struct reflist *a1, *a2;
4761: register U_CHAR *p1 = d1->expansion;
4762: register U_CHAR *p2 = d2->expansion;
4763: int first = 1;
4764:
4765: if (d1->nargs != d2->nargs)
4766: return 1;
4767: if (strcmp ((char *)d1->args.argnames, (char *)d2->args.argnames))
4768: return 1;
4769: for (a1 = d1->pattern, a2 = d2->pattern; a1 && a2;
4770: a1 = a1->next, a2 = a2->next) {
4771: if (!((a1->nchars == a2->nchars && ! strncmp (p1, p2, a1->nchars))
4772: || ! comp_def_part (first, p1, a1->nchars, p2, a2->nchars, 0))
4773: || a1->argno != a2->argno
4774: || a1->stringify != a2->stringify
4775: || a1->raw_before != a2->raw_before
4776: || a1->raw_after != a2->raw_after)
4777: return 1;
4778: first = 0;
4779: p1 += a1->nchars;
4780: p2 += a2->nchars;
4781: }
4782: if (a1 != a2)
4783: return 1;
4784: if (comp_def_part (first, p1, d1->length - (p1 - d1->expansion),
4785: p2, d2->length - (p2 - d2->expansion), 1))
4786: return 1;
4787: return 0;
4788: }
4789:
4790: /* Return 1 if two parts of two macro definitions are effectively different.
4791: One of the parts starts at BEG1 and has LEN1 chars;
4792: the other has LEN2 chars at BEG2.
4793: Any sequence of whitespace matches any other sequence of whitespace.
4794: FIRST means these parts are the first of a macro definition;
4795: so ignore leading whitespace entirely.
4796: LAST means these parts are the last of a macro definition;
4797: so ignore trailing whitespace entirely. */
4798:
4799: static int
4800: comp_def_part (first, beg1, len1, beg2, len2, last)
4801: int first;
4802: U_CHAR *beg1, *beg2;
4803: int len1, len2;
4804: int last;
4805: {
4806: register U_CHAR *end1 = beg1 + len1;
4807: register U_CHAR *end2 = beg2 + len2;
4808: if (first) {
4809: while (beg1 != end1 && is_space[*beg1]) beg1++;
4810: while (beg2 != end2 && is_space[*beg2]) beg2++;
4811: }
4812: if (last) {
4813: while (beg1 != end1 && is_space[end1[-1]]) end1--;
4814: while (beg2 != end2 && is_space[end2[-1]]) end2--;
4815: }
4816: while (beg1 != end1 && beg2 != end2) {
4817: if (is_space[*beg1] && is_space[*beg2]) {
4818: while (beg1 != end1 && is_space[*beg1]) beg1++;
4819: while (beg2 != end2 && is_space[*beg2]) beg2++;
4820: } else if (*beg1 == *beg2) {
4821: beg1++; beg2++;
4822: } else break;
4823: }
4824: return (beg1 != end1) || (beg2 != end2);
4825: }
4826:
4827: /* Read a replacement list for a macro with parameters.
4828: Build the DEFINITION structure.
4829: Reads characters of text starting at BUF until END.
4830: ARGLIST specifies the formal parameters to look for
4831: in the text of the definition; NARGS is the number of args
4832: in that list, or -1 for a macro name that wants no argument list.
4833: MACRONAME is the macro name itself (so we can avoid recursive expansion)
4834: and NAMELEN is its length in characters.
4835:
4836: Note that comments and backslash-newlines have already been deleted
4837: from the argument. */
4838:
4839: /* Leading and trailing Space, Tab, etc. are converted to markers
4840: Newline Space, Newline Tab, etc.
4841: Newline Space makes a space in the final output
4842: but is discarded if stringified. (Newline Tab is similar but
4843: makes a Tab instead.)
4844:
4845: If there is no trailing whitespace, a Newline Space is added at the end
4846: to prevent concatenation that would be contrary to the standard. */
4847:
4848: static DEFINITION *
4849: collect_expansion (buf, end, nargs, arglist)
4850: U_CHAR *buf, *end;
4851: int nargs;
4852: struct arglist *arglist;
4853: {
4854: DEFINITION *defn;
4855: register U_CHAR *p, *limit, *lastp, *exp_p;
4856: struct reflist *endpat = NULL;
4857: /* Pointer to first nonspace after last ## seen. */
4858: U_CHAR *concat = 0;
4859: /* Pointer to first nonspace after last single-# seen. */
4860: U_CHAR *stringify = 0;
4861: int maxsize;
4862: int expected_delimiter = '\0';
4863:
4864: /* Scan thru the replacement list, ignoring comments and quoted
4865: strings, picking up on the macro calls. It does a linear search
4866: thru the arg list on every potential symbol. Profiling might say
4867: that something smarter should happen. */
4868:
4869: if (end < buf)
4870: abort ();
4871:
4872: /* Find the beginning of the trailing whitespace. */
4873: /* Find end of leading whitespace. */
4874: limit = end;
4875: p = buf;
4876: while (p < limit && is_space[limit[-1]]) limit--;
4877: while (p < limit && is_space[*p]) p++;
4878:
4879: /* Allocate space for the text in the macro definition.
4880: Leading and trailing whitespace chars need 2 bytes each.
4881: Each other input char may or may not need 1 byte,
4882: so this is an upper bound.
4883: The extra 2 are for invented trailing newline-marker and final null. */
4884: maxsize = (sizeof (DEFINITION)
4885: + 2 * (end - limit) + 2 * (p - buf)
4886: + (limit - p) + 3);
4887: defn = (DEFINITION *) xcalloc (1, maxsize);
4888:
4889: defn->nargs = nargs;
4890: exp_p = defn->expansion = (U_CHAR *) defn + sizeof (DEFINITION);
4891: lastp = exp_p;
4892:
4893: p = buf;
4894:
4895: /* Convert leading whitespace to Newline-markers. */
4896: while (p < limit && is_space[*p]) {
4897: *exp_p++ = '\n';
4898: *exp_p++ = *p++;
4899: }
4900:
4901: if (limit - p >= 2 && p[0] == '#' && p[1] == '#') {
4902: error ("`##' at start of macro definition");
4903: p += 2;
4904: }
4905:
4906: /* Process the main body of the definition. */
4907: while (p < limit) {
4908: int skipped_arg = 0;
4909: register U_CHAR c = *p++;
4910:
4911: *exp_p++ = c;
4912:
4913: if (!traditional) {
4914: switch (c) {
4915: case '\'':
4916: case '\"':
4917: if (expected_delimiter != '\0') {
4918: if (c == expected_delimiter)
4919: expected_delimiter = '\0';
4920: } else
4921: expected_delimiter = c;
4922: break;
4923:
4924: /* Special hack: if a \# is written in the #define
4925: include a # in the definition. This is useless for C code
4926: but useful for preprocessing other things. */
4927:
4928: case '\\':
4929: /* \# quotes a # even outside of strings. */
4930: if (p < limit && *p == '#' && !expected_delimiter) {
4931: exp_p--;
4932: *exp_p++ = *p++;
4933: } else if (p < limit && expected_delimiter) {
4934: /* In a string, backslash goes through
4935: and makes next char ordinary. */
4936: *exp_p++ = *p++;
4937: }
4938: break;
4939:
4940: case '#':
4941: /* # is ordinary inside a string. */
4942: if (expected_delimiter)
4943: break;
4944: if (p < limit && *p == '#') {
4945: /* ##: concatenate preceding and following tokens. */
4946: /* Take out the first #, discard preceding whitespace. */
4947: exp_p--;
4948: while (exp_p > lastp && is_hor_space[exp_p[-1]])
4949: --exp_p;
4950: /* Skip the second #. */
4951: p++;
4952: /* Discard following whitespace. */
4953: SKIP_WHITE_SPACE (p);
4954: concat = p;
4955: if (p == limit)
4956: error ("`##' at end of macro definition");
4957: } else {
4958: /* Single #: stringify following argument ref.
4959: Don't leave the # in the expansion. */
4960: exp_p--;
4961: SKIP_WHITE_SPACE (p);
4962: if (p == limit || ! is_idstart[*p] || nargs <= 0)
4963: error ("`#' operator is not followed by a macro argument name");
4964: else
4965: stringify = p;
4966: }
4967: break;
4968: }
4969: } else {
4970: /* In -traditional mode, recognize arguments inside strings and
4971: and character constants, and ignore special properties of #.
4972: Arguments inside strings are considered "stringified", but no
4973: extra quote marks are supplied. */
4974: switch (c) {
4975: case '\'':
4976: case '\"':
4977: if (expected_delimiter != '\0') {
4978: if (c == expected_delimiter)
4979: expected_delimiter = '\0';
4980: } else
4981: expected_delimiter = c;
4982: break;
4983:
4984: case '\\':
4985: /* Backslash quotes delimiters and itself, but not macro args. */
4986: if (expected_delimiter != 0 && p < limit
4987: && (*p == expected_delimiter || *p == '\\')) {
4988: *exp_p++ = *p++;
4989: continue;
4990: }
4991: break;
4992:
4993: case '/':
4994: if (expected_delimiter != '\0') /* No comments inside strings. */
4995: break;
4996: if (*p == '*') {
4997: /* If we find a comment that wasn't removed by handle_directive,
4998: this must be -traditional. So replace the comment with
4999: nothing at all. */
5000: exp_p--;
5001: p += 1;
5002: while (p < limit && !(p[-2] == '*' && p[-1] == '/'))
5003: p++;
5004: #if 0
5005: /* Mark this as a concatenation-point, as if it had been ##. */
5006: concat = p;
5007: #endif
5008: }
5009: break;
5010: }
5011: }
5012:
5013: /* Handle the start of a symbol. */
5014: if (is_idchar[c] && nargs > 0) {
5015: U_CHAR *id_beg = p - 1;
5016: int id_len;
5017:
5018: --exp_p;
5019: while (p != limit && is_idchar[*p]) p++;
5020: id_len = p - id_beg;
5021:
5022: if (is_idstart[c]) {
5023: register struct arglist *arg;
5024:
5025: for (arg = arglist; arg != NULL; arg = arg->next) {
5026: struct reflist *tpat;
5027:
5028: if (arg->name[0] == c
5029: && arg->length == id_len
5030: && strncmp (arg->name, id_beg, id_len) == 0) {
5031: if (expected_delimiter && warn_stringify) {
5032: if (traditional) {
5033: warning ("macro argument `%.*s' is stringified.",
5034: id_len, arg->name);
5035: } else {
5036: warning ("macro arg `%.*s' would be stringified with -traditional.",
5037: id_len, arg->name);
5038: }
5039: }
5040: /* If ANSI, don't actually substitute inside a string. */
5041: if (!traditional && expected_delimiter)
5042: break;
5043: /* make a pat node for this arg and append it to the end of
5044: the pat list */
5045: tpat = (struct reflist *) xmalloc (sizeof (struct reflist));
5046: tpat->next = NULL;
5047: tpat->raw_before = concat == id_beg;
5048: tpat->raw_after = 0;
5049: tpat->stringify = (traditional ? expected_delimiter != '\0'
5050: : stringify == id_beg);
5051:
5052: if (endpat == NULL)
5053: defn->pattern = tpat;
5054: else
5055: endpat->next = tpat;
5056: endpat = tpat;
5057:
5058: tpat->argno = arg->argno;
5059: tpat->nchars = exp_p - lastp;
5060: {
5061: register U_CHAR *p1 = p;
5062: SKIP_WHITE_SPACE (p1);
5063: if (p1 + 2 <= limit && p1[0] == '#' && p1[1] == '#')
5064: tpat->raw_after = 1;
5065: }
5066: lastp = exp_p; /* place to start copying from next time */
5067: skipped_arg = 1;
5068: break;
5069: }
5070: }
5071: }
5072:
5073: /* If this was not a macro arg, copy it into the expansion. */
5074: if (! skipped_arg) {
5075: register U_CHAR *lim1 = p;
5076: p = id_beg;
5077: while (p != lim1)
5078: *exp_p++ = *p++;
5079: if (stringify == id_beg)
5080: error ("`#' operator should be followed by a macro argument name");
5081: }
5082: }
5083: }
5084:
5085: if (limit < end) {
5086: /* Convert trailing whitespace to Newline-markers. */
5087: while (limit < end && is_space[*limit]) {
5088: *exp_p++ = '\n';
5089: *exp_p++ = *limit++;
5090: }
5091: } else if (!traditional) {
5092: /* There is no trailing whitespace, so invent some. */
5093: *exp_p++ = '\n';
5094: *exp_p++ = ' ';
5095: }
5096:
5097: *exp_p = '\0';
5098:
5099: defn->length = exp_p - defn->expansion;
5100:
5101: /* Crash now if we overrun the allocated size. */
5102: if (defn->length + 1 > maxsize)
5103: abort ();
5104:
5105: #if 0
5106: /* This isn't worth the time it takes. */
5107: /* give back excess storage */
5108: defn->expansion = (U_CHAR *) xrealloc (defn->expansion, defn->length + 1);
5109: #endif
5110:
5111: return defn;
5112: }
5113:
5114: static int
5115: do_assert (buf, limit, op, keyword)
5116: U_CHAR *buf, *limit;
5117: FILE_BUF *op;
5118: struct directive *keyword;
5119: {
5120: U_CHAR *bp; /* temp ptr into input buffer */
5121: U_CHAR *symname; /* remember where symbol name starts */
5122: int sym_length; /* and how long it is */
5123: struct arglist *tokens = NULL;
5124:
5125: if (pedantic && done_initializing && !instack[indepth].system_header_p)
5126: pedwarn ("ANSI C does not allow `#assert'");
5127:
5128: bp = buf;
5129:
5130: while (is_hor_space[*bp])
5131: bp++;
5132:
5133: symname = bp; /* remember where it starts */
5134: sym_length = check_macro_name (bp, "assertion");
5135: bp += sym_length;
5136: /* #define doesn't do this, but we should. */
5137: SKIP_WHITE_SPACE (bp);
5138:
5139: /* Lossage will occur if identifiers or control tokens are broken
5140: across lines using backslash. This is not the right place to take
5141: care of that. */
5142:
5143: if (*bp != '(') {
5144: error ("missing token-sequence in `#assert'");
5145: return 1;
5146: }
5147:
5148: {
5149: int error_flag = 0;
5150:
5151: bp++; /* skip '(' */
5152: SKIP_WHITE_SPACE (bp);
5153:
5154: tokens = read_token_list (&bp, limit, &error_flag);
5155: if (error_flag)
5156: return 1;
5157: if (tokens == 0) {
5158: error ("empty token-sequence in `#assert'");
5159: return 1;
5160: }
5161:
5162: ++bp; /* skip paren */
5163: SKIP_WHITE_SPACE (bp);
5164: }
5165:
5166: /* If this name isn't already an assertion name, make it one.
5167: Error if it was already in use in some other way. */
5168:
5169: {
5170: ASSERTION_HASHNODE *hp;
5171: int hashcode = hashf (symname, sym_length, ASSERTION_HASHSIZE);
5172: struct tokenlist_list *value
5173: = (struct tokenlist_list *) xmalloc (sizeof (struct tokenlist_list));
5174:
5175: hp = assertion_lookup (symname, sym_length, hashcode);
5176: if (hp == NULL) {
5177: if (sym_length == 7 && ! strncmp (symname, "defined", sym_length))
5178: error ("`defined' redefined as assertion");
5179: hp = assertion_install (symname, sym_length, hashcode);
5180: }
5181:
5182: /* Add the spec'd token-sequence to the list of such. */
5183: value->tokens = tokens;
5184: value->next = hp->value;
5185: hp->value = value;
5186: }
5187:
5188: return 0;
5189: }
5190:
5191: static int
5192: do_unassert (buf, limit, op, keyword)
5193: U_CHAR *buf, *limit;
5194: FILE_BUF *op;
5195: struct directive *keyword;
5196: {
5197: U_CHAR *bp; /* temp ptr into input buffer */
5198: U_CHAR *symname; /* remember where symbol name starts */
5199: int sym_length; /* and how long it is */
5200:
5201: struct arglist *tokens = NULL;
5202: int tokens_specified = 0;
5203:
5204: if (pedantic && done_initializing && !instack[indepth].system_header_p)
5205: pedwarn ("ANSI C does not allow `#unassert'");
5206:
5207: bp = buf;
5208:
5209: while (is_hor_space[*bp])
5210: bp++;
5211:
5212: symname = bp; /* remember where it starts */
5213: sym_length = check_macro_name (bp, "assertion");
5214: bp += sym_length;
5215: /* #define doesn't do this, but we should. */
5216: SKIP_WHITE_SPACE (bp);
5217:
5218: /* Lossage will occur if identifiers or control tokens are broken
5219: across lines using backslash. This is not the right place to take
5220: care of that. */
5221:
5222: if (*bp == '(') {
5223: int error_flag = 0;
5224:
5225: bp++; /* skip '(' */
5226: SKIP_WHITE_SPACE (bp);
5227:
5228: tokens = read_token_list (&bp, limit, &error_flag);
5229: if (error_flag)
5230: return 1;
5231: if (tokens == 0) {
5232: error ("empty token list in `#unassert'");
5233: return 1;
5234: }
5235:
5236: tokens_specified = 1;
5237:
5238: ++bp; /* skip paren */
5239: SKIP_WHITE_SPACE (bp);
5240: }
5241:
5242: {
5243: ASSERTION_HASHNODE *hp;
5244: int hashcode = hashf (symname, sym_length, ASSERTION_HASHSIZE);
5245: struct tokenlist_list *tail, *prev;
5246:
5247: hp = assertion_lookup (symname, sym_length, hashcode);
5248: if (hp == NULL)
5249: return 1;
5250:
5251: /* If no token list was specified, then eliminate this assertion
5252: entirely. */
5253: if (! tokens_specified) {
5254: struct tokenlist_list *next;
5255: for (tail = hp->value; tail; tail = next) {
5256: next = tail->next;
5257: free_token_list (tail->tokens);
5258: free (tail);
5259: }
5260: delete_assertion (hp);
5261: } else {
5262: /* If a list of tokens was given, then delete any matching list. */
5263:
5264: tail = hp->value;
5265: prev = 0;
5266: while (tail) {
5267: struct tokenlist_list *next = tail->next;
5268: if (compare_token_lists (tail->tokens, tokens)) {
5269: if (prev)
5270: prev->next = next;
5271: else
5272: hp->value = tail->next;
5273: free_token_list (tail->tokens);
5274: free (tail);
5275: } else {
5276: prev = tail;
5277: }
5278: tail = next;
5279: }
5280: }
5281: }
5282:
5283: return 0;
5284: }
5285:
5286: /* Test whether there is an assertion named NAME
5287: and optionally whether it has an asserted token list TOKENS.
5288: NAME is not null terminated; its length is SYM_LENGTH.
5289: If TOKENS_SPECIFIED is 0, then don't check for any token list. */
5290:
5291: int
5292: check_assertion (name, sym_length, tokens_specified, tokens)
5293: U_CHAR *name;
5294: int sym_length;
5295: int tokens_specified;
5296: struct arglist *tokens;
5297: {
5298: ASSERTION_HASHNODE *hp;
5299: int hashcode = hashf (name, sym_length, ASSERTION_HASHSIZE);
5300:
5301: if (pedantic && !instack[indepth].system_header_p)
5302: pedwarn ("ANSI C does not allow testing assertions");
5303:
5304: hp = assertion_lookup (name, sym_length, hashcode);
5305: if (hp == NULL)
5306: /* It is not an assertion; just return false. */
5307: return 0;
5308:
5309: /* If no token list was specified, then value is 1. */
5310: if (! tokens_specified)
5311: return 1;
5312:
5313: {
5314: struct tokenlist_list *tail;
5315:
5316: tail = hp->value;
5317:
5318: /* If a list of tokens was given,
5319: then succeed if the assertion records a matching list. */
5320:
5321: while (tail) {
5322: if (compare_token_lists (tail->tokens, tokens))
5323: return 1;
5324: tail = tail->next;
5325: }
5326:
5327: /* Fail if the assertion has no matching list. */
5328: return 0;
5329: }
5330: }
5331:
5332: /* Compare two lists of tokens for equality including order of tokens. */
5333:
5334: static int
5335: compare_token_lists (l1, l2)
5336: struct arglist *l1, *l2;
5337: {
5338: while (l1 && l2) {
5339: if (l1->length != l2->length)
5340: return 0;
5341: if (strncmp (l1->name, l2->name, l1->length))
5342: return 0;
5343: l1 = l1->next;
5344: l2 = l2->next;
5345: }
5346:
5347: /* Succeed if both lists end at the same time. */
5348: return l1 == l2;
5349: }
5350:
5351: /* Read a space-separated list of tokens ending in a close parenthesis.
5352: Return a list of strings, in the order they were written.
5353: (In case of error, return 0 and store -1 in *ERROR_FLAG.)
5354: Parse the text starting at *BPP, and update *BPP.
5355: Don't parse beyond LIMIT. */
5356:
5357: static struct arglist *
5358: read_token_list (bpp, limit, error_flag)
5359: U_CHAR **bpp;
5360: U_CHAR *limit;
5361: int *error_flag;
5362: {
5363: struct arglist *token_ptrs = 0;
5364: U_CHAR *bp = *bpp;
5365: int depth = 1;
5366:
5367: *error_flag = 0;
5368:
5369: /* Loop over the assertion value tokens. */
5370: while (depth > 0) {
5371: struct arglist *temp;
5372: int eofp = 0;
5373: U_CHAR *beg = bp;
5374:
5375: /* Find the end of the token. */
5376: if (*bp == '(') {
5377: bp++;
5378: depth++;
5379: } else if (*bp == ')') {
5380: depth--;
5381: if (depth == 0)
5382: break;
5383: bp++;
5384: } else if (*bp == '"' || *bp == '\'')
5385: bp = skip_quoted_string (bp, limit, 0, 0, 0, &eofp);
5386: else
5387: while (! is_hor_space[*bp] && *bp != '(' && *bp != ')'
5388: && *bp != '"' && *bp != '\'' && bp != limit)
5389: bp++;
5390:
5391: temp = (struct arglist *) xmalloc (sizeof (struct arglist));
5392: temp->name = (U_CHAR *) xmalloc (bp - beg + 1);
5393: bcopy (beg, temp->name, bp - beg);
5394: temp->name[bp - beg] = 0;
5395: temp->next = token_ptrs;
5396: token_ptrs = temp;
5397: temp->length = bp - beg;
5398:
5399: SKIP_WHITE_SPACE (bp);
5400:
5401: if (bp >= limit) {
5402: error ("unterminated token sequence in `#assert' or `#unassert'");
5403: *error_flag = -1;
5404: return 0;
5405: }
5406: }
5407: *bpp = bp;
5408:
5409: /* We accumulated the names in reverse order.
5410: Now reverse them to get the proper order. */
5411: {
5412: register struct arglist *prev = 0, *this, *next;
5413: for (this = token_ptrs; this; this = next) {
5414: next = this->next;
5415: this->next = prev;
5416: prev = this;
5417: }
5418: return prev;
5419: }
5420: }
5421:
5422: static void
5423: free_token_list (tokens)
5424: struct arglist *tokens;
5425: {
5426: while (tokens) {
5427: struct arglist *next = tokens->next;
5428: free (tokens->name);
5429: free (tokens);
5430: tokens = next;
5431: }
5432: }
5433:
5434: /*
5435: * Install a name in the assertion hash table.
5436: *
5437: * If LEN is >= 0, it is the length of the name.
5438: * Otherwise, compute the length by scanning the entire name.
5439: *
5440: * If HASH is >= 0, it is the precomputed hash code.
5441: * Otherwise, compute the hash code.
5442: */
5443: static ASSERTION_HASHNODE *
5444: assertion_install (name, len, hash)
5445: U_CHAR *name;
5446: int len;
5447: int hash;
5448: {
5449: register ASSERTION_HASHNODE *hp;
5450: register int i, bucket;
5451: register U_CHAR *p, *q;
5452:
5453: i = sizeof (ASSERTION_HASHNODE) + len + 1;
5454: hp = (ASSERTION_HASHNODE *) xmalloc (i);
5455: bucket = hash;
5456: hp->bucket_hdr = &assertion_hashtab[bucket];
5457: hp->next = assertion_hashtab[bucket];
5458: assertion_hashtab[bucket] = hp;
5459: hp->prev = NULL;
5460: if (hp->next != NULL)
5461: hp->next->prev = hp;
5462: hp->length = len;
5463: hp->value = 0;
5464: hp->name = ((U_CHAR *) hp) + sizeof (ASSERTION_HASHNODE);
5465: p = hp->name;
5466: q = name;
5467: for (i = 0; i < len; i++)
5468: *p++ = *q++;
5469: hp->name[len] = 0;
5470: return hp;
5471: }
5472:
5473: /*
5474: * find the most recent hash node for name name (ending with first
5475: * non-identifier char) installed by install
5476: *
5477: * If LEN is >= 0, it is the length of the name.
5478: * Otherwise, compute the length by scanning the entire name.
5479: *
5480: * If HASH is >= 0, it is the precomputed hash code.
5481: * Otherwise, compute the hash code.
5482: */
5483: static ASSERTION_HASHNODE *
5484: assertion_lookup (name, len, hash)
5485: U_CHAR *name;
5486: int len;
5487: int hash;
5488: {
5489: register U_CHAR *bp;
5490: register ASSERTION_HASHNODE *bucket;
5491:
5492: bucket = assertion_hashtab[hash];
5493: while (bucket) {
5494: if (bucket->length == len && strncmp (bucket->name, name, len) == 0)
5495: return bucket;
5496: bucket = bucket->next;
5497: }
5498: return NULL;
5499: }
5500:
5501: static void
5502: delete_assertion (hp)
5503: ASSERTION_HASHNODE *hp;
5504: {
5505:
5506: if (hp->prev != NULL)
5507: hp->prev->next = hp->next;
5508: if (hp->next != NULL)
5509: hp->next->prev = hp->prev;
5510:
5511: /* make sure that the bucket chain header that
5512: the deleted guy was on points to the right thing afterwards. */
5513: if (hp == *hp->bucket_hdr)
5514: *hp->bucket_hdr = hp->next;
5515:
5516: free (hp);
5517: }
5518:
5519: /*
5520: * interpret #line command. Remembers previously seen fnames
5521: * in its very own hash table.
5522: */
5523: #define FNAME_HASHSIZE 37
5524:
5525: static int
5526: do_line (buf, limit, op, keyword)
5527: U_CHAR *buf, *limit;
5528: FILE_BUF *op;
5529: struct directive *keyword;
5530: {
5531: register U_CHAR *bp;
5532: FILE_BUF *ip = &instack[indepth];
5533: FILE_BUF tem;
5534: int new_lineno;
5535: enum file_change_code file_change = same_file;
5536:
5537: /* Expand any macros. */
5538: tem = expand_to_temp_buffer (buf, limit, 0, 0);
5539:
5540: /* Point to macroexpanded line, which is null-terminated now. */
5541: bp = tem.buf;
5542: SKIP_WHITE_SPACE (bp);
5543:
5544: if (!isdigit (*bp)) {
5545: error ("invalid format `#line' command");
5546: return 0;
5547: }
5548:
5549: /* The Newline at the end of this line remains to be processed.
5550: To put the next line at the specified line number,
5551: we must store a line number now that is one less. */
5552: new_lineno = atoi (bp) - 1;
5553:
5554: /* skip over the line number. */
5555: while (isdigit (*bp))
5556: bp++;
5557:
5558: #if 0 /* #line 10"foo.c" is supposed to be allowed. */
5559: if (*bp && !is_space[*bp]) {
5560: error ("invalid format `#line' command");
5561: return;
5562: }
5563: #endif
5564:
5565: SKIP_WHITE_SPACE (bp);
5566:
5567: if (*bp == '\"') {
5568: static HASHNODE *fname_table[FNAME_HASHSIZE];
5569: HASHNODE *hp, **hash_bucket;
5570: U_CHAR *fname;
5571: int fname_length;
5572:
5573: fname = ++bp;
5574:
5575: while (*bp && *bp != '\"')
5576: bp++;
5577: if (*bp != '\"') {
5578: error ("invalid format `#line' command");
5579: return 0;
5580: }
5581:
5582: fname_length = bp - fname;
5583:
5584: bp++;
5585: SKIP_WHITE_SPACE (bp);
5586: if (*bp) {
5587: if (*bp == '1')
5588: file_change = enter_file;
5589: else if (*bp == '2')
5590: file_change = leave_file;
1.1.1.2 ! root 5591: else if (*bp == '3')
! 5592: ip->system_header_p = 1;
1.1 root 5593: else {
5594: error ("invalid format `#line' command");
5595: return 0;
5596: }
5597:
5598: bp++;
5599: SKIP_WHITE_SPACE (bp);
1.1.1.2 ! root 5600: if (*bp == '3') {
! 5601: ip->system_header_p = 1;
! 5602: bp++;
! 5603: SKIP_WHITE_SPACE (bp);
! 5604: }
1.1 root 5605: if (*bp) {
5606: error ("invalid format `#line' command");
5607: return 0;
5608: }
5609: }
5610:
5611: hash_bucket =
5612: &fname_table[hashf (fname, fname_length, FNAME_HASHSIZE)];
5613: for (hp = *hash_bucket; hp != NULL; hp = hp->next)
5614: if (hp->length == fname_length &&
5615: strncmp (hp->value.cpval, fname, fname_length) == 0) {
5616: ip->nominal_fname = hp->value.cpval;
5617: break;
5618: }
5619: if (hp == 0) {
5620: /* Didn't find it; cons up a new one. */
5621: hp = (HASHNODE *) xcalloc (1, sizeof (HASHNODE) + fname_length + 1);
5622: hp->next = *hash_bucket;
5623: *hash_bucket = hp;
5624:
5625: hp->length = fname_length;
5626: ip->nominal_fname = hp->value.cpval = ((char *) hp) + sizeof (HASHNODE);
5627: bcopy (fname, hp->value.cpval, fname_length);
5628: }
5629: } else if (*bp) {
5630: error ("invalid format `#line' command");
5631: return 0;
5632: }
5633:
5634: ip->lineno = new_lineno;
5635: output_line_command (ip, op, 0, file_change);
5636: check_expand (op, ip->length - (ip->bufp - ip->buf));
5637: return 0;
5638: }
5639:
5640: /*
5641: * remove the definition of a symbol from the symbol table.
5642: * according to un*x /lib/cpp, it is not an error to undef
5643: * something that has no definitions, so it isn't one here either.
5644: */
5645:
5646: static int
5647: do_undef (buf, limit, op, keyword)
5648: U_CHAR *buf, *limit;
5649: FILE_BUF *op;
5650: struct directive *keyword;
5651: {
5652: int sym_length;
5653: HASHNODE *hp;
5654: U_CHAR *orig_buf = buf;
5655:
5656: /* If this is a precompiler run (with -pcp) pass thru #undef commands. */
5657: if (pcp_outfile && op)
5658: pass_thru_directive (buf, limit, op, keyword);
5659:
5660: SKIP_WHITE_SPACE (buf);
5661: sym_length = check_macro_name (buf, "macro");
5662:
5663: while ((hp = lookup (buf, sym_length, -1)) != NULL) {
5664: /* If we are generating additional info for debugging (with -g) we
5665: need to pass through all effective #undef commands. */
5666: if (debug_output && op)
5667: pass_thru_directive (orig_buf, limit, op, keyword);
5668: if (hp->type != T_MACRO)
5669: warning ("undefining `%s'", hp->name);
5670: delete_macro (hp);
5671: }
5672:
5673: if (pedantic) {
5674: buf += sym_length;
5675: SKIP_WHITE_SPACE (buf);
5676: if (buf != limit)
5677: pedwarn ("garbage after `#undef' directive");
5678: }
5679: return 0;
5680: }
5681:
5682: /*
5683: * Report a fatal error detected by the program we are processing.
5684: * Use the text of the line in the error message, then terminate.
5685: * (We use error() because it prints the filename & line#.)
5686: */
5687:
5688: static int
5689: do_error (buf, limit, op, keyword)
5690: U_CHAR *buf, *limit;
5691: FILE_BUF *op;
5692: struct directive *keyword;
5693: {
5694: int length = limit - buf;
5695: char *copy = (char *) xmalloc (length + 1);
5696: bcopy (buf, copy, length);
5697: copy[length] = 0;
5698: SKIP_WHITE_SPACE (copy);
5699: error ("#error %s", copy);
5700: exit (FAILURE_EXIT_CODE);
5701: /* NOTREACHED */
5702: return 0;
5703: }
5704:
5705: /*
5706: * Report a warning detected by the program we are processing.
5707: * Use the text of the line in the warning message, then continue.
5708: * (We use error() because it prints the filename & line#.)
5709: */
5710:
5711: static int
5712: do_warning (buf, limit, op, keyword)
5713: U_CHAR *buf, *limit;
5714: FILE_BUF *op;
5715: struct directive *keyword;
5716: {
5717: int length = limit - buf;
5718: char *copy = (char *) xmalloc (length + 1);
5719: bcopy (buf, copy, length);
5720: copy[length] = 0;
5721: SKIP_WHITE_SPACE (copy);
5722: error ("#warning %s", copy);
5723: return 0;
5724: }
5725:
5726: /* Remember the name of the current file being read from so that we can
5727: avoid ever including it again. */
5728:
5729: static int
5730: do_once ()
5731: {
5732: int i;
5733: FILE_BUF *ip = NULL;
5734:
5735: for (i = indepth; i >= 0; i--)
5736: if (instack[i].fname != NULL) {
5737: ip = &instack[i];
5738: break;
5739: }
5740:
5741: if (ip != NULL) {
5742: struct file_name_list *new;
5743:
5744: new = (struct file_name_list *) xmalloc (sizeof (struct file_name_list));
5745: new->next = dont_repeat_files;
5746: dont_repeat_files = new;
5747: new->fname = savestring (ip->fname);
5748: new->control_macro = 0;
5749: }
5750: return 0;
5751: }
5752:
5753: /* #ident has already been copied to the output file, so just ignore it. */
5754:
5755: static int
5756: do_ident (buf, limit)
5757: U_CHAR *buf, *limit;
5758: {
5759: /* Allow #ident in system headers, since that's not user's fault. */
5760: if (pedantic && !instack[indepth].system_header_p)
5761: pedwarn ("ANSI C does not allow `#ident'");
5762: return 0;
5763: }
5764:
5765: /* #pragma and its argument line have already been copied to the output file.
5766: Here just check for recognized pragmas. */
5767:
5768: static int
5769: do_pragma (buf, limit)
5770: U_CHAR *buf, *limit;
5771: {
5772: while (*buf == ' ' || *buf == '\t')
5773: buf++;
5774: if (!strncmp (buf, "once", 4)) {
5775: warning ("`#pragma once' is obsolete");
5776: do_once ();
5777: }
5778: return 0;
5779: }
5780:
5781: #if 0
5782: /* This was a fun hack, but #pragma seems to start to be useful.
5783: By failing to recognize it, we pass it through unchanged to cc1. */
5784:
5785: /*
5786: * the behavior of the #pragma directive is implementation defined.
5787: * this implementation defines it as follows.
5788: */
5789:
5790: static int
5791: do_pragma ()
5792: {
5793: close (0);
5794: if (open ("/dev/tty", O_RDONLY, 0666) != 0)
5795: goto nope;
5796: close (1);
5797: if (open ("/dev/tty", O_WRONLY, 0666) != 1)
5798: goto nope;
5799: execl ("/usr/games/hack", "#pragma", 0);
5800: execl ("/usr/games/rogue", "#pragma", 0);
5801: execl ("/usr/new/emacs", "-f", "hanoi", "9", "-kill", 0);
5802: execl ("/usr/local/emacs", "-f", "hanoi", "9", "-kill", 0);
5803: nope:
5804: fatal ("You are in a maze of twisty compiler features, all different");
5805: }
5806: #endif
5807:
5808: /* Just ignore #sccs, on systems where we define it at all. */
5809:
5810: static int
5811: do_sccs ()
5812: {
5813: if (pedantic)
5814: pedwarn ("ANSI C does not allow `#sccs'");
5815: return 0;
5816: }
5817:
5818: /*
5819: * handle #if command by
5820: * 1) inserting special `defined' keyword into the hash table
5821: * that gets turned into 0 or 1 by special_symbol (thus,
5822: * if the luser has a symbol called `defined' already, it won't
5823: * work inside the #if command)
5824: * 2) rescan the input into a temporary output buffer
5825: * 3) pass the output buffer to the yacc parser and collect a value
5826: * 4) clean up the mess left from steps 1 and 2.
5827: * 5) call conditional_skip to skip til the next #endif (etc.),
5828: * or not, depending on the value from step 3.
5829: */
5830:
5831: static int
5832: do_if (buf, limit, op, keyword)
5833: U_CHAR *buf, *limit;
5834: FILE_BUF *op;
5835: struct directive *keyword;
5836: {
5837: int value;
5838: FILE_BUF *ip = &instack[indepth];
5839:
5840: value = eval_if_expression (buf, limit - buf);
5841: conditional_skip (ip, value == 0, T_IF, 0);
5842: return 0;
5843: }
5844:
5845: /*
5846: * handle a #elif directive by not changing if_stack either.
5847: * see the comment above do_else.
5848: */
5849:
5850: static int
5851: do_elif (buf, limit, op, keyword)
5852: U_CHAR *buf, *limit;
5853: FILE_BUF *op;
5854: struct directive *keyword;
5855: {
5856: int value;
5857: FILE_BUF *ip = &instack[indepth];
5858:
5859: if (if_stack == instack[indepth].if_stack) {
5860: error ("`#elif' not within a conditional");
5861: return 0;
5862: } else {
5863: if (if_stack->type != T_IF && if_stack->type != T_ELIF) {
5864: error ("`#elif' after `#else'");
5865: fprintf (stderr, " (matches line %d", if_stack->lineno);
5866: if (if_stack->fname != NULL && ip->fname != NULL &&
5867: strcmp (if_stack->fname, ip->nominal_fname) != 0)
5868: fprintf (stderr, ", file %s", if_stack->fname);
5869: fprintf (stderr, ")\n");
5870: }
5871: if_stack->type = T_ELIF;
5872: }
5873:
5874: if (if_stack->if_succeeded)
5875: skip_if_group (ip, 0);
5876: else {
5877: value = eval_if_expression (buf, limit - buf);
5878: if (value == 0)
5879: skip_if_group (ip, 0);
5880: else {
5881: ++if_stack->if_succeeded; /* continue processing input */
5882: output_line_command (ip, op, 1, same_file);
5883: }
5884: }
5885: return 0;
5886: }
5887:
5888: /*
5889: * evaluate a #if expression in BUF, of length LENGTH,
5890: * then parse the result as a C expression and return the value as an int.
5891: */
5892: static int
5893: eval_if_expression (buf, length)
5894: U_CHAR *buf;
5895: int length;
5896: {
5897: FILE_BUF temp_obuf;
5898: HASHNODE *save_defined;
5899: int value;
5900:
5901: save_defined = install ("defined", -1, T_SPEC_DEFINED, 0, -1);
5902: pcp_inside_if = 1;
5903: temp_obuf = expand_to_temp_buffer (buf, buf + length, 0, 1);
5904: pcp_inside_if = 0;
5905: delete_macro (save_defined); /* clean up special symbol */
5906:
5907: value = parse_c_expression (temp_obuf.buf);
5908:
5909: free (temp_obuf.buf);
5910:
5911: return value;
5912: }
5913:
5914: /*
5915: * routine to handle ifdef/ifndef. Try to look up the symbol,
5916: * then do or don't skip to the #endif/#else/#elif depending
5917: * on what directive is actually being processed.
5918: */
5919:
5920: static int
5921: do_xifdef (buf, limit, op, keyword)
5922: U_CHAR *buf, *limit;
5923: FILE_BUF *op;
5924: struct directive *keyword;
5925: {
5926: int skip;
5927: FILE_BUF *ip = &instack[indepth];
5928: U_CHAR *end;
5929: int start_of_file = 0;
5930: U_CHAR *control_macro = 0;
5931:
5932: /* Detect a #ifndef at start of file (not counting comments). */
5933: if (ip->fname != 0 && keyword->type == T_IFNDEF) {
5934: U_CHAR *p = ip->buf;
5935: while (p != directive_start) {
5936: char c = *p++;
5937: switch (c) {
5938: case ' ':
5939: case '\t':
5940: case '\n':
5941: break;
5942: case '/':
5943: if (p != ip->bufp && *p == '*') {
5944: /* Skip this comment. */
5945: int junk;
5946: U_CHAR *save_bufp = ip->bufp;
5947: ip->bufp = p + 1;
1.1.1.2 ! root 5948: p = skip_to_end_of_comment (ip, &junk, 1);
1.1 root 5949: ip->bufp = save_bufp;
5950: }
5951: break;
5952: default:
5953: goto fail;
5954: }
5955: }
5956: /* If we get here, this conditional is the beginning of the file. */
5957: start_of_file = 1;
5958: fail: ;
5959: }
5960:
5961: /* Discard leading and trailing whitespace. */
5962: SKIP_WHITE_SPACE (buf);
5963: while (limit != buf && is_hor_space[limit[-1]]) limit--;
5964:
5965: /* Find the end of the identifier at the beginning. */
5966: for (end = buf; is_idchar[*end]; end++);
5967:
5968: if (end == buf) {
5969: skip = (keyword->type == T_IFDEF);
5970: if (! traditional)
5971: pedwarn (end == limit ? "`#%s' with no argument"
5972: : "`#%s' argument starts with punctuation",
5973: keyword->name);
5974: } else {
5975: HASHNODE *hp;
5976:
5977: if (pedantic && buf[0] >= '0' && buf[0] <= '9')
5978: pedwarn ("`#%s' argument starts with a digit", keyword->name);
5979: else if (end != limit && !traditional)
5980: pedwarn ("garbage at end of `#%s' argument", keyword->name);
5981:
5982: hp = lookup (buf, end-buf, -1);
5983:
5984: if (pcp_outfile) {
5985: /* Output a precondition for this macro. */
5986: if (hp && hp->value.defn->predefined)
5987: fprintf(pcp_outfile, "#define %s\n", hp->name);
5988: else {
5989: U_CHAR *cp = buf;
5990: fprintf(pcp_outfile, "#undef ");
5991: while (is_idchar[*cp]) /* Ick! */
5992: fputc (*cp++, pcp_outfile);
5993: putc ('\n', pcp_outfile);
5994: }
5995: }
5996:
5997: skip = (hp == NULL) ^ (keyword->type == T_IFNDEF);
5998: if (start_of_file && !skip) {
5999: control_macro = (U_CHAR *) xmalloc (end - buf + 1);
6000: bcopy (buf, control_macro, end - buf);
6001: control_macro[end - buf] = 0;
6002: }
6003: }
6004:
6005: conditional_skip (ip, skip, T_IF, control_macro);
6006: return 0;
6007: }
6008:
6009: /* Push TYPE on stack; then, if SKIP is nonzero, skip ahead.
6010: If this is a #ifndef starting at the beginning of a file,
6011: CONTROL_MACRO is the macro name tested by the #ifndef.
6012: Otherwise, CONTROL_MACRO is 0. */
6013:
6014: static void
6015: conditional_skip (ip, skip, type, control_macro)
6016: FILE_BUF *ip;
6017: int skip;
6018: enum node_type type;
6019: U_CHAR *control_macro;
6020: {
6021: IF_STACK_FRAME *temp;
6022:
6023: temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME));
6024: temp->fname = ip->nominal_fname;
6025: temp->lineno = ip->lineno;
6026: temp->next = if_stack;
6027: temp->control_macro = control_macro;
6028: if_stack = temp;
6029:
6030: if_stack->type = type;
6031:
6032: if (skip != 0) {
6033: skip_if_group (ip, 0);
6034: return;
6035: } else {
6036: ++if_stack->if_succeeded;
6037: output_line_command (ip, &outbuf, 1, same_file);
6038: }
6039: }
6040:
6041: /*
6042: * skip to #endif, #else, or #elif. adjust line numbers, etc.
6043: * leaves input ptr at the sharp sign found.
6044: * If ANY is nonzero, return at next directive of any sort.
6045: */
6046: static void
6047: skip_if_group (ip, any)
6048: FILE_BUF *ip;
6049: int any;
6050: {
6051: register U_CHAR *bp = ip->bufp, *cp;
6052: register U_CHAR *endb = ip->buf + ip->length;
6053: struct directive *kt;
6054: IF_STACK_FRAME *save_if_stack = if_stack; /* don't pop past here */
6055: U_CHAR *beg_of_line = bp;
6056: register int ident_length;
6057: U_CHAR *ident, *after_ident;
6058:
6059: while (bp < endb) {
6060: switch (*bp++) {
6061: case '/': /* possible comment */
6062: if (*bp == '\\' && bp[1] == '\n')
6063: newline_fix (bp);
6064: if (*bp == '*'
6065: || ((cplusplus || objc) && *bp == '/')) {
6066: ip->bufp = ++bp;
1.1.1.2 ! root 6067: bp = skip_to_end_of_comment (ip, &ip->lineno, 0);
1.1 root 6068: }
6069: break;
6070: case '\"':
6071: case '\'':
6072: bp = skip_quoted_string (bp - 1, endb, ip->lineno, &ip->lineno, 0, 0);
6073: break;
6074: case '\\':
6075: /* Char after backslash loses its special meaning. */
6076: if (bp < endb) {
6077: if (*bp == '\n')
6078: ++ip->lineno; /* But do update the line-count. */
6079: bp++;
6080: }
6081: break;
6082: case '\n':
6083: ++ip->lineno;
6084: beg_of_line = bp;
6085: break;
6086: case '#':
6087: ip->bufp = bp - 1;
6088:
6089: /* # keyword: a # must be first nonblank char on the line */
6090: if (beg_of_line == 0)
6091: break;
6092: /* Scan from start of line, skipping whitespace, comments
6093: and backslash-newlines, and see if we reach this #.
6094: If not, this # is not special. */
6095: bp = beg_of_line;
6096: while (1) {
6097: if (is_hor_space[*bp])
6098: bp++;
6099: else if (*bp == '\\' && bp[1] == '\n')
6100: bp += 2;
6101: else if (*bp == '/' && bp[1] == '*') {
6102: bp += 2;
6103: while (!(*bp == '*' && bp[1] == '/'))
6104: bp++;
6105: bp += 2;
6106: } else if ((cplusplus || objc) && *bp == '/' && bp[1] == '/') {
6107: bp += 2;
6108: while (*bp++ != '\n') ;
6109: }
6110: else break;
6111: }
6112: if (bp != ip->bufp) {
6113: bp = ip->bufp + 1; /* Reset bp to after the #. */
6114: break;
6115: }
6116:
6117: bp = ip->bufp + 1; /* Point after the '#' */
6118:
6119: /* Skip whitespace and \-newline. */
6120: while (1) {
6121: if (is_hor_space[*bp])
6122: bp++;
6123: else if (*bp == '\\' && bp[1] == '\n')
6124: bp += 2;
6125: else if (*bp == '/' && bp[1] == '*') {
6126: bp += 2;
6127: while (!(*bp == '*' && bp[1] == '/')) {
6128: if (*bp == '\n')
6129: ip->lineno++;
6130: bp++;
6131: }
6132: bp += 2;
6133: } else if ((cplusplus || objc) && *bp == '/' && bp[1] == '/') {
6134: bp += 2;
6135: while (*bp++ != '\n') ;
6136: }
6137: else break;
6138: }
6139:
6140: cp = bp;
6141:
6142: /* Now find end of directive name.
6143: If we encounter a backslash-newline, exchange it with any following
6144: symbol-constituents so that we end up with a contiguous name. */
6145:
6146: while (1) {
6147: if (is_idchar[*bp])
6148: bp++;
6149: else {
6150: if (*bp == '\\' && bp[1] == '\n')
6151: name_newline_fix (bp);
6152: if (is_idchar[*bp])
6153: bp++;
6154: else break;
6155: }
6156: }
6157: ident_length = bp - cp;
6158: ident = cp;
6159: after_ident = bp;
6160:
6161: /* A line of just `#' becomes blank. */
6162:
6163: if (ident_length == 0 && *after_ident == '\n') {
6164: continue;
6165: }
6166:
6167: if (ident_length == 0 || !is_idstart[*ident]) {
6168: U_CHAR *p = ident;
6169: while (is_idchar[*p]) {
6170: if (*p < '0' || *p > '9')
6171: break;
6172: p++;
6173: }
6174: /* Handle # followed by a line number. */
6175: if (p != ident && !is_idchar[*p]) {
6176: if (pedantic)
6177: pedwarn ("`#' followed by integer");
6178: continue;
6179: }
6180:
6181: /* Avoid error for `###' and similar cases unless -pedantic. */
6182: if (p == ident) {
6183: while (*p == '#' || is_hor_space[*p]) p++;
6184: if (*p == '\n') {
6185: if (pedantic && !lang_asm)
6186: pedwarn ("invalid preprocessor directive");
6187: continue;
6188: }
6189: }
6190:
6191: if (!lang_asm && pedantic)
6192: pedwarn ("invalid preprocessor directive name");
6193: continue;
6194: }
6195:
6196: for (kt = directive_table; kt->length >= 0; kt++) {
6197: IF_STACK_FRAME *temp;
6198: if (ident_length == kt->length
6199: && strncmp (cp, kt->name, kt->length) == 0) {
6200: /* If we are asked to return on next directive, do so now. */
6201: if (any)
6202: return;
6203:
6204: switch (kt->type) {
6205: case T_IF:
6206: case T_IFDEF:
6207: case T_IFNDEF:
6208: temp = (IF_STACK_FRAME *) xcalloc (1, sizeof (IF_STACK_FRAME));
6209: temp->next = if_stack;
6210: if_stack = temp;
6211: temp->lineno = ip->lineno;
6212: temp->fname = ip->nominal_fname;
6213: temp->type = kt->type;
6214: break;
6215: case T_ELSE:
6216: case T_ENDIF:
6217: if (pedantic && if_stack != save_if_stack)
6218: validate_else (bp);
6219: case T_ELIF:
6220: if (if_stack == instack[indepth].if_stack) {
6221: error ("`#%s' not within a conditional", kt->name);
6222: break;
6223: }
6224: else if (if_stack == save_if_stack)
6225: return; /* found what we came for */
6226:
6227: if (kt->type != T_ENDIF) {
6228: if (if_stack->type == T_ELSE)
6229: error ("`#else' or `#elif' after `#else'");
6230: if_stack->type = kt->type;
6231: break;
6232: }
6233:
6234: temp = if_stack;
6235: if_stack = if_stack->next;
6236: free (temp);
6237: break;
6238: }
6239: break;
6240: }
6241: }
6242: /* Don't let erroneous code go by. */
6243: if (kt->length < 0 && !lang_asm && pedantic)
6244: pedwarn ("invalid preprocessor directive name");
6245: }
6246: }
6247: ip->bufp = bp;
6248: /* after this returns, rescan will exit because ip->bufp
6249: now points to the end of the buffer.
6250: rescan is responsible for the error message also. */
6251: }
6252:
6253: /*
6254: * handle a #else directive. Do this by just continuing processing
6255: * without changing if_stack ; this is so that the error message
6256: * for missing #endif's etc. will point to the original #if. It
6257: * is possible that something different would be better.
6258: */
6259:
6260: static int
6261: do_else (buf, limit, op, keyword)
6262: U_CHAR *buf, *limit;
6263: FILE_BUF *op;
6264: struct directive *keyword;
6265: {
6266: FILE_BUF *ip = &instack[indepth];
6267:
6268: if (pedantic) {
6269: SKIP_WHITE_SPACE (buf);
6270: if (buf != limit)
6271: pedwarn ("text following `#else' violates ANSI standard");
6272: }
6273:
6274: if (if_stack == instack[indepth].if_stack) {
6275: error ("`#else' not within a conditional");
6276: return 0;
6277: } else {
6278: /* #ifndef can't have its special treatment for containing the whole file
6279: if it has a #else clause. */
6280: if_stack->control_macro = 0;
6281:
6282: if (if_stack->type != T_IF && if_stack->type != T_ELIF) {
6283: error ("`#else' after `#else'");
6284: fprintf (stderr, " (matches line %d", if_stack->lineno);
6285: if (strcmp (if_stack->fname, ip->nominal_fname) != 0)
6286: fprintf (stderr, ", file %s", if_stack->fname);
6287: fprintf (stderr, ")\n");
6288: }
6289: if_stack->type = T_ELSE;
6290: }
6291:
6292: if (if_stack->if_succeeded)
6293: skip_if_group (ip, 0);
6294: else {
6295: ++if_stack->if_succeeded; /* continue processing input */
6296: output_line_command (ip, op, 1, same_file);
6297: }
6298: return 0;
6299: }
6300:
6301: /*
6302: * unstack after #endif command
6303: */
6304:
6305: static int
6306: do_endif (buf, limit, op, keyword)
6307: U_CHAR *buf, *limit;
6308: FILE_BUF *op;
6309: struct directive *keyword;
6310: {
6311: if (pedantic) {
6312: SKIP_WHITE_SPACE (buf);
6313: if (buf != limit)
6314: pedwarn ("text following `#endif' violates ANSI standard");
6315: }
6316:
6317: if (if_stack == instack[indepth].if_stack)
6318: error ("unbalanced `#endif'");
6319: else {
6320: IF_STACK_FRAME *temp = if_stack;
6321: if_stack = if_stack->next;
6322: if (temp->control_macro != 0) {
6323: /* This #endif matched a #ifndef at the start of the file.
6324: See if it is at the end of the file. */
6325: FILE_BUF *ip = &instack[indepth];
6326: U_CHAR *p = ip->bufp;
6327: U_CHAR *ep = ip->buf + ip->length;
6328:
6329: while (p != ep) {
6330: U_CHAR c = *p++;
6331: switch (c) {
6332: case ' ':
6333: case '\t':
6334: case '\n':
6335: break;
6336: case '/':
6337: if (p != ep && *p == '*') {
6338: /* Skip this comment. */
6339: int junk;
6340: U_CHAR *save_bufp = ip->bufp;
6341: ip->bufp = p + 1;
1.1.1.2 ! root 6342: p = skip_to_end_of_comment (ip, &junk, 1);
1.1 root 6343: ip->bufp = save_bufp;
6344: }
6345: break;
6346: default:
6347: goto fail;
6348: }
6349: }
6350: /* If we get here, this #endif ends a #ifndef
6351: that contains all of the file (aside from whitespace).
6352: Arrange not to include the file again
6353: if the macro that was tested is defined. */
6354: if (indepth != 0)
6355: record_control_macro (ip->fname, temp->control_macro);
6356: fail: ;
6357: }
6358: free (temp);
6359: output_line_command (&instack[indepth], op, 1, same_file);
6360: }
6361: return 0;
6362: }
6363:
6364: /* When an #else or #endif is found while skipping failed conditional,
6365: if -pedantic was specified, this is called to warn about text after
6366: the command name. P points to the first char after the command name. */
6367:
6368: static void
6369: validate_else (p)
6370: register U_CHAR *p;
6371: {
6372: /* Advance P over whitespace and comments. */
6373: while (1) {
6374: if (*p == '\\' && p[1] == '\n')
6375: p += 2;
6376: if (is_hor_space[*p])
6377: p++;
6378: else if (*p == '/') {
6379: if (p[1] == '\\' && p[2] == '\n')
6380: newline_fix (p + 1);
6381: if (p[1] == '*') {
6382: p += 2;
6383: /* Don't bother warning about unterminated comments
6384: since that will happen later. Just be sure to exit. */
6385: while (*p) {
6386: if (p[1] == '\\' && p[2] == '\n')
6387: newline_fix (p + 1);
6388: if (*p == '*' && p[1] == '/') {
6389: p += 2;
6390: break;
6391: }
6392: p++;
6393: }
6394: }
6395: else if ((cplusplus || objc) && p[1] == '/') {
6396: p += 2;
6397: while (*p && *p++ != '\n') ;
6398: }
6399: } else break;
6400: }
6401: if (*p && *p != '\n')
6402: pedwarn ("text following `#else' or `#endif' violates ANSI standard");
6403: }
6404:
1.1.1.2 ! root 6405: /* Skip a comment, assuming the input ptr immediately follows the
! 6406: initial slash-star. Bump *LINE_COUNTER for each newline.
! 6407: (The canonical line counter is &ip->lineno.)
! 6408: Don't use this routine (or the next one) if bumping the line
! 6409: counter is not sufficient to deal with newlines in the string.
! 6410:
! 6411: If NOWARN is nonzero, don't warn about slash-star inside a comment.
! 6412: This feature is useful when processing a comment that is going to be
! 6413: processed or was processed at another point in the preprocessor,
! 6414: to avoid a duplicate warning. */
1.1 root 6415: static U_CHAR *
1.1.1.2 ! root 6416: skip_to_end_of_comment (ip, line_counter, nowarn)
1.1 root 6417: register FILE_BUF *ip;
6418: int *line_counter; /* place to remember newlines, or NULL */
1.1.1.2 ! root 6419: int nowarn;
1.1 root 6420: {
6421: register U_CHAR *limit = ip->buf + ip->length;
6422: register U_CHAR *bp = ip->bufp;
6423: FILE_BUF *op = &outbuf; /* JF */
6424: int output = put_out_comments && !line_counter;
6425:
6426: /* JF this line_counter stuff is a crock to make sure the
6427: comment is only put out once, no matter how many times
6428: the comment is skipped. It almost works */
6429: if (output) {
6430: *op->bufp++ = '/';
6431: *op->bufp++ = '*';
6432: }
6433: if ((cplusplus || objc) && bp[-1] == '/') {
6434: if (output) {
6435: while (bp < limit)
6436: if ((*op->bufp++ = *bp++) == '\n') {
6437: bp--;
6438: break;
6439: }
6440: op->bufp[-1] = '*';
6441: *op->bufp++ = '/';
6442: *op->bufp++ = '\n';
6443: } else {
6444: while (bp < limit) {
6445: if (*bp++ == '\n') {
6446: bp--;
6447: break;
6448: }
6449: }
6450: }
6451: ip->bufp = bp;
6452: return bp;
6453: }
6454: while (bp < limit) {
6455: if (output)
6456: *op->bufp++ = *bp;
6457: switch (*bp++) {
6458: case '/':
1.1.1.2 ! root 6459: if (warn_comments && !nowarn && bp < limit && *bp == '*')
1.1 root 6460: warning ("`/*' within comment");
6461: break;
6462: case '\n':
6463: if (line_counter != NULL)
6464: ++*line_counter;
6465: if (output)
6466: ++op->lineno;
6467: break;
6468: case '*':
6469: if (*bp == '\\' && bp[1] == '\n')
6470: newline_fix (bp);
6471: if (*bp == '/') {
6472: if (output)
6473: *op->bufp++ = '/';
6474: ip->bufp = ++bp;
6475: return bp;
6476: }
6477: break;
6478: }
6479: }
6480: ip->bufp = bp;
6481: return bp;
6482: }
6483:
6484: /*
6485: * Skip over a quoted string. BP points to the opening quote.
6486: * Returns a pointer after the closing quote. Don't go past LIMIT.
6487: * START_LINE is the line number of the starting point (but it need
6488: * not be valid if the starting point is inside a macro expansion).
6489: *
6490: * The input stack state is not changed.
6491: *
6492: * If COUNT_NEWLINES is nonzero, it points to an int to increment
6493: * for each newline passed.
6494: *
6495: * If BACKSLASH_NEWLINES_P is nonzero, store 1 thru it
6496: * if we pass a backslash-newline.
6497: *
6498: * If EOFP is nonzero, set *EOFP to 1 if the string is unterminated.
6499: */
6500: static U_CHAR *
6501: skip_quoted_string (bp, limit, start_line, count_newlines, backslash_newlines_p, eofp)
6502: register U_CHAR *bp;
6503: register U_CHAR *limit;
6504: int start_line;
6505: int *count_newlines;
6506: int *backslash_newlines_p;
6507: int *eofp;
6508: {
6509: register U_CHAR c, match;
6510:
6511: match = *bp++;
6512: while (1) {
6513: if (bp >= limit) {
6514: error_with_line (line_for_error (start_line),
6515: "unterminated string or character constant");
6516: if (eofp)
6517: *eofp = 1;
6518: break;
6519: }
6520: c = *bp++;
6521: if (c == '\\') {
6522: while (*bp == '\\' && bp[1] == '\n') {
6523: if (backslash_newlines_p)
6524: *backslash_newlines_p = 1;
6525: if (count_newlines)
6526: ++*count_newlines;
6527: bp += 2;
6528: }
6529: if (*bp == '\n' && count_newlines) {
6530: if (backslash_newlines_p)
6531: *backslash_newlines_p = 1;
6532: ++*count_newlines;
6533: }
6534: bp++;
6535: } else if (c == '\n') {
6536: if (traditional) {
6537: /* Unterminated strings and character constants are 'legal'. */
6538: bp--; /* Don't consume the newline. */
6539: if (eofp)
6540: *eofp = 1;
6541: break;
6542: }
6543: if (match == '\'') {
6544: error_with_line (line_for_error (start_line),
6545: "unterminated character constant");
6546: bp--;
6547: if (eofp)
6548: *eofp = 1;
6549: break;
6550: }
6551: if (traditional) { /* Unterminated strings are 'legal'. */
6552: if (eofp)
6553: *eofp = 1;
6554: break;
6555: }
6556: /* If not traditional, then allow newlines inside strings. */
6557: if (count_newlines)
6558: ++*count_newlines;
6559: } else if (c == match)
6560: break;
6561: }
6562: return bp;
6563: }
6564:
6565: /* Skip across a group of balanced parens, starting from IP->bufp.
6566: IP->bufp is updated. Use this with IP->bufp pointing at an open-paren.
6567:
6568: This does not handle newlines, because it's used for the arg of #if,
1.1.1.2 ! root 6569: where there aren't any newlines. Also, backslash-newline can't appear. */
1.1 root 6570:
6571: static U_CHAR *
6572: skip_paren_group (ip)
6573: register FILE_BUF *ip;
6574: {
6575: U_CHAR *limit = ip->buf + ip->length;
6576: U_CHAR *p = ip->bufp;
6577: int depth = 0;
6578: int lines_dummy = 0;
6579:
6580: while (p != limit) {
6581: int c = *p++;
6582: switch (c) {
6583: case '(':
6584: depth++;
6585: break;
6586:
6587: case ')':
6588: depth--;
6589: if (depth == 0)
6590: return ip->bufp = p;
6591: break;
6592:
6593: case '/':
6594: if (*p == '*') {
6595: ip->bufp = p;
1.1.1.2 ! root 6596: p = skip_to_end_of_comment (ip, &lines_dummy, 0);
1.1 root 6597: p = ip->bufp;
6598: }
6599:
6600: case '"':
6601: case '\'':
6602: {
6603: int eofp = 0;
6604: p = skip_quoted_string (p - 1, limit, 0, 0, 0, &eofp);
6605: if (eofp)
6606: return ip->bufp = p;
6607: }
6608: break;
6609: }
6610: }
6611:
6612: ip->bufp = p;
6613: return p;
6614: }
6615:
6616: /*
6617: * write out a #line command, for instance, after an #include file.
6618: * If CONDITIONAL is nonzero, we can omit the #line if it would
6619: * appear to be a no-op, and we can output a few newlines instead
6620: * if we want to increase the line number by a small amount.
6621: * FILE_CHANGE says whether we are entering a file, leaving, or neither.
6622: */
6623:
6624: static void
6625: output_line_command (ip, op, conditional, file_change)
6626: FILE_BUF *ip, *op;
6627: int conditional;
6628: enum file_change_code file_change;
6629: {
6630: int len;
6631: char line_cmd_buf[500];
6632:
6633: if (no_line_commands
6634: || ip->fname == NULL
6635: || no_output) {
6636: op->lineno = ip->lineno;
6637: return;
6638: }
6639:
6640: if (conditional) {
6641: if (ip->lineno == op->lineno)
6642: return;
6643:
6644: /* If the inherited line number is a little too small,
6645: output some newlines instead of a #line command. */
6646: if (ip->lineno > op->lineno && ip->lineno < op->lineno + 8) {
6647: check_expand (op, 10);
6648: while (ip->lineno > op->lineno) {
6649: *op->bufp++ = '\n';
6650: op->lineno++;
6651: }
6652: return;
6653: }
6654: }
6655:
1.1.1.2 ! root 6656: /* Don't output a line number of 0 if we can help it. */
! 6657: if (ip->lineno == 0 && ip->bufp - ip->buf < ip->length
! 6658: && *ip->bufp == '\n') {
! 6659: ip->lineno++;
! 6660: ip->bufp++;
! 6661: }
! 6662:
1.1 root 6663: #ifdef OUTPUT_LINE_COMMANDS
6664: sprintf (line_cmd_buf, "#line %d \"%s\"", ip->lineno, ip->nominal_fname);
6665: #else
6666: sprintf (line_cmd_buf, "# %d \"%s\"", ip->lineno, ip->nominal_fname);
6667: #endif
6668: if (file_change != same_file)
6669: strcat (line_cmd_buf, file_change == enter_file ? " 1" : " 2");
6670: /* Tell cc1 if following text comes from a system header file. */
6671: if (ip->system_header_p)
6672: strcat (line_cmd_buf, " 3");
6673: len = strlen (line_cmd_buf);
6674: line_cmd_buf[len++] = '\n';
6675: check_expand (op, len + 1);
6676: if (op->bufp > op->buf && op->bufp[-1] != '\n')
6677: *op->bufp++ = '\n';
6678: bcopy (line_cmd_buf, op->bufp, len);
6679: op->bufp += len;
6680: op->lineno = ip->lineno;
6681: }
6682:
6683: /* This structure represents one parsed argument in a macro call.
6684: `raw' points to the argument text as written (`raw_length' is its length).
6685: `expanded' points to the argument's macro-expansion
6686: (its length is `expand_length').
6687: `stringified_length' is the length the argument would have
6688: if stringified.
6689: `use_count' is the number of times this macro arg is substituted
6690: into the macro. If the actual use count exceeds 10,
6691: the value stored is 10.
6692: `free1' and `free2', if nonzero, point to blocks to be freed
6693: when the macro argument data is no longer needed. */
6694:
6695: struct argdata {
6696: U_CHAR *raw, *expanded;
6697: int raw_length, expand_length;
6698: int stringified_length;
6699: U_CHAR *free1, *free2;
6700: char newlines;
6701: char comments;
6702: char use_count;
6703: };
6704:
6705: /* Expand a macro call.
6706: HP points to the symbol that is the macro being called.
6707: Put the result of expansion onto the input stack
6708: so that subsequent input by our caller will use it.
6709:
6710: If macro wants arguments, caller has already verified that
6711: an argument list follows; arguments come from the input stack. */
6712:
6713: static void
6714: macroexpand (hp, op)
6715: HASHNODE *hp;
6716: FILE_BUF *op;
6717: {
6718: int nargs;
6719: DEFINITION *defn = hp->value.defn;
6720: register U_CHAR *xbuf;
6721: int xbuf_len;
6722: int start_line = instack[indepth].lineno;
6723:
6724: CHECK_DEPTH (return;);
6725:
6726: /* it might not actually be a macro. */
6727: if (hp->type != T_MACRO) {
6728: special_symbol (hp, op);
6729: return;
6730: }
6731:
6732: /* This macro is being used inside a #if, which means it must be */
6733: /* recorded as a precondition. */
6734: if (pcp_inside_if && pcp_outfile && defn->predefined)
6735: dump_single_macro (hp, pcp_outfile);
6736:
6737: nargs = defn->nargs;
6738:
6739: if (nargs >= 0) {
6740: register int i;
6741: struct argdata *args;
6742: char *parse_error = 0;
6743:
6744: args = (struct argdata *) alloca ((nargs + 1) * sizeof (struct argdata));
6745:
6746: for (i = 0; i < nargs; i++) {
6747: args[i].raw = args[i].expanded = (U_CHAR *) "";
6748: args[i].raw_length = args[i].expand_length
6749: = args[i].stringified_length = 0;
6750: args[i].free1 = args[i].free2 = 0;
6751: args[i].use_count = 0;
6752: }
6753:
6754: /* Parse all the macro args that are supplied. I counts them.
6755: The first NARGS args are stored in ARGS.
6756: The rest are discarded. */
6757: i = 0;
6758: do {
6759: /* Discard the open-parenthesis or comma before the next arg. */
6760: ++instack[indepth].bufp;
6761: parse_error
6762: = macarg ((i < nargs || (nargs == 0 && i == 0)) ? &args[i] : 0);
6763: if (parse_error) {
6764: error_with_line (line_for_error (start_line), parse_error);
6765: break;
6766: }
6767: i++;
6768: } while (*instack[indepth].bufp != ')');
6769:
6770: /* If we got one arg but it was just whitespace, call that 0 args. */
6771: if (i == 1) {
6772: register U_CHAR *bp = args[0].raw;
6773: register U_CHAR *lim = bp + args[0].raw_length;
6774: while (bp != lim && is_space[*bp]) bp++;
6775: if (bp == lim)
6776: i = 0;
6777: }
6778:
6779: if (nargs == 0 && i > 0)
6780: error ("arguments given to macro `%s'", hp->name);
6781: else if (i < nargs) {
6782: /* traditional C allows foo() if foo wants one argument. */
6783: if (nargs == 1 && i == 0 && traditional)
6784: ;
6785: else if (i == 0)
6786: error ("macro `%s' used without args", hp->name);
6787: else if (i == 1)
6788: error ("macro `%s' used with just one arg", hp->name);
6789: else
6790: error ("macro `%s' used with only %d args", hp->name, i);
6791: } else if (i > nargs)
6792: error ("macro `%s' used with too many (%d) args", hp->name, i);
6793:
6794: /* Swallow the closeparen. */
6795: ++instack[indepth].bufp;
6796:
6797: /* If macro wants zero args, we parsed the arglist for checking only.
6798: Read directly from the macro definition. */
6799: if (nargs == 0) {
6800: xbuf = defn->expansion;
6801: xbuf_len = defn->length;
6802: } else {
6803: register U_CHAR *exp = defn->expansion;
6804: register int offset; /* offset in expansion,
6805: copied a piece at a time */
6806: register int totlen; /* total amount of exp buffer filled so far */
6807:
6808: register struct reflist *ap;
6809:
6810: /* Macro really takes args. Compute the expansion of this call. */
6811:
6812: /* Compute length in characters of the macro's expansion.
6813: Also count number of times each arg is used. */
6814: xbuf_len = defn->length;
6815: for (ap = defn->pattern; ap != NULL; ap = ap->next) {
6816: if (ap->stringify)
6817: xbuf_len += args[ap->argno].stringified_length;
6818: else if (ap->raw_before || ap->raw_after || traditional)
6819: xbuf_len += args[ap->argno].raw_length;
6820: else
6821: xbuf_len += args[ap->argno].expand_length;
6822:
6823: if (args[ap->argno].use_count < 10)
6824: args[ap->argno].use_count++;
6825: }
6826:
6827: xbuf = (U_CHAR *) xmalloc (xbuf_len + 1);
6828:
6829: /* Generate in XBUF the complete expansion
6830: with arguments substituted in.
6831: TOTLEN is the total size generated so far.
6832: OFFSET is the index in the definition
6833: of where we are copying from. */
6834: offset = totlen = 0;
6835: for (ap = defn->pattern; ap != NULL; ap = ap->next) {
6836: register struct argdata *arg = &args[ap->argno];
6837:
6838: for (i = 0; i < ap->nchars; i++)
6839: xbuf[totlen++] = exp[offset++];
6840:
6841: if (ap->stringify != 0) {
6842: int arglen = arg->raw_length;
6843: int escaped = 0;
6844: int in_string = 0;
6845: int c;
6846: i = 0;
6847: while (i < arglen
6848: && (c = arg->raw[i], is_space[c]))
6849: i++;
6850: while (i < arglen
6851: && (c = arg->raw[arglen - 1], is_space[c]))
6852: arglen--;
6853: if (!traditional)
6854: xbuf[totlen++] = '\"'; /* insert beginning quote */
6855: for (; i < arglen; i++) {
6856: c = arg->raw[i];
6857:
6858: /* Special markers Newline Space
6859: generate nothing for a stringified argument. */
6860: if (c == '\n' && arg->raw[i+1] != '\n') {
6861: i++;
6862: continue;
6863: }
6864:
6865: /* Internal sequences of whitespace are replaced by one space
6866: except within an string or char token. */
6867: if (! in_string
6868: && (c == '\n' ? arg->raw[i+1] == '\n' : is_space[c])) {
6869: while (1) {
6870: /* Note that Newline Space does occur within whitespace
6871: sequences; consider it part of the sequence. */
6872: if (c == '\n' && is_space[arg->raw[i+1]])
6873: i += 2;
6874: else if (c != '\n' && is_space[c])
6875: i++;
6876: else break;
6877: c = arg->raw[i];
6878: }
6879: i--;
6880: c = ' ';
6881: }
6882:
6883: if (escaped)
6884: escaped = 0;
6885: else {
6886: if (c == '\\')
6887: escaped = 1;
6888: if (in_string) {
6889: if (c == in_string)
6890: in_string = 0;
6891: } else if (c == '\"' || c == '\'')
6892: in_string = c;
6893: }
6894:
6895: /* Escape these chars */
6896: if (c == '\"' || (in_string && c == '\\'))
6897: xbuf[totlen++] = '\\';
6898: if (isprint (c))
6899: xbuf[totlen++] = c;
6900: else {
6901: sprintf ((char *) &xbuf[totlen], "\\%03o", (unsigned int) c);
6902: totlen += 4;
6903: }
6904: }
6905: if (!traditional)
6906: xbuf[totlen++] = '\"'; /* insert ending quote */
6907: } else if (ap->raw_before || ap->raw_after || traditional) {
6908: U_CHAR *p1 = arg->raw;
6909: U_CHAR *l1 = p1 + arg->raw_length;
6910: if (ap->raw_before) {
6911: while (p1 != l1 && is_space[*p1]) p1++;
6912: while (p1 != l1 && is_idchar[*p1])
6913: xbuf[totlen++] = *p1++;
6914: /* Delete any no-reexpansion marker that follows
6915: an identifier at the beginning of the argument
6916: if the argument is concatenated with what precedes it. */
6917: if (p1[0] == '\n' && p1[1] == '-')
6918: p1 += 2;
6919: }
6920: if (ap->raw_after) {
6921: /* Arg is concatenated after: delete trailing whitespace,
6922: whitespace markers, and no-reexpansion markers. */
6923: while (p1 != l1) {
6924: if (is_space[l1[-1]]) l1--;
6925: else if (l1[-1] == '-') {
6926: U_CHAR *p2 = l1 - 1;
6927: /* If a `-' is preceded by an odd number of newlines then it
6928: and the last newline are a no-reexpansion marker. */
6929: while (p2 != p1 && p2[-1] == '\n') p2--;
6930: if ((l1 - 1 - p2) & 1) {
6931: l1 -= 2;
6932: }
6933: else break;
6934: }
6935: else break;
6936: }
6937: }
6938: bcopy (p1, xbuf + totlen, l1 - p1);
6939: totlen += l1 - p1;
6940: } else {
6941: bcopy (arg->expanded, xbuf + totlen, arg->expand_length);
6942: totlen += arg->expand_length;
6943: /* If a macro argument with newlines is used multiple times,
6944: then only expand the newlines once. This avoids creating output
6945: lines which don't correspond to any input line, which confuses
6946: gdb and gcov. */
6947: if (arg->use_count > 1 && arg->newlines > 0) {
6948: /* Don't bother doing delete_newlines for subsequent
6949: uses of arg. */
6950: arg->use_count = 1;
6951: arg->expand_length
6952: = delete_newlines (arg->expanded, arg->expand_length);
6953: }
6954: }
6955:
6956: if (totlen > xbuf_len)
6957: abort ();
6958: }
6959:
6960: /* if there is anything left of the definition
6961: after handling the arg list, copy that in too. */
6962:
6963: for (i = offset; i < defn->length; i++)
6964: xbuf[totlen++] = exp[i];
6965:
6966: xbuf[totlen] = 0;
6967: xbuf_len = totlen;
6968:
6969: for (i = 0; i < nargs; i++) {
6970: if (args[i].free1 != 0)
6971: free (args[i].free1);
6972: if (args[i].free2 != 0)
6973: free (args[i].free2);
6974: }
6975: }
6976: } else {
6977: xbuf = defn->expansion;
6978: xbuf_len = defn->length;
6979: }
6980:
6981: /* Now put the expansion on the input stack
6982: so our caller will commence reading from it. */
6983: {
6984: register FILE_BUF *ip2;
6985:
6986: ip2 = &instack[++indepth];
6987:
6988: ip2->fname = 0;
6989: ip2->nominal_fname = 0;
6990: ip2->lineno = 0;
6991: ip2->buf = xbuf;
6992: ip2->length = xbuf_len;
6993: ip2->bufp = xbuf;
6994: ip2->free_ptr = (nargs > 0) ? xbuf : 0;
6995: ip2->macro = hp;
6996: ip2->if_stack = if_stack;
6997: ip2->system_header_p = 0;
6998:
6999: /* Recursive macro use sometimes works traditionally.
7000: #define foo(x,y) bar(x(y,0), y)
7001: foo(foo, baz) */
7002:
7003: if (!traditional)
7004: hp->type = T_DISABLED;
7005: }
7006: }
7007:
7008: /*
7009: * Parse a macro argument and store the info on it into *ARGPTR.
7010: * Return nonzero to indicate a syntax error.
7011: */
7012:
7013: static char *
7014: macarg (argptr)
7015: register struct argdata *argptr;
7016: {
7017: FILE_BUF *ip = &instack[indepth];
7018: int paren = 0;
7019: int newlines = 0;
7020: int comments = 0;
7021:
7022: /* Try to parse as much of the argument as exists at this
7023: input stack level. */
7024: U_CHAR *bp = macarg1 (ip->bufp, ip->buf + ip->length,
7025: &paren, &newlines, &comments);
7026:
7027: /* If we find the end of the argument at this level,
7028: set up *ARGPTR to point at it in the input stack. */
7029: if (!(ip->fname != 0 && (newlines != 0 || comments != 0))
7030: && bp != ip->buf + ip->length) {
7031: if (argptr != 0) {
7032: argptr->raw = ip->bufp;
7033: argptr->raw_length = bp - ip->bufp;
7034: argptr->newlines = newlines;
7035: }
7036: ip->bufp = bp;
7037: } else {
7038: /* This input stack level ends before the macro argument does.
7039: We must pop levels and keep parsing.
7040: Therefore, we must allocate a temporary buffer and copy
7041: the macro argument into it. */
7042: int bufsize = bp - ip->bufp;
7043: int extra = newlines;
7044: U_CHAR *buffer = (U_CHAR *) xmalloc (bufsize + extra + 1);
7045: int final_start = 0;
7046:
7047: bcopy (ip->bufp, buffer, bufsize);
7048: ip->bufp = bp;
7049: ip->lineno += newlines;
7050:
7051: while (bp == ip->buf + ip->length) {
7052: if (instack[indepth].macro == 0) {
7053: free (buffer);
7054: return "unterminated macro call";
7055: }
7056: ip->macro->type = T_MACRO;
7057: if (ip->free_ptr)
7058: free (ip->free_ptr);
7059: ip = &instack[--indepth];
7060: newlines = 0;
7061: comments = 0;
7062: bp = macarg1 (ip->bufp, ip->buf + ip->length, &paren,
7063: &newlines, &comments);
7064: final_start = bufsize;
7065: bufsize += bp - ip->bufp;
7066: extra += newlines;
7067: buffer = (U_CHAR *) xrealloc (buffer, bufsize + extra + 1);
7068: bcopy (ip->bufp, buffer + bufsize - (bp - ip->bufp), bp - ip->bufp);
7069: ip->bufp = bp;
7070: ip->lineno += newlines;
7071: }
7072:
7073: /* Now, if arg is actually wanted, record its raw form,
7074: discarding comments and duplicating newlines in whatever
7075: part of it did not come from a macro expansion.
7076: EXTRA space has been preallocated for duplicating the newlines.
7077: FINAL_START is the index of the start of that part. */
7078: if (argptr != 0) {
7079: argptr->raw = buffer;
7080: argptr->raw_length = bufsize;
7081: argptr->free1 = buffer;
7082: argptr->newlines = newlines;
7083: argptr->comments = comments;
7084: if ((newlines || comments) && ip->fname != 0)
7085: argptr->raw_length
7086: = final_start +
7087: discard_comments (argptr->raw + final_start,
7088: argptr->raw_length - final_start,
7089: newlines);
7090: argptr->raw[argptr->raw_length] = 0;
7091: if (argptr->raw_length > bufsize + extra)
7092: abort ();
7093: }
7094: }
7095:
7096: /* If we are not discarding this argument,
7097: macroexpand it and compute its length as stringified.
7098: All this info goes into *ARGPTR. */
7099:
7100: if (argptr != 0) {
7101: FILE_BUF obuf;
7102: register U_CHAR *buf, *lim;
7103: register int totlen;
7104:
7105: obuf = expand_to_temp_buffer (argptr->raw,
7106: argptr->raw + argptr->raw_length,
7107: 1, 0);
7108:
7109: argptr->expanded = obuf.buf;
7110: argptr->expand_length = obuf.length;
7111: argptr->free2 = obuf.buf;
7112:
7113: buf = argptr->raw;
7114: lim = buf + argptr->raw_length;
7115:
7116: while (buf != lim && is_space[*buf])
7117: buf++;
7118: while (buf != lim && is_space[lim[-1]])
7119: lim--;
7120: totlen = traditional ? 0 : 2; /* Count opening and closing quote. */
7121: while (buf != lim) {
7122: register U_CHAR c = *buf++;
7123: totlen++;
7124: /* Internal sequences of whitespace are replaced by one space
7125: in most cases, but not always. So count all the whitespace
7126: in case we need to keep it all. */
7127: #if 0
7128: if (is_space[c])
7129: SKIP_ALL_WHITE_SPACE (buf);
7130: else
7131: #endif
7132: if (c == '\"' || c == '\\') /* escape these chars */
7133: totlen++;
7134: else if (!isprint (c))
7135: totlen += 3;
7136: }
7137: argptr->stringified_length = totlen;
7138: }
7139: return 0;
7140: }
7141:
7142: /* Scan text from START (inclusive) up to LIMIT (exclusive),
7143: counting parens in *DEPTHPTR,
7144: and return if reach LIMIT
7145: or before a `)' that would make *DEPTHPTR negative
7146: or before a comma when *DEPTHPTR is zero.
7147: Single and double quotes are matched and termination
7148: is inhibited within them. Comments also inhibit it.
7149: Value returned is pointer to stopping place.
7150:
7151: Increment *NEWLINES each time a newline is passed.
7152: Set *COMMENTS to 1 if a comment is seen. */
7153:
7154: static U_CHAR *
7155: macarg1 (start, limit, depthptr, newlines, comments)
7156: U_CHAR *start;
7157: register U_CHAR *limit;
7158: int *depthptr, *newlines, *comments;
7159: {
7160: register U_CHAR *bp = start;
7161:
7162: while (bp < limit) {
7163: switch (*bp) {
7164: case '(':
7165: (*depthptr)++;
7166: break;
7167: case ')':
7168: if (--(*depthptr) < 0)
7169: return bp;
7170: break;
7171: case '\\':
7172: /* Traditionally, backslash makes following char not special. */
7173: if (bp + 1 < limit && traditional)
7174: {
7175: bp++;
7176: /* But count source lines anyway. */
7177: if (*bp == '\n')
7178: ++*newlines;
7179: }
7180: break;
7181: case '\n':
7182: ++*newlines;
7183: break;
7184: case '/':
7185: if (bp[1] == '\\' && bp[2] == '\n')
7186: newline_fix (bp + 1);
7187: if ((cplusplus || objc) && bp[1] == '/') {
7188: *comments = 1;
7189: bp += 2;
7190: while (bp < limit && *bp++ != '\n') ;
7191: ++*newlines;
7192: break;
7193: }
7194: if (bp[1] != '*' || bp + 1 >= limit)
7195: break;
7196: *comments = 1;
7197: bp += 2;
7198: while (bp + 1 < limit) {
7199: if (bp[0] == '*'
7200: && bp[1] == '\\' && bp[2] == '\n')
7201: newline_fix (bp + 1);
7202: if (bp[0] == '*' && bp[1] == '/')
7203: break;
7204: if (*bp == '\n') ++*newlines;
7205: bp++;
7206: }
7207: break;
7208: case '\'':
7209: case '\"':
7210: {
7211: int quotec;
7212: for (quotec = *bp++; bp + 1 < limit && *bp != quotec; bp++) {
7213: if (*bp == '\\') {
7214: bp++;
7215: if (*bp == '\n')
7216: ++*newlines;
7217: while (*bp == '\\' && bp[1] == '\n') {
7218: bp += 2;
7219: }
7220: } else if (*bp == '\n') {
7221: ++*newlines;
7222: if (quotec == '\'')
7223: break;
7224: }
7225: }
7226: }
7227: break;
7228: case ',':
7229: if ((*depthptr) == 0)
7230: return bp;
7231: break;
7232: }
7233: bp++;
7234: }
7235:
7236: return bp;
7237: }
7238:
7239: /* Discard comments and duplicate newlines
7240: in the string of length LENGTH at START,
7241: except inside of string constants.
7242: The string is copied into itself with its beginning staying fixed.
7243:
7244: NEWLINES is the number of newlines that must be duplicated.
7245: We assume that that much extra space is available past the end
7246: of the string. */
7247:
7248: static int
7249: discard_comments (start, length, newlines)
7250: U_CHAR *start;
7251: int length;
7252: int newlines;
7253: {
7254: register U_CHAR *ibp;
7255: register U_CHAR *obp;
7256: register U_CHAR *limit;
7257: register int c;
7258:
7259: /* If we have newlines to duplicate, copy everything
7260: that many characters up. Then, in the second part,
7261: we will have room to insert the newlines
7262: while copying down.
7263: NEWLINES may actually be too large, because it counts
7264: newlines in string constants, and we don't duplicate those.
7265: But that does no harm. */
7266: if (newlines > 0) {
7267: ibp = start + length;
7268: obp = ibp + newlines;
7269: limit = start;
7270: while (limit != ibp)
7271: *--obp = *--ibp;
7272: }
7273:
7274: ibp = start + newlines;
7275: limit = start + length + newlines;
7276: obp = start;
7277:
7278: while (ibp < limit) {
7279: *obp++ = c = *ibp++;
7280: switch (c) {
7281: case '\n':
7282: /* Duplicate the newline. */
7283: *obp++ = '\n';
7284: break;
7285:
7286: case '\\':
7287: if (*ibp == '\n') {
7288: obp--;
7289: ibp++;
7290: }
7291: break;
7292:
7293: case '/':
7294: if (*ibp == '\\' && ibp[1] == '\n')
7295: newline_fix (ibp);
7296: /* Delete any comment. */
7297: if ((cplusplus || objc) && ibp[0] == '/') {
7298: obp--;
7299: ibp++;
7300: while (ibp < limit && *ibp++ != '\n') ;
7301: break;
7302: }
7303: if (ibp[0] != '*' || ibp + 1 >= limit)
7304: break;
7305: obp--;
7306: ibp++;
7307: while (ibp + 1 < limit) {
7308: if (ibp[0] == '*'
7309: && ibp[1] == '\\' && ibp[2] == '\n')
7310: newline_fix (ibp + 1);
7311: if (ibp[0] == '*' && ibp[1] == '/')
7312: break;
7313: ibp++;
7314: }
7315: ibp += 2;
7316: break;
7317:
7318: case '\'':
7319: case '\"':
7320: /* Notice and skip strings, so that we don't
7321: think that comments start inside them,
7322: and so we don't duplicate newlines in them. */
7323: {
7324: int quotec = c;
7325: while (ibp < limit) {
7326: *obp++ = c = *ibp++;
7327: if (c == quotec)
7328: break;
7329: if (c == '\n' && quotec == '\'')
7330: break;
7331: if (c == '\\' && ibp < limit) {
7332: while (*ibp == '\\' && ibp[1] == '\n')
7333: ibp += 2;
7334: *obp++ = *ibp++;
7335: }
7336: }
7337: }
7338: break;
7339: }
7340: }
7341:
7342: return obp - start;
7343: }
7344:
7345: /* Delete newlines in the string of length LENGTH at START, except inside
7346: of string constants. The string is copied into itself with its beginning
7347: staying fixed. */
7348:
7349: static int
7350: delete_newlines (start, length)
7351: U_CHAR *start;
7352: int length;
7353: {
7354: register U_CHAR *ibp;
7355: register U_CHAR *obp;
7356: register U_CHAR *limit;
7357: register int c;
7358:
7359: ibp = start;
7360: limit = start + length;
7361: obp = start;
7362:
7363: while (ibp < limit) {
7364: *obp++ = c = *ibp++;
7365: switch (c) {
7366: case '\n':
7367: /* If this is a NEWLINE NEWLINE, then this is a real newline in the
7368: output. Skip past the newline and its duplicate. */
7369: if (*ibp == '\n')
7370: {
7371: ibp++;
7372: obp--;
7373: }
7374: break;
7375:
7376: case '\'':
7377: case '\"':
7378: /* Notice and skip strings, so that we don't delete newlines in them. */
7379: {
7380: int quotec = c;
7381: while (ibp < limit) {
7382: *obp++ = c = *ibp++;
7383: if (c == quotec)
7384: break;
7385: if (c == '\n' && quotec == '\'')
7386: break;
7387: }
7388: }
7389: break;
7390: }
7391: }
7392:
7393: return obp - start;
7394: }
7395:
7396: /*
7397: * error - print error message and increment count of errors.
7398: */
7399:
7400: void
7401: error (msg, arg1, arg2, arg3)
7402: char *msg;
7403: {
7404: int i;
7405: FILE_BUF *ip = NULL;
7406:
7407: print_containing_files ();
7408:
7409: for (i = indepth; i >= 0; i--)
7410: if (instack[i].fname != NULL) {
7411: ip = &instack[i];
7412: break;
7413: }
7414:
7415: if (ip != NULL)
7416: fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno);
7417: fprintf (stderr, msg, arg1, arg2, arg3);
7418: fprintf (stderr, "\n");
7419: errors++;
7420: }
7421:
7422: /* Error including a message from `errno'. */
7423:
7424: static void
7425: error_from_errno (name)
7426: char *name;
7427: {
7428: int i;
7429: FILE_BUF *ip = NULL;
7430:
7431: print_containing_files ();
7432:
7433: for (i = indepth; i >= 0; i--)
7434: if (instack[i].fname != NULL) {
7435: ip = &instack[i];
7436: break;
7437: }
7438:
7439: if (ip != NULL)
7440: fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno);
7441:
7442: if (errno < sys_nerr)
7443: fprintf (stderr, "%s: %s\n", name, sys_errlist[errno]);
7444: else
7445: fprintf (stderr, "%s: undocumented I/O error\n", name);
7446:
7447: errors++;
7448: }
7449:
7450: /* Print error message but don't count it. */
7451:
7452: void
7453: warning (msg, arg1, arg2, arg3)
7454: char *msg;
7455: {
7456: int i;
7457: FILE_BUF *ip = NULL;
7458:
7459: if (inhibit_warnings)
7460: return;
7461:
7462: if (warnings_are_errors)
7463: errors++;
7464:
7465: print_containing_files ();
7466:
7467: for (i = indepth; i >= 0; i--)
7468: if (instack[i].fname != NULL) {
7469: ip = &instack[i];
7470: break;
7471: }
7472:
7473: if (ip != NULL)
7474: fprintf (stderr, "%s:%d: ", ip->nominal_fname, ip->lineno);
7475: fprintf (stderr, "warning: ");
7476: fprintf (stderr, msg, arg1, arg2, arg3);
7477: fprintf (stderr, "\n");
7478: }
7479:
7480: static void
7481: error_with_line (line, msg, arg1, arg2, arg3)
7482: int line;
7483: char *msg;
7484: {
7485: int i;
7486: FILE_BUF *ip = NULL;
7487:
7488: print_containing_files ();
7489:
7490: for (i = indepth; i >= 0; i--)
7491: if (instack[i].fname != NULL) {
7492: ip = &instack[i];
7493: break;
7494: }
7495:
7496: if (ip != NULL)
7497: fprintf (stderr, "%s:%d: ", ip->nominal_fname, line);
7498: fprintf (stderr, msg, arg1, arg2, arg3);
7499: fprintf (stderr, "\n");
7500: errors++;
7501: }
7502:
7503: /* print an error message and maybe count it. */
7504:
7505: void
7506: pedwarn (msg, arg1, arg2, arg3)
7507: char *msg;
7508: {
7509: if (pedantic_errors)
7510: error (msg, arg1, arg2, arg3);
7511: else
7512: warning (msg, arg1, arg2, arg3);
7513: }
7514:
7515: /* Report a warning (or an error if pedantic_errors)
7516: giving specified file name and line number, not current. */
7517:
7518: static void
7519: pedwarn_with_file_and_line (file, line, msg, arg1, arg2, arg3)
7520: char *file;
7521: int line;
7522: char *msg;
7523: {
7524: int i;
7525: if (!pedantic_errors && inhibit_warnings)
7526: return;
7527: if (file != NULL)
7528: fprintf (stderr, "%s:%d: ", file, line);
7529: if (pedantic_errors || warnings_are_errors)
7530: errors++;
7531: if (!pedantic_errors)
7532: fprintf (stderr, "warning: ");
7533: fprintf (stderr, msg, arg1, arg2, arg3);
7534: fprintf (stderr, "\n");
7535: }
7536:
7537: /* Print the file names and line numbers of the #include
7538: commands which led to the current file. */
7539:
7540: static void
7541: print_containing_files ()
7542: {
7543: FILE_BUF *ip = NULL;
7544: int i;
7545: int first = 1;
7546:
7547: /* If stack of files hasn't changed since we last printed
7548: this info, don't repeat it. */
7549: if (last_error_tick == input_file_stack_tick)
7550: return;
7551:
7552: for (i = indepth; i >= 0; i--)
7553: if (instack[i].fname != NULL) {
7554: ip = &instack[i];
7555: break;
7556: }
7557:
7558: /* Give up if we don't find a source file. */
7559: if (ip == NULL)
7560: return;
7561:
7562: /* Find the other, outer source files. */
7563: for (i--; i >= 0; i--)
7564: if (instack[i].fname != NULL) {
7565: ip = &instack[i];
7566: if (first) {
7567: first = 0;
7568: fprintf (stderr, "In file included");
7569: } else {
7570: fprintf (stderr, ",");
7571: }
7572:
7573: fprintf (stderr, " from %s:%d", ip->nominal_fname, ip->lineno);
7574: }
7575: if (! first)
7576: fprintf (stderr, ":\n");
7577:
7578: /* Record we have printed the status as of this time. */
7579: last_error_tick = input_file_stack_tick;
7580: }
7581:
7582: /* Return the line at which an error occurred.
7583: The error is not necessarily associated with the current spot
7584: in the input stack, so LINE says where. LINE will have been
7585: copied from ip->lineno for the current input level.
7586: If the current level is for a file, we return LINE.
7587: But if the current level is not for a file, LINE is meaningless.
7588: In that case, we return the lineno of the innermost file. */
7589:
7590: static int
7591: line_for_error (line)
7592: int line;
7593: {
7594: int i;
7595: int line1 = line;
7596:
7597: for (i = indepth; i >= 0; ) {
7598: if (instack[i].fname != 0)
7599: return line1;
7600: i--;
7601: if (i < 0)
7602: return 0;
7603: line1 = instack[i].lineno;
7604: }
7605: abort ();
7606: /*NOTREACHED*/
7607: return 0;
7608: }
7609:
7610: /*
7611: * If OBUF doesn't have NEEDED bytes after OPTR, make it bigger.
7612: *
7613: * As things stand, nothing is ever placed in the output buffer to be
7614: * removed again except when it's KNOWN to be part of an identifier,
7615: * so flushing and moving down everything left, instead of expanding,
7616: * should work ok.
7617: */
7618:
7619: /* You might think void was cleaner for the return type,
7620: but that would get type mismatch in check_expand in strict ANSI. */
7621: static int
7622: grow_outbuf (obuf, needed)
7623: register FILE_BUF *obuf;
7624: register int needed;
7625: {
7626: register U_CHAR *p;
7627: int minsize;
7628:
7629: if (obuf->length - (obuf->bufp - obuf->buf) > needed)
7630: return 0;
7631:
7632: /* Make it at least twice as big as it is now. */
7633: obuf->length *= 2;
7634: /* Make it have at least 150% of the free space we will need. */
7635: minsize = (3 * needed) / 2 + (obuf->bufp - obuf->buf);
7636: if (minsize > obuf->length)
7637: obuf->length = minsize;
7638:
7639: if ((p = (U_CHAR *) xrealloc (obuf->buf, obuf->length)) == NULL)
7640: memory_full ();
7641:
7642: obuf->bufp = p + (obuf->bufp - obuf->buf);
7643: obuf->buf = p;
7644:
7645: return 0;
7646: }
7647:
7648: /* Symbol table for macro names and special symbols */
7649:
7650: /*
7651: * install a name in the main hash table, even if it is already there.
7652: * name stops with first non alphanumeric, except leading '#'.
7653: * caller must check against redefinition if that is desired.
7654: * delete_macro () removes things installed by install () in fifo order.
7655: * this is important because of the `defined' special symbol used
7656: * in #if, and also if pushdef/popdef directives are ever implemented.
7657: *
7658: * If LEN is >= 0, it is the length of the name.
7659: * Otherwise, compute the length by scanning the entire name.
7660: *
7661: * If HASH is >= 0, it is the precomputed hash code.
7662: * Otherwise, compute the hash code.
7663: */
7664: static HASHNODE *
7665: install (name, len, type, value, hash)
7666: U_CHAR *name;
7667: int len;
7668: enum node_type type;
7669: int value;
7670: int hash;
7671: /* watch out here if sizeof (U_CHAR *) != sizeof (int) */
7672: {
7673: register HASHNODE *hp;
7674: register int i, bucket;
7675: register U_CHAR *p, *q;
7676:
7677: if (len < 0) {
7678: p = name;
7679: while (is_idchar[*p])
7680: p++;
7681: len = p - name;
7682: }
7683:
7684: if (hash < 0)
7685: hash = hashf (name, len, HASHSIZE);
7686:
7687: i = sizeof (HASHNODE) + len + 1;
7688: hp = (HASHNODE *) xmalloc (i);
7689: bucket = hash;
7690: hp->bucket_hdr = &hashtab[bucket];
7691: hp->next = hashtab[bucket];
7692: hashtab[bucket] = hp;
7693: hp->prev = NULL;
7694: if (hp->next != NULL)
7695: hp->next->prev = hp;
7696: hp->type = type;
7697: hp->length = len;
7698: hp->value.ival = value;
7699: hp->name = ((U_CHAR *) hp) + sizeof (HASHNODE);
7700: p = hp->name;
7701: q = name;
7702: for (i = 0; i < len; i++)
7703: *p++ = *q++;
7704: hp->name[len] = 0;
7705: return hp;
7706: }
7707:
7708: /*
7709: * find the most recent hash node for name name (ending with first
7710: * non-identifier char) installed by install
7711: *
7712: * If LEN is >= 0, it is the length of the name.
7713: * Otherwise, compute the length by scanning the entire name.
7714: *
7715: * If HASH is >= 0, it is the precomputed hash code.
7716: * Otherwise, compute the hash code.
7717: */
7718: HASHNODE *
7719: lookup (name, len, hash)
7720: U_CHAR *name;
7721: int len;
7722: int hash;
7723: {
7724: register U_CHAR *bp;
7725: register HASHNODE *bucket;
7726:
7727: if (len < 0) {
7728: for (bp = name; is_idchar[*bp]; bp++) ;
7729: len = bp - name;
7730: }
7731:
7732: if (hash < 0)
7733: hash = hashf (name, len, HASHSIZE);
7734:
7735: bucket = hashtab[hash];
7736: while (bucket) {
7737: if (bucket->length == len && strncmp (bucket->name, name, len) == 0)
7738: return bucket;
7739: bucket = bucket->next;
7740: }
7741: return NULL;
7742: }
7743:
7744: /*
7745: * Delete a hash node. Some weirdness to free junk from macros.
7746: * More such weirdness will have to be added if you define more hash
7747: * types that need it.
7748: */
7749:
7750: /* Note that the DEFINITION of a macro is removed from the hash table
7751: but its storage is not freed. This would be a storage leak
7752: except that it is not reasonable to keep undefining and redefining
7753: large numbers of macros many times.
7754: In any case, this is necessary, because a macro can be #undef'd
7755: in the middle of reading the arguments to a call to it.
7756: If #undef freed the DEFINITION, that would crash. */
7757:
7758: static void
7759: delete_macro (hp)
7760: HASHNODE *hp;
7761: {
7762:
7763: if (hp->prev != NULL)
7764: hp->prev->next = hp->next;
7765: if (hp->next != NULL)
7766: hp->next->prev = hp->prev;
7767:
7768: /* make sure that the bucket chain header that
7769: the deleted guy was on points to the right thing afterwards. */
7770: if (hp == *hp->bucket_hdr)
7771: *hp->bucket_hdr = hp->next;
7772:
7773: #if 0
7774: if (hp->type == T_MACRO) {
7775: DEFINITION *d = hp->value.defn;
7776: struct reflist *ap, *nextap;
7777:
7778: for (ap = d->pattern; ap != NULL; ap = nextap) {
7779: nextap = ap->next;
7780: free (ap);
7781: }
7782: free (d);
7783: }
7784: #endif
7785: free (hp);
7786: }
7787:
7788: /*
7789: * return hash function on name. must be compatible with the one
7790: * computed a step at a time, elsewhere
7791: */
7792: static int
7793: hashf (name, len, hashsize)
7794: register U_CHAR *name;
7795: register int len;
7796: int hashsize;
7797: {
7798: register int r = 0;
7799:
7800: while (len--)
7801: r = HASHSTEP (r, *name++);
7802:
7803: return MAKE_POS (r) % hashsize;
7804: }
7805:
7806:
7807: /* Dump the definition of a single macro HP to OF. */
7808: static void
7809: dump_single_macro (hp, of)
7810: register HASHNODE *hp;
7811: FILE *of;
7812: {
7813: register DEFINITION *defn = hp->value.defn;
7814: struct reflist *ap;
7815: int offset;
7816: int concat;
7817:
7818:
7819: /* Print the definition of the macro HP. */
7820:
7821: fprintf (of, "#define %s", hp->name);
7822:
7823: if (defn->nargs >= 0) {
7824: int i;
7825:
7826: fprintf (of, "(");
7827: for (i = 0; i < defn->nargs; i++) {
7828: dump_arg_n (defn, i, of);
7829: if (i + 1 < defn->nargs)
7830: fprintf (of, ", ");
7831: }
7832: fprintf (of, ")");
7833: }
7834:
7835: fprintf (of, " ");
7836:
7837: offset = 0;
7838: concat = 0;
7839: for (ap = defn->pattern; ap != NULL; ap = ap->next) {
7840: dump_defn_1 (defn->expansion, offset, ap->nchars, of);
7841: if (ap->nchars != 0)
7842: concat = 0;
7843: offset += ap->nchars;
7844: if (ap->stringify)
7845: fprintf (of, " #");
7846: if (ap->raw_before && !concat)
7847: fprintf (of, " ## ");
7848: concat = 0;
7849: dump_arg_n (defn, ap->argno, of);
7850: if (ap->raw_after) {
7851: fprintf (of, " ## ");
7852: concat = 1;
7853: }
7854: }
7855: dump_defn_1 (defn->expansion, offset, defn->length - offset, of);
7856: fprintf (of, "\n");
7857: }
7858:
7859: /* Dump all macro definitions as #defines to stdout. */
7860:
7861: static void
7862: dump_all_macros ()
7863: {
7864: int bucket;
7865:
7866: for (bucket = 0; bucket < HASHSIZE; bucket++) {
7867: register HASHNODE *hp;
7868:
7869: for (hp = hashtab[bucket]; hp; hp= hp->next) {
7870: if (hp->type == T_MACRO)
7871: dump_single_macro (hp, stdout);
7872: }
7873: }
7874: }
7875:
7876: /* Output to OF a substring of a macro definition.
7877: BASE is the beginning of the definition.
7878: Output characters START thru LENGTH.
7879: Discard newlines outside of strings, thus
7880: converting funny-space markers to ordinary spaces. */
7881:
7882: static void
7883: dump_defn_1 (base, start, length, of)
7884: U_CHAR *base;
7885: int start;
7886: int length;
7887: FILE *of;
7888: {
7889: U_CHAR *p = base + start;
7890: U_CHAR *limit = base + start + length;
7891:
7892: while (p < limit) {
7893: if (*p != '\n')
7894: putc (*p, of);
7895: else if (*p == '\"' || *p =='\'') {
7896: U_CHAR *p1 = skip_quoted_string (p, limit, 0, 0, 0, 0);
7897: fwrite (p, p1 - p, 1, of);
7898: p = p1 - 1;
7899: }
7900: p++;
7901: }
7902: }
7903:
7904: /* Print the name of argument number ARGNUM of macro definition DEFN
7905: to OF.
7906: Recall that DEFN->args.argnames contains all the arg names
7907: concatenated in reverse order with comma-space in between. */
7908:
7909: static void
7910: dump_arg_n (defn, argnum, of)
7911: DEFINITION *defn;
7912: int argnum;
7913: FILE *of;
7914: {
7915: register U_CHAR *p = defn->args.argnames;
7916: while (argnum + 1 < defn->nargs) {
7917: p = (U_CHAR *) index (p, ' ') + 1;
7918: argnum++;
7919: }
7920:
7921: while (*p && *p != ',') {
7922: putc (*p, of);
7923: p++;
7924: }
7925: }
7926:
7927: /* Initialize syntactic classifications of characters. */
7928:
7929: static void
7930: initialize_char_syntax ()
7931: {
7932: register int i;
7933:
7934: /*
7935: * Set up is_idchar and is_idstart tables. These should be
7936: * faster than saying (is_alpha (c) || c == '_'), etc.
7937: * Set up these things before calling any routines tthat
7938: * refer to them.
7939: */
7940: for (i = 'a'; i <= 'z'; i++) {
7941: is_idchar[i - 'a' + 'A'] = 1;
7942: is_idchar[i] = 1;
7943: is_idstart[i - 'a' + 'A'] = 1;
7944: is_idstart[i] = 1;
7945: }
7946: for (i = '0'; i <= '9'; i++)
7947: is_idchar[i] = 1;
7948: is_idchar['_'] = 1;
7949: is_idstart['_'] = 1;
7950: is_idchar['$'] = dollars_in_ident;
7951: is_idstart['$'] = dollars_in_ident;
7952:
7953: /* horizontal space table */
7954: is_hor_space[' '] = 1;
7955: is_hor_space['\t'] = 1;
7956: is_hor_space['\v'] = 1;
7957: is_hor_space['\f'] = 1;
7958: is_hor_space['\r'] = 1;
7959:
7960: is_space[' '] = 1;
7961: is_space['\t'] = 1;
7962: is_space['\v'] = 1;
7963: is_space['\f'] = 1;
7964: is_space['\n'] = 1;
7965: is_space['\r'] = 1;
7966: }
7967:
7968: /* Initialize the built-in macros. */
7969:
7970: static void
7971: initialize_builtins (inp, outp)
7972: FILE_BUF *inp;
7973: FILE_BUF *outp;
7974: {
7975: time_t t;
7976:
7977: t = time (0);
7978: timebuf = localtime (&t);
7979:
7980: install ("__LINE__", -1, T_SPECLINE, 0, -1);
7981: install ("__DATE__", -1, T_DATE, 0, -1);
7982: install ("__FILE__", -1, T_FILE, 0, -1);
7983: install ("__BASE_FILE__", -1, T_BASE_FILE, 0, -1);
7984: install ("__INCLUDE_LEVEL__", -1, T_INCLUDE_LEVEL, 0, -1);
7985: install ("__VERSION__", -1, T_VERSION, 0, -1);
7986: install ("__SIZE_TYPE__", -1, T_SIZE_TYPE, 0, -1);
7987: install ("__PTRDIFF_TYPE__ ", -1, T_PTRDIFF_TYPE, 0, -1);
7988: install ("__WCHAR_TYPE__", -1, T_WCHAR_TYPE, 0, -1);
7989: install ("__TIME__", -1, T_TIME, 0, -1);
7990: if (!traditional)
7991: install ("__STDC__", -1, T_CONST, STDC_VALUE, -1);
7992: if (objc)
7993: install ("__OBJC__", -1, T_CONST, 1, -1);
7994: /* This is supplied using a -D by the compiler driver
7995: so that it is present only when truly compiling with GNU C. */
7996: /* install ("__GNUC__", -1, T_CONST, 2, -1); */
7997:
7998: if (debug_output)
7999: {
8000: char directive[2048];
8001: register struct directive *dp = &directive_table[0];
8002:
8003: sprintf (directive, " __BASE_FILE__ \"%s\"",
8004: instack[0].nominal_fname);
8005: output_line_command (inp, outp, 0, same_file);
8006: pass_thru_directive (directive, &directive[strlen (directive)], outp, dp);
8007:
8008: sprintf (directive, " __VERSION__ \"%s\"", version_string);
8009: output_line_command (inp, outp, 0, same_file);
8010: pass_thru_directive (directive, &directive[strlen (directive)], outp, dp);
8011:
8012: sprintf (directive, " __SIZE_TYPE__ %s", SIZE_TYPE);
8013: output_line_command (inp, outp, 0, same_file);
8014: pass_thru_directive (directive, &directive[strlen (directive)], outp, dp);
8015:
8016: sprintf (directive, " __PTRDIFF_TYPE__ %s", PTRDIFF_TYPE);
8017: output_line_command (inp, outp, 0, same_file);
8018: pass_thru_directive (directive, &directive[strlen (directive)], outp, dp);
8019:
8020: sprintf (directive, " __WCHAR_TYPE__ %s", WCHAR_TYPE);
8021: output_line_command (inp, outp, 0, same_file);
8022: pass_thru_directive (directive, &directive[strlen (directive)], outp, dp);
8023:
8024: sprintf (directive, " __WCHAR_TYPE__ %s", WCHAR_TYPE);
8025: output_line_command (inp, outp, 0, same_file);
8026: pass_thru_directive (directive, &directive[strlen (directive)], outp, dp);
8027:
8028: sprintf (directive, " __DATE__ \"%s %2d %4d\"",
8029: monthnames[timebuf->tm_mon],
8030: timebuf->tm_mday, timebuf->tm_year + 1900);
8031: output_line_command (inp, outp, 0, same_file);
8032: pass_thru_directive (directive, &directive[strlen (directive)], outp, dp);
8033:
8034: sprintf (directive, " __TIME__ \"%02d:%02d:%02d\"",
8035: timebuf->tm_hour, timebuf->tm_min, timebuf->tm_sec);
8036: output_line_command (inp, outp, 0, same_file);
8037: pass_thru_directive (directive, &directive[strlen (directive)], outp, dp);
8038:
8039: if (!traditional)
8040: {
8041: sprintf (directive, " __STDC__ 1");
8042: output_line_command (inp, outp, 0, same_file);
8043: pass_thru_directive (directive, &directive[strlen (directive)],
8044: outp, dp);
8045: }
8046: if (objc)
8047: {
8048: sprintf (directive, " __OBJC__ 1");
8049: output_line_command (inp, outp, 0, same_file);
8050: pass_thru_directive (directive, &directive[strlen (directive)],
8051: outp, dp);
8052: }
8053: }
8054: }
8055:
8056: /*
8057: * process a given definition string, for initialization
8058: * If STR is just an identifier, define it with value 1.
8059: * If STR has anything after the identifier, then it should
8060: * be identifier=definition.
8061: */
8062:
8063: static void
8064: make_definition (str, op)
8065: U_CHAR *str;
8066: FILE_BUF *op;
8067: {
8068: FILE_BUF *ip;
8069: struct directive *kt;
8070: U_CHAR *buf, *p;
8071:
8072: buf = str;
8073: p = str;
8074: if (!is_idstart[*p]) {
8075: error ("malformed option `-D %s'", str);
8076: return;
8077: }
8078: while (is_idchar[*++p])
8079: ;
8080: if (*p == 0) {
8081: buf = (U_CHAR *) alloca (p - buf + 4);
8082: strcpy ((char *)buf, str);
8083: strcat ((char *)buf, " 1");
8084: } else if (*p != '=') {
8085: error ("malformed option `-D %s'", str);
8086: return;
8087: } else {
8088: U_CHAR *q;
8089: /* Copy the entire option so we can modify it. */
8090: buf = (U_CHAR *) alloca (2 * strlen (str) + 1);
8091: strncpy (buf, str, p - str);
8092: /* Change the = to a space. */
8093: buf[p - str] = ' ';
8094: /* Scan for any backslash-newline and remove it. */
8095: p++;
8096: q = &buf[p - str];
8097: while (*p) {
8098: if (*p == '\\' && p[1] == '\n')
8099: p += 2;
8100: /* Change newline chars into newline-markers. */
8101: else if (*p == '\n')
8102: {
8103: *q++ = '\n';
8104: *q++ = '\n';
8105: p++;
8106: }
8107: else
8108: *q++ = *p++;
8109: }
8110: *q = 0;
8111: }
8112:
8113: ip = &instack[++indepth];
8114: ip->nominal_fname = ip->fname = "*Initialization*";
8115:
8116: ip->buf = ip->bufp = buf;
8117: ip->length = strlen (buf);
8118: ip->lineno = 1;
8119: ip->macro = 0;
8120: ip->free_ptr = 0;
8121: ip->if_stack = if_stack;
8122: ip->system_header_p = 0;
8123:
8124: for (kt = directive_table; kt->type != T_DEFINE; kt++)
8125: ;
8126:
8127: do_define (buf, buf + strlen (buf) , op, kt);
8128: --indepth;
8129: }
8130:
8131: /* JF, this does the work for the -U option */
8132:
8133: static void
8134: make_undef (str, op)
8135: U_CHAR *str;
8136: FILE_BUF *op;
8137: {
8138: FILE_BUF *ip;
8139: struct directive *kt;
8140:
8141: ip = &instack[++indepth];
8142: ip->nominal_fname = ip->fname = "*undef*";
8143:
8144: ip->buf = ip->bufp = str;
8145: ip->length = strlen (str);
8146: ip->lineno = 1;
8147: ip->macro = 0;
8148: ip->free_ptr = 0;
8149: ip->if_stack = if_stack;
8150: ip->system_header_p = 0;
8151:
8152: for (kt = directive_table; kt->type != T_UNDEF; kt++)
8153: ;
8154:
8155: do_undef (str, str + strlen (str), op, kt);
8156: --indepth;
8157: }
8158:
8159: /* Process the string STR as if it appeared as the body of a #assert.
8160: OPTION is the option name for which STR was the argument. */
8161:
8162: static void
8163: make_assertion (option, str)
8164: char *option;
8165: U_CHAR *str;
8166: {
8167: FILE_BUF *ip;
8168: struct directive *kt;
8169: U_CHAR *buf, *p, *q;
8170:
8171: /* Copy the entire option so we can modify it. */
8172: buf = (U_CHAR *) alloca (strlen (str) + 1);
8173: strcpy ((char *) buf, str);
8174: /* Scan for any backslash-newline and remove it. */
8175: p = q = buf;
8176: while (*p) {
8177: if (*p == '\\' && p[1] == '\n')
8178: p += 2;
8179: else
8180: *q++ = *p++;
8181: }
8182: *q = 0;
8183:
8184: p = buf;
8185: if (!is_idstart[*p]) {
8186: error ("malformed option `%s %s'", option, str);
8187: return;
8188: }
8189: while (is_idchar[*++p])
8190: ;
8191: while (*p == ' ' || *p == '\t') p++;
8192: if (! (*p == 0 || *p == '(')) {
8193: error ("malformed option `%s %s'", option, str);
8194: return;
8195: }
8196:
8197: ip = &instack[++indepth];
8198: ip->nominal_fname = ip->fname = "*Initialization*";
8199:
8200: ip->buf = ip->bufp = buf;
8201: ip->length = strlen (buf);
8202: ip->lineno = 1;
8203: ip->macro = 0;
8204: ip->free_ptr = 0;
8205: ip->if_stack = if_stack;
8206: ip->system_header_p = 0;
8207:
8208: for (kt = directive_table; kt->type != T_ASSERT; kt++)
8209: ;
8210:
8211: /* pass NULL as output ptr to do_define since we KNOW it never
8212: does any output.... */
8213: do_assert (buf, buf + strlen (buf) , NULL, kt);
8214: --indepth;
8215: }
8216:
8217: /* Add output to `deps_buffer' for the -M switch.
8218: STRING points to the text to be output.
8219: SIZE is the number of bytes, or 0 meaning output until a null.
8220: Outputting the empty string breaks the line if it is long enough. */
8221:
8222: static void
8223: deps_output (string, size)
8224: char *string;
8225: unsigned size;
8226: {
8227: if (size == 0)
8228: size = strlen (string);
8229:
8230: #ifndef MAX_OUTPUT_COLUMNS
8231: #define MAX_OUTPUT_COLUMNS 75
8232: #endif
8233: if (size == 0 && deps_column != 0
8234: && size + deps_column > MAX_OUTPUT_COLUMNS) {
8235: deps_output ("\\\n ", 0);
8236: deps_column = 0;
8237: }
8238:
8239: if (deps_size + size + 1 > deps_allocated_size) {
8240: deps_allocated_size = deps_size + size + 50;
8241: deps_allocated_size *= 2;
8242: deps_buffer = (char *) xrealloc (deps_buffer, deps_allocated_size);
8243: }
8244: bcopy (string, &deps_buffer[deps_size], size);
8245: deps_size += size;
8246: deps_column += size;
8247: deps_buffer[deps_size] = 0;
8248: }
8249:
8250: #if defined(USG) || defined(VMS)
8251: #ifndef BSTRING
8252:
8253: void
8254: bzero (b, length)
8255: register char *b;
8256: register unsigned length;
8257: {
8258: #ifdef VMS
8259: short zero = 0;
8260: long max_str = 65535;
8261:
8262: while (length > max_str) {
8263: (void) LIB$MOVC5 (&zero, &zero, &zero, &max_str, b);
8264: length -= max_str;
8265: b += max_str;
8266: }
8267: (void) LIB$MOVC5 (&zero, &zero, &zero, &length, b);
8268: #else
8269: while (length-- > 0)
8270: *b++ = 0;
8271: #endif /* not VMS */
8272: }
8273:
8274: void
8275: bcopy (b1, b2, length)
8276: register char *b1;
8277: register char *b2;
8278: register unsigned length;
8279: {
8280: #ifdef VMS
8281: long max_str = 65535;
8282:
8283: while (length > max_str) {
8284: (void) LIB$MOVC3 (&max_str, b1, b2);
8285: length -= max_str;
8286: b1 += max_str;
8287: b2 += max_str;
8288: }
8289: (void) LIB$MOVC3 (&length, b1, b2);
8290: #else
8291: while (length-- > 0)
8292: *b2++ = *b1++;
8293: #endif /* not VMS */
8294: }
8295:
8296: int
8297: bcmp (b1, b2, length) /* This could be a macro! */
8298: register char *b1;
8299: register char *b2;
8300: register unsigned length;
8301: {
8302: #ifdef VMS
8303: struct dsc$descriptor_s src1 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b1};
8304: struct dsc$descriptor_s src2 = {length, DSC$K_DTYPE_T, DSC$K_CLASS_S, b2};
8305:
8306: return STR$COMPARE (&src1, &src2);
8307: #else
8308: while (length-- > 0)
8309: if (*b1++ != *b2++)
8310: return 1;
8311:
8312: return 0;
8313: #endif /* not VMS */
8314: }
8315: #endif /* not BSTRING */
8316: #endif /* USG or VMS */
8317:
8318:
8319: static void
8320: fatal (str, arg)
8321: char *str, *arg;
8322: {
8323: if (deps_file)
8324: unlink (deps_file);
8325: fprintf (stderr, "%s: ", progname);
8326: fprintf (stderr, str, arg);
8327: fprintf (stderr, "\n");
8328: exit (FAILURE_EXIT_CODE);
8329: }
8330:
8331: /* More 'friendly' abort that prints the line and file.
8332: config.h can #define abort fancy_abort if you like that sort of thing. */
8333:
8334: void
8335: fancy_abort ()
8336: {
8337: fatal ("Internal gcc abort.");
8338: }
8339:
8340: static void
8341: perror_with_name (name)
8342: char *name;
8343: {
8344: fprintf (stderr, "%s: ", progname);
8345: if (errno < sys_nerr)
8346: fprintf (stderr, "%s: %s\n", name, sys_errlist[errno]);
8347: else
8348: fprintf (stderr, "%s: undocumented I/O error\n", name);
8349: errors++;
8350: }
8351:
8352: static void
8353: pfatal_with_name (name)
8354: char *name;
8355: {
8356: perror_with_name (name);
8357: #ifdef VMS
8358: exit (vaxc$errno);
8359: #else
8360: exit (FAILURE_EXIT_CODE);
8361: #endif
8362: }
8363:
8364:
8365: static void
8366: memory_full ()
8367: {
8368: fatal ("Memory exhausted.");
8369: }
8370:
8371:
8372: char *
8373: xmalloc (size)
8374: unsigned size;
8375: {
8376: register char *ptr = (char *) malloc (size);
8377: if (ptr != 0) return (ptr);
8378: memory_full ();
8379: /*NOTREACHED*/
8380: return 0;
8381: }
8382:
8383: static char *
8384: xrealloc (old, size)
8385: char *old;
8386: unsigned size;
8387: {
8388: register char *ptr = (char *) realloc (old, size);
8389: if (ptr != 0) return (ptr);
8390: memory_full ();
8391: /*NOTREACHED*/
8392: return 0;
8393: }
8394:
8395: static char *
8396: xcalloc (number, size)
8397: unsigned number, size;
8398: {
8399: register unsigned total = number * size;
8400: register char *ptr = (char *) malloc (total);
8401: if (ptr != 0) {
8402: if (total > 100)
8403: bzero (ptr, total);
8404: else {
8405: /* It's not too long, so loop, zeroing by longs.
8406: It must be safe because malloc values are always well aligned. */
8407: register long *zp = (long *) ptr;
8408: register long *zl = (long *) (ptr + total - 4);
8409: register int i = total - 4;
8410: while (zp < zl)
8411: *zp++ = 0;
8412: if (i < 0)
8413: i = 0;
8414: while (i < total)
8415: ptr[i++] = 0;
8416: }
8417: return ptr;
8418: }
8419: memory_full ();
8420: /*NOTREACHED*/
8421: return 0;
8422: }
8423:
8424: static char *
8425: savestring (input)
8426: char *input;
8427: {
8428: unsigned size = strlen (input);
8429: char *output = xmalloc (size + 1);
8430: strcpy (output, input);
8431: return output;
8432: }
8433:
8434: /* Get the file-mode and data size of the file open on FD
8435: and store them in *MODE_POINTER and *SIZE_POINTER. */
8436:
8437: static int
8438: file_size_and_mode (fd, mode_pointer, size_pointer)
8439: int fd;
8440: int *mode_pointer;
8441: long int *size_pointer;
8442: {
8443: struct stat sbuf;
8444:
8445: if (fstat (fd, &sbuf) < 0) return (-1);
8446: if (mode_pointer) *mode_pointer = sbuf.st_mode;
8447: if (size_pointer) *size_pointer = sbuf.st_size;
8448: return 0;
8449: }
8450:
8451: #ifdef VMS
8452:
8453: /* Under VMS we need to fix up the "include" specification
8454: filename so that everything following the 1st slash is
8455: changed into its correct VMS file specification. */
8456:
8457: static void
8458: hack_vms_include_specification (fname)
8459: char *fname;
8460: {
8461: register char *cp, *cp1, *cp2;
8462: int f, check_filename_before_returning, no_prefix_seen;
8463: char Local[512];
8464:
8465: check_filename_before_returning = 0;
8466: no_prefix_seen = 0;
8467:
8468: /* Ignore leading "./"s */
8469: while (fname[0] == '.' && fname[1] == '/') {
8470: strcpy (fname, fname+2);
8471: no_prefix_seen = 1; /* mark this for later */
8472: }
8473: /* Look for the boundary between the VMS and UNIX filespecs */
8474: cp = rindex (fname, ']'); /* Look for end of dirspec. */
8475: if (cp == 0) cp = rindex (fname, '>'); /* ... Ditto */
8476: if (cp == 0) cp = rindex (fname, ':'); /* Look for end of devspec. */
8477: if (cp) {
8478: cp++;
8479: } else {
8480: cp = index (fname, '/'); /* Look for the "/" */
8481: }
8482:
8483: cp2 = Local; /* initialize */
8484:
8485: /* We are trying to do a number of things here. First of all, we are
8486: trying to hammer the filenames into a standard format, such that later
8487: processing can handle them.
8488:
8489: If the file name contains something like [dir.], then it recognizes this
8490: as a root, and strips the ".]". Later processing will add whatever is
8491: needed to get things working properly.
8492:
8493: If no device is specified, then the first directory name is taken to be
8494: a device name (or a rooted logical). */
8495:
8496: /* See if we found that 1st slash */
8497: if (cp == 0) return; /* Nothing to do!!! */
8498: if (*cp != '/') return; /* Nothing to do!!! */
8499: /* Point to the UNIX filename part (which needs to be fixed!) */
8500: cp1 = cp+1;
8501: /* If the directory spec is not rooted, we can just copy
8502: the UNIX filename part and we are done */
8503: if (((cp - fname) > 1) && ((cp[-1] == ']') || (cp[-1] == '>'))) {
8504: if (cp[-2] != '.') {
8505: /*
1.1.1.2 ! root 8506: * The VMS part ends in a `]', and the preceding character is not a `.'.
1.1 root 8507: * We strip the `]', and then splice the two parts of the name in the
8508: * usual way. Given the default locations for include files in cccp.c,
8509: * we will only use this code if the user specifies alternate locations
8510: * with the /include (-I) switch on the command line. */
8511: cp -= 1; /* Strip "]" */
8512: cp1--; /* backspace */
8513: } else {
8514: /*
8515: * The VMS part has a ".]" at the end, and this will not do. Later
8516: * processing will add a second directory spec, and this would be a syntax
8517: * error. Thus we strip the ".]", and thus merge the directory specs.
8518: * We also backspace cp1, so that it points to a '/'. This inhibits the
8519: * generation of the 000000 root directory spec (which does not belong here
8520: * in this case).
8521: */
8522: cp -= 2; /* Strip ".]" */
8523: cp1--; }; /* backspace */
8524: } else {
8525:
8526: /* We drop in here if there is no VMS style directory specification yet.
8527: * If there is no device specification either, we make the first dir a
8528: * device and try that. If we do not do this, then we will be essentially
8529: * searching the users default directory (as if they did a #include "asdf.h").
8530: *
8531: * Then all we need to do is to push a '[' into the output string. Later
8532: * processing will fill this in, and close the bracket.
8533: */
8534: if(cp[-1] != ':') *cp2++ = ':'; /* dev not in spec. take first dir */
8535: *cp2++ = '['; /* Open the directory specification */
8536: }
8537:
8538: /* at this point we assume that we have the device spec, and (at least
8539: the opening "[" for a directory specification. We may have directories
8540: specified already */
8541:
8542: /* If there are no other slashes then the filename will be
8543: in the "root" directory. Otherwise, we need to add
8544: directory specifications. */
8545: if (index (cp1, '/') == 0) {
8546: /* Just add "000000]" as the directory string */
8547: strcpy (cp2, "000000]");
8548: cp2 += strlen (cp2);
8549: check_filename_before_returning = 1; /* we might need to fool with this later */
8550: } else {
8551: /* As long as there are still subdirectories to add, do them. */
8552: while (index (cp1, '/') != 0) {
8553: /* If this token is "." we can ignore it */
8554: if ((cp1[0] == '.') && (cp1[1] == '/')) {
8555: cp1 += 2;
8556: continue;
8557: }
8558: /* Add a subdirectory spec. Do not duplicate "." */
8559: if (cp2[-1] != '.' && cp2[-1] != '[' && cp2[-1] != '<')
8560: *cp2++ = '.';
8561: /* If this is ".." then the spec becomes "-" */
8562: if ((cp1[0] == '.') && (cp1[1] == '.') && (cp[2] == '/')) {
8563: /* Add "-" and skip the ".." */
8564: *cp2++ = '-';
8565: cp1 += 3;
8566: continue;
8567: }
8568: /* Copy the subdirectory */
8569: while (*cp1 != '/') *cp2++= *cp1++;
8570: cp1++; /* Skip the "/" */
8571: }
8572: /* Close the directory specification */
8573: if(cp2[-1] == '.') /* no trailing periods */
8574: cp2--;
8575: *cp2++ = ']';
8576: }
8577: /* Now add the filename */
8578: while (*cp1) *cp2++ = *cp1++;
8579: *cp2 = 0;
8580: /* Now append it to the original VMS spec. */
8581: strcpy (cp, Local);
8582:
8583: /* If we put a [000000] in the filename, try to open it first. If this fails,
8584: remove the [000000], and return that name. This provides flexibility
8585: to the user in that they can use both rooted and non-rooted logical names
8586: to point to the location of the file. */
8587:
8588: if (check_filename_before_returning && no_prefix_seen) {
8589: f = open (fname, O_RDONLY, 0666);
8590: if (f >= 0) {
8591: /* The file name is OK as it is, so return it as is. */
8592: close (f);
8593: return;
8594: }
8595: /* The filename did not work. Try to remove the [000000] from the name,
8596: and return it. */
8597: cp = index (fname, '[');
8598: cp2 = index (fname, ']') + 1;
8599: strcpy (cp, cp2); /* this gets rid of it */
8600: }
8601: return;
8602: }
8603: #endif /* VMS */
8604:
8605: #ifdef VMS
8606:
8607: /* These are the read/write replacement routines for
8608: VAX-11 "C". They make read/write behave enough
8609: like their UNIX counterparts that CCCP will work */
8610:
8611: static int
8612: read (fd, buf, size)
8613: int fd;
8614: char *buf;
8615: int size;
8616: {
8617: #undef read /* Get back the REAL read routine */
8618: register int i;
8619: register int total = 0;
8620:
8621: /* Read until the buffer is exhausted */
8622: while (size > 0) {
8623: /* Limit each read to 32KB */
8624: i = (size > (32*1024)) ? (32*1024) : size;
8625: i = read (fd, buf, i);
8626: if (i <= 0) {
8627: if (i == 0) return (total);
8628: return(i);
8629: }
8630: /* Account for this read */
8631: total += i;
8632: buf += i;
8633: size -= i;
8634: }
8635: return (total);
8636: }
8637:
8638: static int
8639: write (fd, buf, size)
8640: int fd;
8641: char *buf;
8642: int size;
8643: {
8644: #undef write /* Get back the REAL write routine */
8645: int i;
8646: int j;
8647:
8648: /* Limit individual writes to 32Kb */
8649: i = size;
8650: while (i > 0) {
8651: j = (i > (32*1024)) ? (32*1024) : i;
8652: if (write (fd, buf, j) < 0) return (-1);
8653: /* Account for the data written */
8654: buf += j;
8655: i -= j;
8656: }
8657: return (size);
8658: }
8659:
8660: /* The following wrapper functions supply additional arguments to the VMS
8661: I/O routines to optimize performance with file handling. The arguments
8662: are:
8663: "mbc=16" - Set multi-block count to 16 (use a 8192 byte buffer).
8664: "deq=64" - When extending the file, extend it in chunks of 32Kbytes.
8665: "fop=tef"- Truncate unused portions of file when closing file.
8666: "shr=nil"- Disallow file sharing while file is open.
8667: */
8668:
8669: static FILE *
8670: freopen (fname, type, oldfile)
8671: char *fname;
8672: char *type;
8673: FILE *oldfile;
8674: {
8675: #undef freopen /* Get back the REAL fopen routine */
8676: if (strcmp (type, "w") == 0)
8677: return freopen (fname, type, oldfile, "mbc=16", "deq=64", "fop=tef", "shr=nil");
8678: return freopen (fname, type, oldfile, "mbc=16");
8679: }
8680:
8681: static FILE *
8682: fopen (fname, type)
8683: char *fname;
8684: char *type;
8685: {
8686: #undef fopen /* Get back the REAL fopen routine */
8687: if (strcmp (type, "w") == 0)
8688: return fopen (fname, type, "mbc=16", "deq=64", "fop=tef", "shr=nil");
8689: return fopen (fname, type, "mbc=16");
8690: }
8691:
8692: static int
8693: open (fname, flags, prot)
8694: char *fname;
8695: int flags;
8696: int prot;
8697: {
8698: #undef open /* Get back the REAL open routine */
8699: return open (fname, flags, prot, "mbc=16", "deq=64", "fop=tef");
8700: }
8701:
8702: #endif /* VMS */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.