📄 lex.c
字号:
error ("invalid digit in control sequence"); cc = 0; } c = (c * base) + cc; count++; } } else c ^= 64; } storeit: tmp[i++] = c; if (i == allocated) { allocated += 1024; tmp = xrealloc (tmp, allocated); } } done: tmp [*len = i] = '\0'; return tmp;unterminated: if (c == '\n') unput ('\n'); *len = 1; if (pass == 1) error ("unterminated string literal"); to_global_binding_level (); tmp[0] = '\0'; return tmp;}/* Convert an integer INTCHARS into an INTEGER_CST. INTCHARS is on the temporary_obstack, and is popped by this function. */static treeconvert_integer (intchars) char *intchars;{#ifdef YYDEBUG extern int yydebug;#endif char *p = intchars; char *oldp = p; int base = 10, tmp; int valid_chars = 0; int overflow = 0; tree type; HOST_WIDE_INT val_lo = 0, val_hi = 0; tree val; /* determine the base */ switch (*p) { case 'd': case 'D': p += 2; break; case 'o': case 'O': p += 2; base = 8; break; case 'h': case 'H': p += 2; base = 16; break; case 'b': case 'B': p += 2; base = 2; break; default: if (!ISDIGIT (*p)) /* this test is for equal_number () */ { obstack_free (&temporary_obstack, intchars); return 0; } break; } while (*p) { tmp = *p++; if ((tmp == '\'') || (tmp == '_')) continue; if (tmp < '0') goto bad_char; if (tmp >= 'a') /* uppercase the char */ tmp -= ' '; switch (base) /* validate the characters */ { case 2: if (tmp > '1') goto bad_char; break; case 8: if (tmp > '7') goto bad_char; break; case 10: if (tmp > '9') goto bad_char; break; case 16: if (tmp > 'F') goto bad_char; if (tmp > '9' && tmp < 'A') goto bad_char; break; default: abort (); } tmp -= '0'; if (tmp > 9) tmp -= 7; if (mul_double (val_lo, val_hi, base, 0, &val_lo, &val_hi)) overflow++; add_double (val_lo, val_hi, tmp, 0, &val_lo, &val_hi); if (val_hi < 0) overflow++; valid_chars++; } bad_char: obstack_free (&temporary_obstack, intchars); if (!valid_chars) { if (pass == 2) error ("invalid number format `%s'", oldp); return 0; } val = build_int_2 (val_lo, val_hi); /* We set the type to long long (or long long unsigned) so that constant fold of literals is less likely to overflow. */ if (int_fits_type_p (val, long_long_integer_type_node)) type = long_long_integer_type_node; else { if (! int_fits_type_p (val, long_long_unsigned_type_node)) overflow++; type = long_long_unsigned_type_node; } TREE_TYPE (val) = type; CH_DERIVED_FLAG (val) = 1; if (overflow) error ("integer literal too big"); return val;}/* Convert a bitstring literal on the temporary_obstack to a bitstring CONSTRUCTOR. Free the literal from the obstack. */static treeconvert_bitstring (p) char *p;{#ifdef YYDEBUG extern int yydebug;#endif int bl = 0, valid_chars = 0, bits_per_char = 0, c, k; tree initlist = NULL_TREE; tree val; /* Move p to stack so we can re-use temporary_obstack for result. */ char *oldp = (char*) alloca (strlen (p) + 1); if (oldp == 0) fatal ("stack space exhausted"); strcpy (oldp, p); obstack_free (&temporary_obstack, p); p = oldp; switch (*p) { case 'h': case 'H': bits_per_char = 4; break; case 'o': case 'O': bits_per_char = 3; break; case 'b': case 'B': bits_per_char = 1; break; } p += 2; while (*p) { c = *p++; if (c == '_' || c == '\'') continue; if (c >= 'a') c -= ' '; c -= '0'; if (c > 9) c -= 7; valid_chars++; for (k = BYTES_BIG_ENDIAN ? bits_per_char - 1 : 0; BYTES_BIG_ENDIAN ? k >= 0 : k < bits_per_char; bl++, BYTES_BIG_ENDIAN ? k-- : k++) { if (c & (1 << k)) initlist = tree_cons (NULL_TREE, build_int_2 (bl, 0), initlist); } }#if 0 /* as long as BOOLS(0) is valid it must tbe possible to specify an empty bitstring */ if (!valid_chars) { if (pass == 2) error ("invalid number format `%s'", oldp); return 0; }#endif val = build (CONSTRUCTOR, build_bitstring_type (size_int (bl)), NULL_TREE, nreverse (initlist)); TREE_CONSTANT (val) = 1; CH_DERIVED_FLAG (val) = 1; return val;}/* Check if two filenames name the same file. This is done by stat'ing both files and comparing their inodes. Note: we have to take care of seize_path_list. Therefore do it the same way as in yywrap. FIXME: This probably can be done better. */static intsame_file (filename1, filename2) char *filename1; char *filename2;{ struct stat s[2]; char *fn_input[2]; int i, stat_status; if (grant_only_flag) /* do nothing in this case */ return 0; /* if filenames are equal -- return 1, cause there is no need to search in the include list in this case */ if (strcmp (filename1, filename2) == 0) return 1; fn_input[0] = filename1; fn_input[1] = filename2; for (i = 0; i < 2; i++) { stat_status = stat (fn_input[i], &s[i]); if (stat_status < 0 && strchr (fn_input[i], '/') == 0) { STRING_LIST *plp; char *path; for (plp = seize_path_list; plp != 0; plp = plp->next) { path = (char *)xmalloc (strlen (fn_input[i]) + strlen (plp->str) + 2); sprintf (path, "%s/%s", plp->str, fn_input[i]); stat_status = stat (path, &s[i]); free (path); if (stat_status >= 0) break; } } if (stat_status < 0) pfatal_with_name (fn_input[i]); } return s[0].st_ino == s[1].st_ino && s[0].st_dev == s[1].st_dev;}/* * Note that simply appending included file names to a list in this * way completely eliminates the need for nested files, and the * associated book-keeping, since the EOF processing in the lexer * will simply process the files one at a time, in the order that the * USE_SEIZE_FILE directives were scanned. */static voidhandle_use_seizefile_directive (restricted) int restricted;{ tree seen; int len; int c = skip_whitespace (); char *use_seizefile_str = readstring (c, &len); if (pass > 1) return; if (c != '\'' && c != '\"') { error ("USE_SEIZE_FILE directive must be followed by string"); return; } use_seizefile_name = get_identifier (use_seizefile_str); CH_USE_SEIZEFILE_RESTRICTED (use_seizefile_name) = restricted; if (!grant_only_flag) { /* If file foo.ch contains a <> use_seize_file "bar.grt" <>, and file bar.ch contains a <> use_seize_file "foo.grt" <>, then if we're compiling foo.ch, we will indirectly be asked to seize foo.grt. Don't. */ extern char *grant_file_name; if (strcmp (use_seizefile_str, grant_file_name) == 0) return; /* Check if the file is already on the list. */ for (seen = files_to_seize; seen != NULL_TREE; seen = TREE_CHAIN (seen)) if (same_file (IDENTIFIER_POINTER (TREE_VALUE (seen)), use_seizefile_str)) return; /* Previously seen; nothing to do. */ } /* Haven't been asked to seize this file yet, so add its name to the list. */ { tree pl = perm_tree_cons (0, use_seizefile_name, NULL_TREE); if (files_to_seize == NULL_TREE) files_to_seize = pl; else TREE_CHAIN (last_file_to_seize) = pl; if (next_file_to_seize == NULL_TREE) next_file_to_seize = pl; last_file_to_seize = pl; }}/* * get input, convert to lower case for comparison */intgetlc (file) FILE *file;{ register int c; c = getc (file); if (ISUPPER (c) && ignore_case) c = tolower (c); return c;}#if defined HANDLE_PRAGMA/* Local versions of these macros, that can be passed as function pointers. */static intpragma_getc (){ return getc (finput);}static voidpragma_ungetc (arg) int arg;{ ungetc (arg, finput);}#endif /* HANDLE_PRAGMA */#ifdef HANDLE_GENERIC_PRAGMAS/* Handle a generic #pragma directive. BUFFER contains the text we read after `#pragma'. Processes the entire input line and return non-zero iff the pragma was successfully processed. */static inthandle_generic_pragma (buffer) char * buffer;{ register int c; for (;;) { char * buff; handle_pragma_token (buffer, NULL); c = getc (finput); while (c == ' ' || c == '\t') c = getc (finput); ungetc (c, finput); if (c == '\n' || c == EOF) return handle_pragma_token (NULL, NULL); /* Read the next word of the pragma into the buffer. */ buff = buffer; do { * buff ++ = c; c = getc (finput); } while (c != EOF && isascii (c) && ! isspace (c) && c != '\n' && buff < buffer + 128); /* XXX shared knowledge about size of buffer. */ ungetc (c, finput); * -- buff = 0; }}#endif /* HANDLE_GENERIC_PRAGMAS *//* At the beginning of a line, increment the line number and process any #-directive on this line. If the line is a #-directive, read the entire line and return a newline. Otherwise, return the line's first non-whitespace character. (Each language front end has a check_newline() function that is called from lang_init() for that language. One of the things this function must do is read the first line of the input file, and if it is a #line directive, extract the filename from it and use it to initialize main_input_filename. Proper generation of debugging information in the normal "front end calls cpp then calls cc1XXXX environment" depends upon this being done.) */intcheck_newline (){ register int c; lineno++; /* Read first nonwhite char on the line. */ c = getc (finput); while (c == ' ' || c == '\t') c = getc (finput); if (c != '#' || inside_c_comment) { /* If not #, return it so caller will use it. */ return c; } /* Read first nonwhite char after the `#'. */ c = getc (finput); while (c == ' ' || c == '\t') c = getc (finput); /* If a letter follows, then if the word here is `line', skip it and ignore it; otherwise, ignore the line, with an error if the word isn't `pragma', `ident', `define', or `undef'. */ if (ISUPPER (c) && ignore_case) c = tolower (c); if (c >= 'a' && c <= 'z') { if (c == 'p') { if (getlc (finput) == 'r' && getlc (finput) == 'a' && getlc (finput) == 'g' && getlc (finput) == 'm' && getlc (finput) == 'a' && (c = getlc (finput), ISSPACE (c))) {#ifdef HANDLE_PRAGMA static char buffer [128]; char * buff = buffer; /* Read the pragma name into a buffer. */ while (c = getlc (finput), ISSPACE (c)) continue; do { * buff ++ = c; c = getlc (finput); } while (c != EOF && ! ISSPACE (c) && c != '\n' && buff < buffer + 128); pragma_ungetc (c); * -- buff = 0; if (HANDLE_PRAGMA (pragma_getc, pragma_ungetc, buffer)) goto skipline;#endif /* HANDLE_PRAGMA */ #ifdef HANDLE_GENERIC_PRAGMAS if (handle_generic_pragma (buffer)) goto skipline;#endif /* HANDLE_GENERIC_PRAGMAS */ goto skipline; } } else if (c == 'd') { if (getlc (finput) == 'e' && getlc (finput) == 'f' && getlc (finput) == 'i' && getlc (finput) == 'n' && getlc (finput) == 'e' && (c = getlc (finput), ISSPACE (c))) {#if 0 /*def DWARF_DEBUGGING_INFO*/ if (c != '\n' && (debug_info_level == DINFO_LEVEL_VERBOSE) && (write_symbols == DWARF_DEBUG)) dwarfout_define (lineno, get_directive_line (finput));#endif /* DWARF_DEBUGGING_INFO */ goto skipline; } } else if (c == 'u') { if (getlc (finput) == 'n' && getlc (finput) == 'd' && getlc (finput) == 'e' && getlc (finput) == 'f' && (c = getlc (finput), ISSPACE (c))) {#if 0 /*def DWARF_DEBUGGING_INFO*/ if (c != '\n' && (debug_info_level == DINFO_LEVEL_VERBOSE) && (write_symbols == DWARF_DEBUG)) dwarfout_undef (lineno, get_directive_line (finput));#endif /* DWARF_DEBUGGING_INFO */ goto skipline; } } else if (c == 'l') { if (getlc (finput) == 'i' && getlc (finput) == 'n' && getlc (finput) == 'e' && ((c = getlc (finput)) == ' ' || c == '\t')) goto linenum; }#if 0 else if (c == 'i') { if (getlc (finput) == 'd' && getlc (finput) == 'e' && getlc (finput) == 'n' && getlc (finput) == 't' && ((c = getlc (finput)) == ' ' || c == '\t'))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -