/* CPP Library. Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. Contributed by Per Bothner, 1994-95. Based on CCCP program by Paul Rubin, June 1986 Adapted to ANSI C, Richard Stallman, Jan 1987 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "config.h" #include "system.h" #include "cpplib.h" #include "cpphash.h" #include "intl.h" #include "symcat.h" /* `struct directive' defines one #-directive, including how to handle it. */ struct directive { directive_handler func; /* Function to handle directive. */ const U_CHAR *name; /* Name of directive. */ unsigned short length; /* Length of name. */ unsigned short flags; /* Flags describing this directive. */ }; /* Stack of conditionals currently in progress (including both successful and failing conditionals). */ struct if_stack { struct if_stack *next; int lineno; /* line number where condition started */ int if_succeeded; /* truth of last condition in this group */ const U_CHAR *control_macro; /* macro name for #ifndef around entire file */ int type; /* type of last directive seen in this group */ }; typedef struct if_stack IF_STACK; /* Forward declarations. */ static void validate_else PARAMS ((cpp_reader *, const U_CHAR *)); static int parse_ifdef PARAMS ((cpp_reader *, const U_CHAR *)); static unsigned int parse_include PARAMS ((cpp_reader *, const U_CHAR *)); static int conditional_skip PARAMS ((cpp_reader *, int, int, U_CHAR *)); static int skip_if_group PARAMS ((cpp_reader *)); static void pass_thru_directive PARAMS ((const U_CHAR *, size_t, cpp_reader *, int)); static int read_line_number PARAMS ((cpp_reader *, int *)); static U_CHAR *detect_if_not_defined PARAMS ((cpp_reader *)); static int consider_directive_while_skipping PARAMS ((cpp_reader *, IF_STACK *)); /* Values for the flags field of the table below. KANDR and COND directives come from traditional (K&R) C. The difference is, if we care about it while skipping a failed conditional block, its origin is COND. STDC89 directives come from the 1989 C standard. EXTENSION directives are extensions, with origins noted below. */ #define KANDR 0 #define COND 1 #define STDC89 2 #define EXTENSION 3 #define ORIGIN_MASK 3 #define ORIGIN(f) ((f) & ORIGIN_MASK) #define TRAD_DIRECT_P(f) (ORIGIN (f) == KANDR || ORIGIN (f) == COND) /* This is the table of directive handlers. It is ordered by frequency of occurrence; the numbers at the end are directive counts from all the source code I have lying around (egcs and libc CVS as of 1999-05-18, plus grub-0.5.91, linux-2.2.9, and pcmcia-cs-3.0.9). The entries with a dash and a name after the count are extensions, of which all but #warning and #include_next are deprecated. The name is where the extension appears to have come from. */ /* #sccs is not always recognized. */ #ifdef SCCS_DIRECTIVE # define SCCS_ENTRY D(sccs, T_SCCS, EXTENSION) /* 0 - SVR2? */ #else # define SCCS_ENTRY /* nothing */ #endif #define DIRECTIVE_TABLE \ D(define, T_DEFINE = 0, KANDR) /* 270554 */ \ D(include, T_INCLUDE, KANDR | SYNTAX_INCLUDE) /* 52262 */ \ D(endif, T_ENDIF, COND) /* 45855 */ \ D(ifdef, T_IFDEF, COND) /* 22000 */ \ D(if, T_IF, COND) /* 18162 */ \ D(else, T_ELSE, COND) /* 9863 */ \ D(ifndef, T_IFNDEF, COND) /* 9675 */ \ D(undef, T_UNDEF, KANDR) /* 4837 */ \ D(line, T_LINE, KANDR) /* 2465 */ \ D(elif, T_ELIF, COND) /* 610 */ \ D(error, T_ERROR, STDC89) /* 475 */ \ D(pragma, T_PRAGMA, STDC89) /* 195 */ \ D(warning, T_WARNING, EXTENSION) /* 22 GNU */ \ D(include_next, T_INCLUDE_NEXT, EXTENSION | SYNTAX_INCLUDE) /* 19 GNU */ \ D(ident, T_IDENT, EXTENSION) /* 11 SVR4 */ \ D(import, T_IMPORT, EXTENSION | SYNTAX_INCLUDE) /* 0 ObjC */ \ D(assert, T_ASSERT, EXTENSION | SYNTAX_ASSERT) /* 0 SVR4 */ \ D(unassert, T_UNASSERT, EXTENSION | SYNTAX_ASSERT) /* 0 SVR4 */ \ SCCS_ENTRY /* Use the table to generate a series of prototypes, an enum for the directive names, and an array of directive handlers. */ /* The directive-processing functions are declared to return int instead of void, because some old compilers have trouble with pointers to functions returning void. */ /* Don't invoke CONCAT2 with any whitespace or K&R cc will fail. */ #define D(name, t, f) static int CONCAT2(do_,name) PARAMS ((cpp_reader *)); DIRECTIVE_TABLE #undef D #define D(n, tag, f) tag, enum { DIRECTIVE_TABLE N_DIRECTIVES }; #undef D /* Don't invoke CONCAT2 with any whitespace or K&R cc will fail. */ #define D(name, t, flags) \ { CONCAT2(do_,name), (const U_CHAR *) STRINGX(name), \ sizeof STRINGX(name) - 1, flags }, static const struct directive dtable[] = { DIRECTIVE_TABLE }; #undef D #undef DIRECTIVE_TABLE /* Check if a token's name matches that of a known directive. Put in this file to save exporting dtable and other unneeded information. */ void _cpp_check_directive (list, token) cpp_toklist *list; cpp_token *token; { const U_CHAR *name = list->namebuf + token->val.name.offset; size_t len = token->val.name.len; unsigned int i; list->dir_handler = 0; list->dir_flags = 0; for (i = 0; i < N_DIRECTIVES; i++) if (dtable[i].length == len && !ustrncmp (dtable[i].name, name, len)) { list->dir_handler = dtable[i].func; list->dir_flags = dtable[i].flags; break; } } /* Handle a possible # directive. '#' has already been read. */ int _cpp_handle_directive (pfile) cpp_reader *pfile; { int i; int hash_at_bol; unsigned int len; U_CHAR *ident; long old_written = CPP_WRITTEN (pfile); enum cpp_ttype tok; if (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile))) { cpp_ice (pfile, "handle_directive called on macro buffer"); return 0; } /* -traditional directives are recognized only with the # in column 1. */ hash_at_bol = CPP_IN_COLUMN_1 (pfile); /* Scan the next token, then pretend we didn't. */ CPP_SET_MARK (pfile); pfile->no_macro_expand++; tok = _cpp_get_directive_token (pfile); pfile->no_macro_expand--; ident = pfile->token_buffer + old_written; len = CPP_PWRITTEN (pfile) - ident; CPP_SET_WRITTEN (pfile, old_written); CPP_GOTO_MARK (pfile); /* # followed by a number is equivalent to #line. Do not recognize this form in assembly language source files. Complain about this form if we're being pedantic, but not if this is regurgitated input (preprocessed or fed back in by the C++ frontend). */ if (tok == CPP_NUMBER) { if (CPP_OPTION (pfile, lang_asm)) return 0; if (CPP_PEDANTIC (pfile) && CPP_BUFFER (pfile)->ihash && ! CPP_OPTION (pfile, preprocessed)) cpp_pedwarn (pfile, "# followed by integer"); do_line (pfile); return 1; } /* If we are rescanning preprocessed input, don't obey any directives other than # nnn. */ else if (CPP_OPTION (pfile, preprocessed)) return 0; /* A line of just # becomes blank. */ else if (tok == CPP_VSPACE) return 1; /* A NAME token might in fact be a directive! */ else if (tok == CPP_NAME) { for (i = 0; i < N_DIRECTIVES; i++) { if (dtable[i].length == len && !ustrncmp (dtable[i].name, ident, len)) goto real_directive; } /* Don't complain about invalid directives in assembly source, we don't know where the comments are, and # may introduce assembler pseudo-ops. */ if (!CPP_OPTION (pfile, lang_asm)) cpp_error (pfile, "invalid preprocessing directive #%s", ident); return 0; } /* And anything else means the # wasn't a directive marker. */ else return 0; real_directive: /* In -traditional mode, a directive is ignored unless its # is in column 1. */ if (CPP_TRADITIONAL (pfile) && !hash_at_bol) { if (CPP_WTRADITIONAL (pfile)) cpp_warning (pfile, "ignoring #%s because of its indented #", dtable[i].name); return 0; } /* no_directives is set when we are parsing macro arguments. Directives in macro arguments are undefined behavior (C99 6.10.3.11); this implementation chooses to make them hard errors. */ if (pfile->no_directives) { cpp_error (pfile, "#%s may not be used inside a macro argument", dtable[i].name); _cpp_skip_rest_of_line (pfile); return 1; } /* Issue -pedantic warnings for extended directives. */ if (CPP_PEDANTIC (pfile) && ORIGIN (dtable[i].flags) == EXTENSION) cpp_pedwarn (pfile, "ISO C does not allow #%s", dtable[i].name); /* -Wtraditional gives warnings about directives with inappropriate indentation of #. */ if (CPP_WTRADITIONAL (pfile)) { if (!hash_at_bol && TRAD_DIRECT_P (dtable[i].flags)) cpp_warning (pfile, "traditional C ignores #%s with the # indented", dtable[i].name); else if (hash_at_bol && ! TRAD_DIRECT_P (dtable[i].flags)) cpp_warning (pfile, "suggest hiding #%s from traditional C with an indented #", dtable[i].name); } /* Unfortunately, it's necessary to scan the directive name again, now we know we're going to consume it. FIXME. */ pfile->no_macro_expand++; _cpp_get_directive_token (pfile); pfile->no_macro_expand--; CPP_SET_WRITTEN (pfile, old_written); /* Some directives (e.g. #if) may return a request to execute another directive handler immediately. No directive ever requests that #define be executed immediately, so it is safe for the loop to terminate when some function returns 0 (== T_DEFINE). */ while ((i = dtable[i].func (pfile))); return 1; } /* Pass a directive through to the output file. BUF points to the contents of the directive, as a contiguous string. LEN is the length of the string pointed to by BUF. KEYWORD is the keyword-table entry for the directive. */ static void pass_thru_directive (buf, len, pfile, keyword) const U_CHAR *buf; size_t len; cpp_reader *pfile; int keyword; { const struct directive *kt = &dtable[keyword]; register unsigned klen = kt->length; CPP_RESERVE (pfile, 1 + klen + len); CPP_PUTC_Q (pfile, '#'); CPP_PUTS_Q (pfile, kt->name, klen); if (len != 0 && buf[0] != ' ') CPP_PUTC_Q (pfile, ' '); CPP_PUTS_Q (pfile, buf, len); } /* Process a #define command. */ static int do_define (pfile) cpp_reader *pfile; { HASHNODE *node; int len; U_CHAR *sym; cpp_toklist *list = &pfile->directbuf; pfile->no_macro_expand++; pfile->parsing_define_directive++; CPP_OPTION (pfile, discard_comments)++; _cpp_scan_line (pfile, list); /* First token on the line must be a NAME. There must be at least one token (the VSPACE at the end). */ if (TOK_TYPE (list, 0) != CPP_NAME) { cpp_error_with_line (pfile, list->line, TOK_COL (list, 0), "#define must be followed by an identifier"); goto out; } sym = TOK_NAME (list, 0); len = TOK_LEN (list, 0); /* That NAME is not allowed to be "defined". (Not clear if the standard requires this.) */ if (len == 7 && !ustrncmp (sym, U"defined", 7)) { cpp_error_with_line (pfile, list->line, TOK_COL (list, 0), "\"defined\" is not a legal macro name"); goto out; } node = _cpp_lookup (pfile, sym, len); /* Check for poisoned identifiers now. All other checks are done in cpphash.c. */ if (node->type == T_POISON) { cpp_error (pfile, "redefining poisoned `%.*s'", len, sym); goto out; } if (_cpp_create_definition (pfile, list, node) == 0) goto out; if (CPP_OPTION (pfile, debug_output) || CPP_OPTION (pfile, dump_macros) == dump_definitions) _cpp_dump_definition (pfile, node); else if (CPP_OPTION (pfile, dump_macros) == dump_names) pass_thru_directive (sym, len, pfile, T_DEFINE); out: pfile->no_macro_expand--; pfile->parsing_define_directive--; CPP_OPTION (pfile, discard_comments)--; return 0; } /* Handle #include and #import. */ static unsigned int parse_include (pfile, name) cpp_reader *pfile; const U_CHAR *name; { long old_written = CPP_WRITTEN (pfile); enum cpp_ttype token; int len; pfile->parsing_include_directive++; token = _cpp_get_directive_token (pfile); pfile->parsing_include_directive--; len = CPP_WRITTEN (pfile) - old_written; if (token == CPP_STRING) ; /* No special treatment required. */ #ifdef VMS else if (token == CPP_NAME) { /* Support '#include xyz' like VAX-C. It is taken as '#include ' and generates a warning. */ cpp_warning (pfile, "#%s filename is obsolete, use #%s ", name, name); /* Rewrite the token to . */ CPP_RESERVE (pfile, 4); len += 4; memmove (pfile->token_buffer + old_written + 1, pfile->token_buffer + old_written, CPP_WRITTEN (pfile) - old_written); pfile->token_buffer[old_written] = '<'; CPP_PUTS_Q (pfile, ".h>", 2); } #endif else { cpp_error (pfile, "`#%s' expects \"FILENAME\" or ", name); CPP_SET_WRITTEN (pfile, old_written); _cpp_skip_rest_of_line (pfile); return 0; } if (_cpp_get_directive_token (pfile) != CPP_VSPACE) { cpp_error (pfile, "junk at end of `#%s'", name); _cpp_skip_rest_of_line (pfile); } CPP_SET_WRITTEN (pfile, old_written); if (len == 0) cpp_error (pfile, "empty file name in `#%s'", name); return len; } static int do_include (pfile) cpp_reader *pfile; { unsigned int len; U_CHAR *token; len = parse_include (pfile, dtable[T_INCLUDE].name); if (len == 0) return 0; token = (U_CHAR *) alloca (len + 1); memcpy (token, CPP_PWRITTEN (pfile), len); token[len] = '\0'; if (CPP_OPTION (pfile, dump_includes)) pass_thru_directive (token, len, pfile, T_INCLUDE); _cpp_execute_include (pfile, token, len, 0, 0); return 0; } static int do_import (pfile) cpp_reader *pfile; { unsigned int len; U_CHAR *token; if (CPP_OPTION (pfile, warn_import) && !CPP_BUFFER (pfile)->system_header_p && !pfile->import_warning) { pfile->import_warning = 1; cpp_warning (pfile, "#import is obsolete, use an #ifndef wrapper in the header file"); } len = parse_include (pfile, dtable[T_IMPORT].name); if (len == 0) return 0; token = (U_CHAR *) alloca (len + 1); memcpy (token, CPP_PWRITTEN (pfile), len); token[len] = '\0'; if (CPP_OPTION (pfile, dump_includes)) pass_thru_directive (token, len, pfile, T_IMPORT); _cpp_execute_include (pfile, token, len, 1, 0); return 0; } static int do_include_next (pfile) cpp_reader *pfile; { unsigned int len; U_CHAR *token; struct file_name_list *search_start = 0; len = parse_include (pfile, dtable[T_INCLUDE_NEXT].name); if (len == 0) return 0; token = (U_CHAR *) alloca (len + 1); memcpy (token, CPP_PWRITTEN (pfile), len); token[len] = '\0'; if (CPP_OPTION (pfile, dump_includes)) pass_thru_directive (token, len, pfile, T_INCLUDE_NEXT); /* For #include_next, skip in the search path past the dir in which the containing file was found. Treat files specified using an absolute path as if there are no more directories to search. Treat the primary source file like any other included source, but generate a warning. */ if (CPP_PREV_BUFFER (CPP_BUFFER (pfile))) { if (CPP_BUFFER (pfile)->ihash->foundhere != ABSOLUTE_PATH) search_start = CPP_BUFFER (pfile)->ihash->foundhere->next; } else cpp_warning (pfile, "#include_next in primary source file"); _cpp_execute_include (pfile, token, len, 0, search_start); return 0; } /* Subroutine of do_line. Read next token from PFILE without adding it to the output buffer. If it is a number between 1 and 4, store it in *NUM and return 1; otherwise, return 0 and complain if we aren't at the end of the directive. */ static int read_line_number (pfile, num) cpp_reader *pfile; int *num; { long save_written = CPP_WRITTEN (pfile); U_CHAR *p; enum cpp_ttype token = _cpp_get_directive_token (pfile); p = pfile->token_buffer + save_written; if (token == CPP_NUMBER && p + 1 == CPP_PWRITTEN (pfile) && p[0] >= '1' && p[0] <= '4') { *num = p[0] - '0'; CPP_SET_WRITTEN (pfile, save_written); return 1; } else { if (token != CPP_VSPACE && token != CPP_EOF) cpp_error (pfile, "invalid format `#line' command"); CPP_SET_WRITTEN (pfile, save_written); return 0; } } /* Interpret #line command. Note that the filename string (if any) is treated as if it were an include filename. That means no escape handling. */ static int do_line (pfile) cpp_reader *pfile; { cpp_buffer *ip = CPP_BUFFER (pfile); unsigned int new_lineno; long old_written = CPP_WRITTEN (pfile); enum cpp_ttype token; char *x; token = _cpp_get_directive_token (pfile); if (token != CPP_NUMBER) { cpp_error (pfile, "token after `#line' is not an integer"); goto bad_line_directive; } CPP_PUTC (pfile, '\0'); /* not terminated for us */ new_lineno = strtoul ((const char *) (pfile->token_buffer + old_written), &x, 10); if (x[0] != '\0') { cpp_error (pfile, "token after `#line' is not an integer"); goto bad_line_directive; } CPP_SET_WRITTEN (pfile, old_written); if (CPP_PEDANTIC (pfile) && (new_lineno <= 0 || new_lineno > 32767)) cpp_pedwarn (pfile, "line number out of range in `#line' command"); token = _cpp_get_directive_token (pfile); if (token == CPP_STRING) { U_CHAR *fname = pfile->token_buffer + old_written + 1; U_CHAR *end_name = CPP_PWRITTEN (pfile) - 1; int action_number = 0; if (read_line_number (pfile, &action_number)) { if (CPP_PEDANTIC (pfile)) cpp_pedwarn (pfile, "garbage at end of `#line' command"); /* This is somewhat questionable: change the buffer stack depth so that output_line_command thinks we've stacked another buffer. */ if (action_number == 1) { pfile->buffer_stack_depth++; ip->system_header_p = 0; read_line_number (pfile, &action_number); } else if (action_number == 2) { pfile->buffer_stack_depth--; ip->system_header_p = 0; read_line_number (pfile, &action_number); } if (action_number == 3) { ip->system_header_p = 1; read_line_number (pfile, &action_number); } if (action_number == 4) { ip->system_header_p = 2; read_line_number (pfile, &action_number); } } *end_name = '\0'; if (strcmp ((const char *)fname, ip->nominal_fname)) { if (!strcmp ((const char *)fname, ip->ihash->name)) ip->nominal_fname = ip->ihash->name; else ip->nominal_fname = _cpp_fake_ihash (pfile, (const char *)fname); } } else if (token != CPP_VSPACE && token != CPP_EOF) { cpp_error (pfile, "token after `#line %d' is not a string", new_lineno); goto bad_line_directive; } /* The Newline at the end of this line remains to be processed. To put the next line at the specified line number, we must store a line number now that is one less. */ ip->lineno = new_lineno - 1; CPP_SET_WRITTEN (pfile, old_written); return 0; bad_line_directive: _cpp_skip_rest_of_line (pfile); CPP_SET_WRITTEN (pfile, old_written); return 0; } /* Remove the definition of a symbol from the symbol table. According to the C standard, it is not an error to undef something that has no definitions. */ static int do_undef (pfile) cpp_reader *pfile; { int len; HASHNODE *hp; U_CHAR *name; long here = CPP_WRITTEN (pfile); enum cpp_ttype token; pfile->no_macro_expand++; token = _cpp_get_directive_token (pfile); pfile->no_macro_expand--; if (token != CPP_NAME) { cpp_error (pfile, "token after #undef is not an identifier"); _cpp_skip_rest_of_line (pfile); return 0; } len = CPP_WRITTEN (pfile) - here; token = _cpp_get_directive_token (pfile); if (token != CPP_VSPACE) { cpp_pedwarn (pfile, "junk on line after #undef"); _cpp_skip_rest_of_line (pfile); } name = pfile->token_buffer + here; CPP_SET_WRITTEN (pfile, here); hp = _cpp_lookup (pfile, name, len); if (hp->type == T_VOID) ; /* Not defined in the first place - do nothing. */ else if (hp->type == T_POISON) cpp_error (pfile, "cannot undefine poisoned \"%s\"", hp->name); else { /* If we are generating additional info for debugging (with -g) we need to pass through all effective #undef commands. */ if (CPP_OPTION (pfile, debug_output)) pass_thru_directive (hp->name, len, pfile, T_UNDEF); if (hp->type != T_MACRO && hp->type != T_FMACRO && hp->type != T_EMPTY && hp->type != T_IDENTITY) cpp_warning (pfile, "undefining `%s'", hp->name); _cpp_free_definition (hp); hp->type = T_VOID; } return 0; } /* * Report an error detected by the program we are processing. * Use the text of the line in the error message. * (We use error because it prints the filename & line#.) */ static int do_error (pfile) cpp_reader *pfile; { const U_CHAR *text, *limit; _cpp_skip_hspace (pfile); text = CPP_BUFFER (pfile)->cur; _cpp_skip_rest_of_line (pfile); limit = CPP_BUFFER (pfile)->cur; cpp_error (pfile, "#error %.*s", (int)(limit - text), text); return 0; } /* * Report a warning detected by the program we are processing. * Use the text of the line in the warning message, then continue. */ static int do_warning (pfile) cpp_reader *pfile; { const U_CHAR *text, *limit; _cpp_skip_hspace (pfile); text = CPP_BUFFER (pfile)->cur; _cpp_skip_rest_of_line (pfile); limit = CPP_BUFFER (pfile)->cur; cpp_warning (pfile, "#warning %.*s", (int)(limit - text), text); return 0; } /* Report program identification. */ static int do_ident (pfile) cpp_reader *pfile; { long old_written = CPP_WRITTEN (pfile); CPP_PUTS (pfile, "#ident ", 7); /* Next token should be a string constant. */ if (_cpp_get_directive_token (pfile) == CPP_STRING) /* And then a newline. */ if (_cpp_get_directive_token (pfile) == CPP_VSPACE) /* Good - ship it. */ return 0; cpp_error (pfile, "invalid #ident"); _cpp_skip_rest_of_line (pfile); CPP_SET_WRITTEN (pfile, old_written); /* discard directive */ return 0; } /* Pragmata handling. We handle some of these, and pass the rest on to the front end. C99 defines three pragmas and says that no macro expansion is to be performed on them; whether or not macro expansion happens for other pragmas is implementation defined. This implementation never macro-expands the text after #pragma. We currently do not support the _Pragma operator. Support for that has to be coordinated with the front end. Proposed implementation: both #pragma blah blah and _Pragma("blah blah") become __builtin_pragma(blah blah) and we teach the parser about that. */ /* Sub-handlers for the pragmas needing treatment here. They return 1 if the token buffer is to be popped, 0 if not. */ static int do_pragma_once PARAMS ((cpp_reader *)); static int do_pragma_implementation PARAMS ((cpp_reader *)); static int do_pragma_poison PARAMS ((cpp_reader *)); static int do_pragma_default PARAMS ((cpp_reader *)); static int do_pragma (pfile) cpp_reader *pfile; { long here, key; U_CHAR *buf; int pop; enum cpp_ttype token; here = CPP_WRITTEN (pfile); CPP_PUTS (pfile, "#pragma ", 8); key = CPP_WRITTEN (pfile); pfile->no_macro_expand++; token = _cpp_get_directive_token (pfile); if (token != CPP_NAME) { if (token == CPP_VSPACE) goto empty; else goto skip; } buf = pfile->token_buffer + key; CPP_PUTC (pfile, ' '); #define tokis(x) !strncmp((char *) buf, x, sizeof(x) - 1) if (tokis ("once")) pop = do_pragma_once (pfile); else if (tokis ("implementation")) pop = do_pragma_implementation (pfile); else if (tokis ("poison")) pop = do_pragma_poison (pfile); else pop = do_pragma_default (pfile); #undef tokis if (_cpp_get_directive_token (pfile) != CPP_VSPACE) goto skip; if (pop) CPP_SET_WRITTEN (pfile, here); pfile->no_macro_expand--; return 0; skip: cpp_error (pfile, "malformed #pragma directive"); _cpp_skip_rest_of_line (pfile); empty: CPP_SET_WRITTEN (pfile, here); pfile->no_macro_expand--; return 0; } static int do_pragma_default (pfile) cpp_reader *pfile; { while (_cpp_get_directive_token (pfile) != CPP_VSPACE) CPP_PUTC (pfile, ' '); return 0; } static int do_pragma_once (pfile) cpp_reader *pfile; { cpp_buffer *ip = CPP_BUFFER (pfile); /* Allow #pragma once in system headers, since that's not the user's fault. */ if (!ip->system_header_p) cpp_warning (pfile, "`#pragma once' is obsolete"); if (CPP_PREV_BUFFER (ip) == NULL) cpp_warning (pfile, "`#pragma once' outside include file"); else ip->ihash->control_macro = U""; /* never repeat */ return 1; } static int do_pragma_implementation (pfile) cpp_reader *pfile; { /* Be quiet about `#pragma implementation' for a file only if it hasn't been included yet. */ enum cpp_ttype token; long written = CPP_WRITTEN (pfile); U_CHAR *name; char *copy; size_t len; token = _cpp_get_directive_token (pfile); if (token == CPP_VSPACE) return 0; else if (token != CPP_STRING) { cpp_error (pfile, "malformed #pragma implementation"); return 1; } /* Trim the leading and trailing quote marks from the string. */ name = pfile->token_buffer + written + 1; len = CPP_PWRITTEN (pfile) - name; copy = alloca (len); memcpy (copy, name, len - 1); copy[len - 1] = '\0'; if (cpp_included (pfile, copy)) cpp_warning (pfile, "`#pragma implementation' for `%s' appears after file is included", copy); return 0; } static int do_pragma_poison (pfile) cpp_reader *pfile; { /* Poison these symbols so that all subsequent usage produces an error message. */ U_CHAR *p; HASHNODE *hp; long written; size_t len; enum cpp_ttype token; int writeit; /* As a rule, don't include #pragma poison commands in output, unless the user asks for them. */ writeit = (CPP_OPTION (pfile, debug_output) || CPP_OPTION (pfile, dump_macros) == dump_definitions || CPP_OPTION (pfile, dump_macros) == dump_names); for (;;) { written = CPP_WRITTEN (pfile); token = _cpp_get_directive_token (pfile); if (token == CPP_VSPACE) break; if (token != CPP_NAME) { cpp_error (pfile, "invalid #pragma poison directive"); _cpp_skip_rest_of_line (pfile); return 1; } p = pfile->token_buffer + written; len = CPP_PWRITTEN (pfile) - p; hp = _cpp_lookup (pfile, p, len); if (hp->type == T_POISON) ; /* It is allowed to poison the same identifier twice. */ else { if (hp->type != T_VOID) cpp_warning (pfile, "poisoning existing macro `%s'", hp->name); _cpp_free_definition (hp); hp->type = T_POISON; } if (writeit) CPP_PUTC (pfile, ' '); } return !writeit; } /* Just ignore #sccs, on systems where we define it at all. */ #ifdef SCCS_DIRECTIVE static int do_sccs (pfile) cpp_reader *pfile; { _cpp_skip_rest_of_line (pfile); return 0; } #endif /* We've found an `#if' directive. If the only thing before it in this file is white space, and if it is of the form `#if ! defined SYMBOL', then SYMBOL is a possible controlling macro for inclusion of this file. (See redundant_include_p in cppfiles.c for an explanation of controlling macros.) If so, return a malloced copy of SYMBOL. Otherwise, return NULL. */ static U_CHAR * detect_if_not_defined (pfile) cpp_reader *pfile; { U_CHAR *control_macro = 0; enum cpp_ttype token; unsigned int base_offset; unsigned int token_offset; unsigned int need_rparen = 0; unsigned int token_len; if (pfile->only_seen_white != 2) return NULL; /* Save state required for restore. */ pfile->no_macro_expand++; CPP_SET_MARK (pfile); base_offset = CPP_WRITTEN (pfile); /* Look for `!', */ if (_cpp_get_directive_token (pfile) != CPP_OTHER || CPP_WRITTEN (pfile) != (size_t) base_offset + 1 || CPP_PWRITTEN (pfile)[-1] != '!') goto restore; /* ...then `defined', */ token_offset = CPP_WRITTEN (pfile); token = _cpp_get_directive_token (pfile); if (token != CPP_NAME) goto restore; if (ustrncmp (pfile->token_buffer + token_offset, U"defined", 7)) goto restore; /* ...then an optional '(' and the name, */ token_offset = CPP_WRITTEN (pfile); token = _cpp_get_directive_token (pfile); if (token == CPP_OPEN_PAREN) { token_offset = CPP_WRITTEN (pfile); need_rparen = 1; token = _cpp_get_directive_token (pfile); } if (token != CPP_NAME) goto restore; token_len = CPP_WRITTEN (pfile) - token_offset; /* ...then the ')', if necessary, */ if (need_rparen && _cpp_get_directive_token (pfile) != CPP_CLOSE_PAREN) goto restore; /* ...and make sure there's nothing else on the line. */ if (_cpp_get_directive_token (pfile) != CPP_VSPACE) goto restore; /* We have a legitimate controlling macro for this header. */ control_macro = (U_CHAR *) xmalloc (token_len + 1); memcpy (control_macro, pfile->token_buffer + token_offset, token_len); control_macro[token_len] = '\0'; restore: CPP_SET_WRITTEN (pfile, base_offset); pfile->no_macro_expand--; CPP_GOTO_MARK (pfile); return control_macro; } /* * #if is straightforward; just call _cpp_parse_expr, then conditional_skip. * Also, check for a reinclude preventer of the form #if !defined (MACRO). */ static int do_if (pfile) cpp_reader *pfile; { U_CHAR *control_macro = detect_if_not_defined (pfile); int value = _cpp_parse_expr (pfile); return conditional_skip (pfile, value == 0, T_IF, control_macro); } /* * handle a #elif directive by not changing if_stack either. * see the comment above do_else. */ static int do_elif (pfile) cpp_reader *pfile; { if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack) { cpp_error (pfile, "`#elif' not within a conditional"); return 0; } else { if (pfile->if_stack->type == T_ELSE) { cpp_error (pfile, "`#elif' after `#else'"); cpp_error_with_line (pfile, pfile->if_stack->lineno, 0, "the conditional began here"); } pfile->if_stack->type = T_ELIF; } if (pfile->if_stack->if_succeeded) { _cpp_skip_rest_of_line (pfile); return skip_if_group (pfile); } if (_cpp_parse_expr (pfile) == 0) return skip_if_group (pfile); ++pfile->if_stack->if_succeeded; /* continue processing input */ return 0; } /* Parse an #ifdef or #ifndef directive. Returns 1 for defined, 0 for not defined; the macro tested is left in the token buffer (but popped). */ static int parse_ifdef (pfile, name) cpp_reader *pfile; const U_CHAR *name; { U_CHAR *ident; unsigned int len; enum cpp_ttype token; long old_written = CPP_WRITTEN (pfile); int defined; pfile->no_macro_expand++; token = _cpp_get_directive_token (pfile); pfile->no_macro_expand--; ident = pfile->token_buffer + old_written; len = CPP_WRITTEN (pfile) - old_written; if (token == CPP_VSPACE) { if (! CPP_TRADITIONAL (pfile)) cpp_pedwarn (pfile, "`#%s' with no argument", name); defined = 0; goto done; } else if (token == CPP_NAME) { defined = cpp_defined (pfile, ident, len); CPP_PUTC (pfile, '\0'); /* so it can be copied with xstrdup */ } else { defined = 0; if (! CPP_TRADITIONAL (pfile)) cpp_error (pfile, "`#%s' with invalid argument", name); } if (!CPP_TRADITIONAL (pfile)) { if (_cpp_get_directive_token (pfile) == CPP_VSPACE) goto done; cpp_pedwarn (pfile, "garbage at end of `#%s' argument", name); } _cpp_skip_rest_of_line (pfile); done: CPP_SET_WRITTEN (pfile, old_written); /* Pop */ return defined; } /* #ifdef is dead simple. */ static int do_ifdef (pfile) cpp_reader *pfile; { int skip = ! parse_ifdef (pfile, dtable[T_IFDEF].name); return conditional_skip (pfile, skip, T_IFDEF, 0); } /* #ifndef is a tad more complex, because we need to check for a no-reinclusion wrapper. */ static int do_ifndef (pfile) cpp_reader *pfile; { int start_of_file, skip; U_CHAR *control_macro = 0; start_of_file = pfile->only_seen_white == 2; skip = parse_ifdef (pfile, dtable[T_IFNDEF].name); if (start_of_file && !skip) control_macro = uxstrdup (CPP_PWRITTEN (pfile)); return conditional_skip (pfile, skip, T_IFNDEF, control_macro); } /* Push TYPE on stack; then, if SKIP is nonzero, skip ahead. If this is a #ifndef starting at the beginning of a file, CONTROL_MACRO is the macro name tested by the #ifndef. Otherwise, CONTROL_MACRO is 0. */ static int conditional_skip (pfile, skip, type, control_macro) cpp_reader *pfile; int skip; int type; U_CHAR *control_macro; { IF_STACK *temp; temp = (IF_STACK *) xcalloc (1, sizeof (IF_STACK)); temp->lineno = CPP_BUFFER (pfile)->lineno; temp->next = pfile->if_stack; temp->control_macro = control_macro; pfile->if_stack = temp; pfile->if_stack->type = type; if (skip != 0) return skip_if_group (pfile); ++pfile->if_stack->if_succeeded; return 0; } /* Subroutine of skip_if_group. Examine one preprocessing directive and return 0 if skipping should continue, or the directive number of the directive that ends the block if it should halt. Also adjusts the if_stack as appropriate. The `#' has been read, but not the identifier. */ static int consider_directive_while_skipping (pfile, stack) cpp_reader *pfile; IF_STACK *stack; { long ident; int i, hash_at_bol; unsigned int len; IF_STACK *temp; /* -traditional directives are recognized only with the # in column 1. */ hash_at_bol = CPP_IN_COLUMN_1 (pfile); ident = CPP_WRITTEN (pfile); if (_cpp_get_directive_token (pfile) != CPP_NAME) return 0; len = CPP_WRITTEN (pfile) - ident; for (i = 0; i < N_DIRECTIVES; i++) { if (dtable[i].length == len && !ustrncmp (dtable[i].name, pfile->token_buffer + ident, len)) goto real_directive; } return 0; real_directive: /* If it's not a directive of interest to us, return now. */ if (ORIGIN (dtable[i].flags) != COND) return 0; /* First, deal with -traditional and -Wtraditional. All COND directives are from K+R. */ if (! hash_at_bol) { if (CPP_TRADITIONAL (pfile)) { if (CPP_WTRADITIONAL (pfile)) cpp_warning (pfile, "ignoring #%s because of its indented #", dtable[i].name); return 0; } if (CPP_WTRADITIONAL (pfile)) cpp_warning (pfile, "traditional C ignores %s with the # indented", dtable[i].name); } switch (i) { default: cpp_ice (pfile, "non COND directive in switch in c_d_w_s"); return 0; case T_IF: case T_IFDEF: case T_IFNDEF: temp = (IF_STACK *) xcalloc (1, sizeof (IF_STACK)); temp->lineno = CPP_BUFFER (pfile)->lineno; temp->next = pfile->if_stack; temp->type = i; pfile->if_stack = temp; return 0; case T_ELSE: if (pfile->if_stack != stack) validate_else (pfile, dtable[i].name); /* fall through */ case T_ELIF: if (pfile->if_stack == stack) return i; pfile->if_stack->type = i; return 0; case T_ENDIF: if (pfile->if_stack != stack) validate_else (pfile, dtable[i].name); if (pfile->if_stack == stack) return i; temp = pfile->if_stack; pfile->if_stack = temp->next; free (temp); return 0; } } /* Skip to #endif, #else, or #elif. Consumes the directive that causes it to stop, but not its argument. Returns the number of that directive, which must be passed back up to _cpp_handle_directive, which will execute it. */ static int skip_if_group (pfile) cpp_reader *pfile; { enum cpp_ttype token; IF_STACK *save_if_stack = pfile->if_stack; /* don't pop past here */ long old_written; int ret = 0; /* We are no longer at the start of the file. */ pfile->only_seen_white = 0; old_written = CPP_WRITTEN (pfile); pfile->no_macro_expand++; for (;;) { /* We are at the end of a line. XXX Serious layering violation here. */ int c = CPP_BUF_PEEK (CPP_BUFFER (pfile)); if (c == EOF) break; /* Caller will issue error. */ else if (c != '\n') cpp_ice (pfile, "character %c at end of line in skip_if_group", c); CPP_BUFFER (pfile)->cur++; CPP_BUMP_LINE (pfile); CPP_SET_WRITTEN (pfile, old_written); pfile->only_seen_white = 1; token = _cpp_get_directive_token (pfile); if (token == CPP_DIRECTIVE) { ret = consider_directive_while_skipping (pfile, save_if_stack); if (ret) break; } if (token != CPP_VSPACE) _cpp_skip_rest_of_line (pfile); } CPP_SET_WRITTEN (pfile, old_written); pfile->no_macro_expand--; return ret; } /* * handle a #else directive. Do this by just continuing processing * without changing if_stack ; this is so that the error message * for missing #endif's etc. will point to the original #if. It * is possible that something different would be better. */ static int do_else (pfile) cpp_reader *pfile; { validate_else (pfile, dtable[T_ELSE].name); _cpp_skip_rest_of_line (pfile); if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack) { cpp_error (pfile, "`#else' not within a conditional"); return 0; } else { /* #ifndef can't have its special treatment for containing the whole file if it has a #else clause. */ pfile->if_stack->control_macro = 0; if (pfile->if_stack->type == T_ELSE) { cpp_error (pfile, "`#else' after `#else'"); cpp_error_with_line (pfile, pfile->if_stack->lineno, 0, "the conditional began here"); } pfile->if_stack->type = T_ELSE; } if (pfile->if_stack->if_succeeded) return skip_if_group (pfile); ++pfile->if_stack->if_succeeded; /* continue processing input */ return 0; } /* * unstack after #endif command */ static int do_endif (pfile) cpp_reader *pfile; { validate_else (pfile, dtable[T_ENDIF].name); _cpp_skip_rest_of_line (pfile); if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack) cpp_error (pfile, "`#endif' not within a conditional"); else { IF_STACK *temp = pfile->if_stack; pfile->if_stack = temp->next; if (temp->control_macro != 0) pfile->potential_control_macro = temp->control_macro; free (temp); } return 0; } /* Issue -pedantic warning for text which is not a comment following an #else or #endif. Do not warn in system headers, as this is harmless and very common on old systems. */ static void validate_else (pfile, directive) cpp_reader *pfile; const U_CHAR *directive; { long old_written; if (! CPP_PEDANTIC (pfile)) return; old_written = CPP_WRITTEN (pfile); pfile->no_macro_expand++; if (_cpp_get_directive_token (pfile) != CPP_VSPACE) cpp_pedwarn (pfile, "text following `#%s' violates ANSI standard", directive); CPP_SET_WRITTEN (pfile, old_written); pfile->no_macro_expand--; } /* Called when we reach the end of a macro buffer. Walk back up the conditional stack till we reach its level at entry to this file, issuing error messages. */ void _cpp_unwind_if_stack (pfile, pbuf) cpp_reader *pfile; cpp_buffer *pbuf; { struct if_stack *ifs, *nifs; for (ifs = pfile->if_stack; ifs != pbuf->if_stack; ifs = nifs) { cpp_error_with_line (pfile, ifs->lineno, 0, "unterminated `#%s' conditional", dtable[ifs->type].name); nifs = ifs->next; free (ifs); } pfile->if_stack = ifs; } static int do_assert (pfile) cpp_reader *pfile; { long old_written; U_CHAR *sym; int ret; HASHNODE *base, *this; size_t blen, tlen; old_written = CPP_WRITTEN (pfile); /* remember where it starts */ ret = _cpp_parse_assertion (pfile); if (ret == 0) goto error; else if (ret == 1) { cpp_error (pfile, "missing token-sequence in #assert"); goto error; } tlen = CPP_WRITTEN (pfile) - old_written; if (_cpp_get_directive_token (pfile) != CPP_VSPACE) { cpp_error (pfile, "junk at end of #assert"); goto error; } sym = pfile->token_buffer + old_written; this = _cpp_lookup (pfile, sym, tlen); if (this->type == T_ASSERT) { cpp_warning (pfile, "%s re-asserted", sym); goto error; } blen = ustrchr (sym, '(') - sym; base = _cpp_lookup (pfile, sym, blen); if (base->type == T_VOID) { base->type = T_ASSERT; base->value.aschain = 0; } this->type = T_ASSERT; this->value.aschain = base->value.aschain; base->value.aschain = this; error: _cpp_skip_rest_of_line (pfile); CPP_SET_WRITTEN (pfile, old_written); return 0; } static int do_unassert (pfile) cpp_reader *pfile; { int ret; long old_written; U_CHAR *sym; long baselen, thislen; HASHNODE *base, *this, *next; old_written = CPP_WRITTEN (pfile); ret = _cpp_parse_assertion (pfile); if (ret == 0) goto out; thislen = CPP_WRITTEN (pfile) - old_written; if (_cpp_get_directive_token (pfile) != CPP_VSPACE) { cpp_error (pfile, "junk at end of #unassert"); goto out; } sym = pfile->token_buffer + old_written; CPP_SET_WRITTEN (pfile, old_written); if (ret == 1) { base = _cpp_lookup (pfile, sym, thislen); if (base->type == T_VOID) goto out; /* It isn't an error to #undef what isn't #defined, so it isn't an error to #unassert what isn't #asserted either. */ for (this = base->value.aschain; this; this = next) { next = this->value.aschain; this->value.aschain = NULL; this->type = T_VOID; } base->value.aschain = NULL; base->type = T_VOID; } else { baselen = ustrchr (sym, '(') - sym; base = _cpp_lookup (pfile, sym, baselen); if (base->type == T_VOID) goto out; this = _cpp_lookup (pfile, sym, thislen); if (this->type == T_VOID) goto out; next = base; while (next->value.aschain != this) next = next->value.aschain; next->value.aschain = this->value.aschain; this->value.aschain = NULL; this->type = T_VOID; if (base->value.aschain == NULL) /* Last answer for this predicate deleted. */ base->type = T_VOID; } return 0; out: _cpp_skip_rest_of_line (pfile); CPP_SET_WRITTEN (pfile, old_written); return 0; } /* These are for -D, -U, -A. */ /* Process the string STR as if it appeared as the body of a #define. If STR is just an identifier, define it with value 1. If STR has anything after the identifier, then it should be identifier=definition. */ void cpp_define (pfile, str) cpp_reader *pfile; const char *str; { char *buf, *p; size_t count; p = strchr (str, '='); /* Copy the entire option so we can modify it. Change the first "=" in the string to a space. If there is none, tack " 1" on the end. Then add a newline and a NUL. */ if (p) { count = strlen (str) + 2; buf = (char *) alloca (count); memcpy (buf, str, count - 2); buf[p - str] = ' '; buf[count - 2] = '\n'; buf[count - 1] = '\0'; } else { count = strlen (str) + 4; buf = (char *) alloca (count); memcpy (buf, str, count - 4); strcpy (&buf[count-4], " 1\n"); } if (cpp_push_buffer (pfile, (U_CHAR *)buf, count - 1) != NULL) { do_define (pfile); cpp_pop_buffer (pfile); } } /* Process MACRO as if it appeared as the body of an #undef. */ void cpp_undef (pfile, macro) cpp_reader *pfile; const char *macro; { /* Copy the string so we can append a newline. */ size_t len = strlen (macro); char *buf = (char *) alloca (len + 2); memcpy (buf, macro, len); buf[len] = '\n'; buf[len + 1] = '\0'; if (cpp_push_buffer (pfile, (U_CHAR *)buf, len + 1) != NULL) { do_undef (pfile); cpp_pop_buffer (pfile); } } /* Process the string STR as if it appeared as the body of a #assert. */ void cpp_assert (pfile, str) cpp_reader *pfile; const char *str; { if (cpp_push_buffer (pfile, (const U_CHAR *)str, strlen (str)) != NULL) { do_assert (pfile); cpp_pop_buffer (pfile); } } /* Process STR as if it appeared as the body of an #unassert. */ void cpp_unassert (pfile, str) cpp_reader *pfile; const char *str; { if (cpp_push_buffer (pfile, (const U_CHAR *)str, strlen (str)) != NULL) { do_unassert (pfile); cpp_pop_buffer (pfile); } } /* Determine whether the identifier ID, of length LEN, is a defined macro. */ int cpp_defined (pfile, id, len) cpp_reader *pfile; const U_CHAR *id; int len; { HASHNODE *hp = _cpp_lookup (pfile, id, len); if (hp->type == T_POISON) { cpp_error (pfile, "attempt to use poisoned `%s'", hp->name); return 0; } return (hp->type != T_VOID); }