📄 cccp.c
字号:
/* Nonzero means don't print warning messages. -w. */static int inhibit_warnings = 0;/* Nonzero means warn if slash-star appears in a slash-star comment, or if newline-backslash appears in a slash-slash comment. */static int warn_comments;/* Nonzero means warn if a macro argument is (or would be) stringified with -traditional. */static int warn_stringify;/* Nonzero means warn if there are any trigraphs. */static int warn_trigraphs;/* Nonzero means warn if undefined identifiers are evaluated in an #if. */int warn_undef;/* Nonzero means warn if #import is used. */static int warn_import = 1;/* Nonzero means turn warnings into errors. */static int warnings_are_errors;/* Nonzero means try to imitate old fashioned non-ANSI preprocessor. */int traditional;/* Nonzero for the 1989 C Standard, including corrigenda and amendments. */int c89;/* Nonzero causes output not to be done, but directives such as #define that have side effects are still obeyed. */static int no_output;/* Nonzero means this file was included with a -imacros or -include command line and should not be recorded as an include file. */static int no_record_file;/* Nonzero means that we have finished processing the command line options. This flag is used to decide whether or not to issue certain errors and/or warnings. */static int done_initializing = 0;/* Line where a newline was first seen in a string constant. */static int multiline_string_line = 0;/* I/O buffer structure. The `fname' field is nonzero for source files and #include files and for the dummy text used for -D and -U. It is zero for rescanning results of macro expansion and for expanding macro arguments. */#define INPUT_STACK_MAX 400static struct file_buf { char *fname; /* Filename specified with #line directive. */ char *nominal_fname; /* omni: Filename of #included file */ char *include_fname; /* Include file description. */ struct include_file *inc; /* Record where in the search path this file was found. For #include_next. */ struct file_name_list *dir; int lineno; int length; U_CHAR *buf; U_CHAR *bufp; /* Macro that this level is the expansion of. Included so that we can reenable the macro at the end of this level. */ struct hashnode *macro; /* Value of if_stack at start of this file. Used to prohibit unmatched #endif (etc) in an include file. */ struct if_stack *if_stack; /* Object to be freed at end of input at this level. */ U_CHAR *free_ptr; /* True if this is a header file included using <FILENAME>. */ char system_header_p;} instack[INPUT_STACK_MAX];static int last_error_tick; /* Incremented each time we print it. */static int input_file_stack_tick; /* Incremented when the status changes. *//* Current nesting level of input sources. `instack[indepth]' is the level currently being read. */static int indepth = -1;#define CHECK_DEPTH(code) \ if (indepth >= (INPUT_STACK_MAX - 1)) \ { \ error_with_line (line_for_error (instack[indepth].lineno), \ "macro or `#include' recursion too deep"); \ code; \ }/* Current depth in #include directives that use <...>. */static int system_include_depth = 0;typedef struct file_buf FILE_BUF;/* The output buffer. Its LENGTH field is the amount of room allocated for the buffer, not the number of chars actually present. To get that, subtract outbuf.buf from outbuf.bufp. */#define OUTBUF_SIZE 10 /* initial size of output buffer */static FILE_BUF outbuf;/* Grow output buffer OBUF points at so it can hold at least NEEDED more chars. */#define check_expand(OBUF, NEEDED) \ (((OBUF)->length - ((OBUF)->bufp - (OBUF)->buf) <= (NEEDED)) \ ? grow_outbuf ((OBUF), (NEEDED)) : 0)struct file_name_list { struct file_name_list *next; /* If the following is 1, it is a C-language system include directory. */ int c_system_include_path; /* Mapping of file names for this directory. */ struct file_name_map *name_map; /* Non-zero if name_map is valid. */ int got_name_map; /* The include directory status. */ struct stat st; /* The include prefix: "" denotes the working directory, otherwise fname must end in '/'. The actual size is dynamically allocated. */ char fname[1]; };/* #include "file" looks in source file dir, then stack. *//* #include <file> just looks in the stack. *//* -I directories are added to the end, then the defaults are added. *//* The */static struct default_include { char *fname; /* The name of the directory. */ int cplusplus; /* Only look here if we're compiling C++. */ int cxx_aware; /* Includes in this directory don't need to be wrapped in extern "C" when compiling C++. */} include_defaults_array[]#ifdef INCLUDE_DEFAULTS = INCLUDE_DEFAULTS;#else = { /* Pick up GNU C++ specific include files. */ { GPLUSPLUS_INCLUDE_DIR, 1, 1 }, { OLD_GPLUSPLUS_INCLUDE_DIR, 1, 1 },#ifdef CROSS_COMPILE /* This is the dir for fixincludes. Put it just before the files that we fix. */ { GCC_INCLUDE_DIR, 0, 0 }, /* For cross-compilation, this dir name is generated automatically in Makefile.in. */ { CROSS_INCLUDE_DIR, 0, 0 },#ifdef TOOL_INCLUDE_DIR /* This is another place that the target system's headers might be. */ { TOOL_INCLUDE_DIR, 0, 0 },#endif#else /* not CROSS_COMPILE */#ifdef LOCAL_INCLUDE_DIR /* This should be /usr/local/include and should come before the fixincludes-fixed header files. */ { LOCAL_INCLUDE_DIR, 0, 1 },#endif#ifdef TOOL_INCLUDE_DIR /* This is here ahead of GCC_INCLUDE_DIR because assert.h goes here. Likewise, behind LOCAL_INCLUDE_DIR, where glibc puts its assert.h. */ { TOOL_INCLUDE_DIR, 0, 0 },#endif /* This is the dir for fixincludes. Put it just before the files that we fix. */ { GCC_INCLUDE_DIR, 0, 0 }, /* Some systems have an extra dir of include files. */#ifdef SYSTEM_INCLUDE_DIR { SYSTEM_INCLUDE_DIR, 0, 0 },#endif { STANDARD_INCLUDE_DIR, 0, 0 },#endif /* not CROSS_COMPILE */ { 0, 0, 0 } };#endif /* no INCLUDE_DEFAULTS *//* The code looks at the defaults through this pointer, rather than through the constant structure above. This pointer gets changed if an environment variable specifies other defaults. */static struct default_include *include_defaults = include_defaults_array;static struct file_name_list *include = 0; /* First dir to search */ /* First dir to search for <file> *//* This is the first element to use for #include <...>. If it is 0, use the entire chain for such includes. */static struct file_name_list *first_bracket_include = 0;/* This is the first element in the chain that corresponds to a directory of system header files. */static struct file_name_list *first_system_include = 0;static struct file_name_list *last_include = 0; /* Last in chain *//* Chain of include directories to put at the end of the other chain. */static struct file_name_list *after_include = 0;static struct file_name_list *last_after_include = 0; /* Last in chain *//* Chain to put at the start of the system include files. */static struct file_name_list *before_system = 0;static struct file_name_list *last_before_system = 0; /* Last in chain *//* Directory prefix that should replace `/usr' in the standard include file directories. */static char *include_prefix;/* Maintain and search list of included files. */struct include_file { struct include_file *next; /* for include_hashtab */ struct include_file *next_ino; /* for include_ino_hashtab */ char *fname; /* omni: original #included name */ char *include_fname; /* If the following is the empty string, it means #pragma once was seen in this include file, or #import was applied to the file. Otherwise, if it is nonzero, it is a macro name. Don't include the file again if that macro is defined. */ U_CHAR *control_macro; /* Nonzero if the dependency on this include file has been output. */ int deps_output; struct stat st;};/* Hash tables of files already included with #include or #import. include_hashtab is by full name; include_ino_hashtab is by inode number. */#define INCLUDE_HASHSIZE 61static struct include_file *include_hashtab[INCLUDE_HASHSIZE];static struct include_file *include_ino_hashtab[INCLUDE_HASHSIZE];/* Global list of strings read in from precompiled files. This list is kept in the order the strings are read in, with new strings being added at the end through stringlist_tailp. We use this list to output the strings at the end of the run. */static STRINGDEF *stringlist;static STRINGDEF **stringlist_tailp = &stringlist;/* Structure returned by create_definition */typedef struct macrodef MACRODEF;struct macrodef{ struct definition *defn; U_CHAR *symnam; int symlen;};enum sharp_token_type { NO_SHARP_TOKEN = 0, /* token not present */ SHARP_TOKEN = '#', /* token spelled with # only */ WHITE_SHARP_TOKEN, /* token spelled with # and white space */ PERCENT_COLON_TOKEN = '%', /* token spelled with %: only */ WHITE_PERCENT_COLON_TOKEN /* token spelled with %: and white space */};/* Structure allocated for every #define. For a simple replacement such as #define foo bar , nargs = -1, the `pattern' list is null, and the expansion is just the replacement text. Nargs = 0 means a functionlike macro with no args, e.g., #define getchar() getc (stdin) . When there are args, the expansion is the replacement text with the args squashed out, and the reflist is a list describing how to build the output from the input: e.g., "3 chars, then the 1st arg, then 9 chars, then the 3rd arg, then 0 chars, then the 2nd arg". The chars here come from the expansion. Whatever is left of the expansion after the last arg-occurrence is copied after that arg. Note that the reflist can be arbitrarily long--- its length depends on the number of times the arguments appear in the replacement text, not how many args there are. Example: #define f(x) x+x+x+x+x+x+x would have replacement text "++++++" and pattern list { (0, 1), (1, 1), (1, 1), ..., (1, 1), NULL } where (x, y) means (nchars, argno). */typedef struct definition DEFINITION;struct definition { int nargs; int length; /* length of expansion string */ int predefined; /* True if the macro was builtin or */ /* came from the command line */ U_CHAR *expansion; int line; /* Line number of definition */ char *file; /* File of definition */ char rest_args; /* Nonzero if last arg. absorbs the rest */ struct reflist { struct reflist *next; enum sharp_token_type stringify; /* set if a # operator before arg */ enum sharp_token_type raw_before; /* set if a ## operator before arg */ enum sharp_token_type raw_after; /* set if a ## operator after arg */ char rest_args; /* Nonzero if this arg. absorbs the rest */ int nchars; /* Number of literal chars to copy before this arg occurrence. */ int argno; /* Number of arg to substitute (origin-0) */ } *pattern; union { /* Names of macro args, concatenated in reverse order with comma-space between them. The only use of this is that we warn on redefinition if this differs between the old and new definitions. */ U_CHAR *argnames; } args;};/* different kinds of things that can appear in the value field of a hash node. Actually, this may be useless now. */union hashval { char *cpval; DEFINITION *defn; KEYDEF *keydef;};/* * special extension string that can be added to the last macro argument to * allow it to absorb the "rest" of the arguments when expanded. Ex: * #define wow(a, b...) process (b, a, b) * { wow (1, 2, 3); } -> { process (2, 3, 1, 2, 3); } * { wow (one, two); } -> { process (two, one, two); } * if this "rest_arg" is used with the concat token '##' and if it is not * supplied then the token attached to with ## will not be outputted. Ex: * #define wow (a, b...) process (b ## , a, ## b) * { wow (1, 2); } -> { process (2, 1, 2); } * { wow (one); } -> { process (one); { */static char rest_extension[] = "...";#define REST_EXTENSION_LENGTH (sizeof (rest_extension) - 1)/* The structure of a node in the hash table. The hash table has entries for all tokens defined by #define directives (type T_MACRO), plus some special tokens like __LINE__ (these each have their own type, and the appropriate code is run when that type of node is seen. It does not contain control words like "#define", which are recognized by a separate piece of code. *//* different flavors of hash nodes --- also used in keyword table */enum node_type { T_DEFINE = 1, /* the `#define' keyword */ T_INCLUDE, /* the `#include' keyword */ T_INCLUDE_NEXT, /* the `#include_next' keyword */ T_IMPORT, /* the `#import' keyword */ T_IFDEF, /* the `#ifdef' keyword */ T_IFNDEF, /* the `#ifndef' keyword */ T_IF, /* the `#if' keyword */ T_ELSE, /* `#else' */ T_PRAGMA, /* `#pragma' */ T_ELIF, /* `#elif' */ T_UNDEF, /* `#undef' */ T_LINE, /* `#line' */ T_ERROR, /* `#error' */ T_WARNING, /* `#warning' */ T_ENDIF, /* `#endif' */ T_SCCS, /* `#sccs', used on system V. */ T_IDENT, /* `#ident', used on system V. */ T_ASSERT, /* `#assert', taken from system V. */ T_UNASSERT, /* `#unassert', taken from system V. */ T_SPECLINE, /* special symbol `__LINE__' */ T_DATE, /* `__DATE__' */ T_FILE, /* `__FILE__' */ T_BASE_FILE, /* `__BASE_FILE__' */ T_INCLUDE_LEVEL, /* `__INCLUDE_LEVEL__' */ T_VERSION, /* `__VERSION__' */ T_SIZE_TYPE, /* `__SIZE_TYPE__' */ T_PTRDIFF_TYPE, /* `__PTRDIFF_TYPE__' */ T_WCHAR_TYPE, /* `__WCHAR_TYPE__' */ T_USER_LABEL_PREFIX_TYPE, /* `__USER_LABEL_PREFIX__' */ T_REGISTER_PREFIX_TYPE, /* `__REGISTER_PREFIX__' */ T_IMMEDIATE_PREFIX_TYPE, /* `__IMMEDIATE_PREFIX__' */ T_TIME, /* `__TIME__' */ T_CONST, /* Constant value, used by `__STDC__' */ T_MACRO, /* macro defined by `#define' */ T_DISABLED, /* macro temporarily turned off for rescan */ T_SPEC_DEFINED, /* special `defined' macro for use in #if statements */ T_PCSTRING, /* precompiled string (hashval is KEYDEF *) */ T_UNUSED /* Used for something not defined. */ };struct hashnode { struct hashnode *next; /* double links for easy deletion */ struct hashnode *prev; struct hashnode **bucket_hdr; /* also, a back pointer to this node's hash chain is kept, in case the node is the head of the chain and gets deleted. */ enum node_type type; /* type of special token */ int length; /* length of token, for quick comparison */ U_CHAR *name; /* the actual name */ union hashval value; /* pointer to expansion, or whatever */};typedef struct hashnode HASHNODE;/* Some definitions for the hash table. The hash function MUST be computed as shown in hashf () below. That is because the rescan loop computes the hash value `on the fly' for most tokens, in order to avoid the overhead of a lot of procedure calls to the hashf () function. Hashf () only exists for the sake of politeness, for use when speed isn't so important. */#define HASHSIZE 1403static HASHNODE *hashtab[HASHSIZE];#define HASHSTEP(old, c) ((old << 2) + c)#define MAKE_POS(v) (v & 0x7fffffff) /* make number positive *//* Symbols to predefine. */#ifdef CPP_PREDEFINESstatic char *predefs = CPP_PREDEFINES;#elsestatic char *predefs = "";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -