📄 c-lex.c
字号:
if (c == '\n') return c; /* Something follows the #; read a token. */ ungetc (c, finput); token = yylex (); if (token == CONSTANT && TREE_CODE (yylval.ttype) == INTEGER_CST) { int old_lineno = lineno; int used_up = 0; /* subtract one, because it is the following line that gets the specified number */ int l = TREE_INT_CST_LOW (yylval.ttype) - 1; /* Is this the last nonwhite stuff on the line? */ c = getc (finput); while (c == ' ' || c == '\t') c = getc (finput); if (c == '\n') { /* No more: store the line number and check following line. */ lineno = l; return c; } ungetc (c, finput); /* More follows: it must be a string constant (filename). */ /* Read the string constant. */ token = yylex (); if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST) { error ("invalid #line"); goto skipline; } input_filename = (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1); strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype)); lineno = l; /* Each change of file name reinitializes whether we are now in a system header. */ in_system_header = 0; if (main_input_filename == 0) main_input_filename = input_filename; /* Is this the last nonwhite stuff on the line? */ c = getc (finput); while (c == ' ' || c == '\t') c = getc (finput); if (c == '\n') { /* Update the name in the top element of input_file_stack. */ if (input_file_stack) input_file_stack->name = input_filename; return c; } ungetc (c, finput); token = yylex (); used_up = 0; /* `1' after file name means entering new file. `2' after file name means just left a file. */ if (token == CONSTANT && TREE_CODE (yylval.ttype) == INTEGER_CST) { if (TREE_INT_CST_LOW (yylval.ttype) == 1) { /* Pushing to a new file. */ struct file_stack *p = (struct file_stack *) xmalloc (sizeof (struct file_stack)); input_file_stack->line = old_lineno; p->next = input_file_stack; p->name = input_filename; input_file_stack = p; input_file_stack_tick++;#ifdef DWARF_DEBUGGING_INFO if (debug_info_level == DINFO_LEVEL_VERBOSE && write_symbols == DWARF_DEBUG) dwarfout_start_new_source_file (input_filename);#endif /* DWARF_DEBUGGING_INFO */ used_up = 1; } else if (TREE_INT_CST_LOW (yylval.ttype) == 2) { /* Popping out of a file. */ if (input_file_stack->next) { struct file_stack *p = input_file_stack; input_file_stack = p->next; free (p); input_file_stack_tick++;#ifdef DWARF_DEBUGGING_INFO if (debug_info_level == DINFO_LEVEL_VERBOSE && write_symbols == DWARF_DEBUG) dwarfout_resume_previous_source_file (input_file_stack->line);#endif /* DWARF_DEBUGGING_INFO */ } else error ("#-lines for entering and leaving files don't match"); used_up = 1; } } /* Now that we've pushed or popped the input stack, update the name in the top element. */ if (input_file_stack) input_file_stack->name = input_filename; /* If we have handled a `1' or a `2', see if there is another number to read. */ if (used_up) { /* Is this the last nonwhite stuff on the line? */ c = getc (finput); while (c == ' ' || c == '\t') c = getc (finput); if (c == '\n') return c; ungetc (c, finput); token = yylex (); used_up = 0; } /* `3' after file name means this is a system header file. */ if (token == CONSTANT && TREE_CODE (yylval.ttype) == INTEGER_CST && TREE_INT_CST_LOW (yylval.ttype) == 3) in_system_header = 1, used_up = 1; if (used_up) { /* Is this the last nonwhite stuff on the line? */ c = getc (finput); while (c == ' ' || c == '\t') c = getc (finput); if (c == '\n') return c; ungetc (c, finput); } warning ("unrecognized text at end of #line"); } else error ("invalid #-line"); /* skip the rest of this line. */ skipline: if (c == '\n') return c; while ((c = getc (finput)) != EOF && c != '\n'); return c;}#ifdef HANDLE_SYSV_PRAGMA/* Handle a #pragma directive. INPUT is the current input stream, and C is a character to reread. Processes the entire input line and returns a character for the caller to reread: either \n or EOF. *//* This function has to be in this file, in order to get at the token types. */inthandle_sysv_pragma (input, c) FILE *input; int c;{ for (;;) { while (c == ' ' || c == '\t') c = getc (input); if (c == '\n' || c == EOF) { handle_pragma_token (0, 0); return c; } ungetc (c, input); switch (yylex ()) { case IDENTIFIER: case TYPENAME: case STRING: case CONSTANT: handle_pragma_token (token_buffer, yylval.ttype); break; default: handle_pragma_token (token_buffer, 0); } if (nextchar >= 0) c = nextchar, nextchar = -1; else c = getc (input); }}#endif /* HANDLE_SYSV_PRAGMA */#define ENDFILE -1 /* token that represents end-of-file *//* Read an escape sequence, returning its equivalent as a character, or store 1 in *ignore_ptr if it is backslash-newline. */static intreadescape (ignore_ptr) int *ignore_ptr;{ register int c = getc (finput); register int code; register unsigned count; unsigned firstdig = 0; int nonnull; switch (c) { case 'x': if (warn_traditional) warning ("the meaning of `\\x' varies with -traditional"); if (flag_traditional) return c; code = 0; count = 0; nonnull = 0; while (1) { c = getc (finput); if (!(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F') && !(c >= '0' && c <= '9')) { ungetc (c, finput); break; } code *= 16; if (c >= 'a' && c <= 'f') code += c - 'a' + 10; if (c >= 'A' && c <= 'F') code += c - 'A' + 10; if (c >= '0' && c <= '9') code += c - '0'; if (code != 0 || count != 0) { if (count == 0) firstdig = code; count++; } nonnull = 1; } if (! nonnull) error ("\\x used with no following hex digits"); else if (count == 0) /* Digits are all 0's. Ok. */ ; else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node) || (count > 1 && ((1 << (TYPE_PRECISION (integer_type_node) - (count - 1) * 4)) <= firstdig))) pedwarn ("hex escape out of range"); return code; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': code = 0; count = 0; while ((c <= '7') && (c >= '0') && (count++ < 3)) { code = (code * 8) + (c - '0'); c = getc (finput); } ungetc (c, finput); return code; case '\\': case '\'': case '"': return c; case '\n': lineno++; *ignore_ptr = 1; return 0; case 'n': return TARGET_NEWLINE; case 't': return TARGET_TAB; case 'r': return TARGET_CR; case 'f': return TARGET_FF; case 'b': return TARGET_BS; case 'a': if (warn_traditional) warning ("the meaning of `\\a' varies with -traditional"); if (flag_traditional) return c; return TARGET_BELL; case 'v':#if 0 /* Vertical tab is present in common usage compilers. */ if (flag_traditional) return c;#endif return TARGET_VT; case 'e': case 'E': if (pedantic) pedwarn ("non-ANSI-standard escape sequence, `\\%c'", c); return 033; case '?': return c; /* `\(', etc, are used at beginning of line to avoid confusing Emacs. */ case '(': case '{': case '[': /* `\%' is used to prevent SCCS from getting confused. */ case '%': if (pedantic) pedwarn ("non-ANSI escape sequence `\\%c'", c); return c; } if (c >= 040 && c < 0177) pedwarn ("unknown escape sequence `\\%c'", c); else pedwarn ("unknown escape sequence: `\\' followed by char code 0x%x", c); return c;}voidyyerror (string) char *string;{ char buf[200]; strcpy (buf, string); /* We can't print string and character constants well because the token_buffer contains the result of processing escapes. */ if (end_of_file) strcat (buf, " at end of input"); else if (token_buffer[0] == 0) strcat (buf, " at null character"); else if (token_buffer[0] == '"') strcat (buf, " before string constant"); else if (token_buffer[0] == '\'') strcat (buf, " before character constant"); else if (token_buffer[0] < 040 || (unsigned char) token_buffer[0] >= 0177) sprintf (buf + strlen (buf), " before character 0%o", (unsigned char) token_buffer[0]); else strcat (buf, " before `%s'"); error (buf, token_buffer);}#if 0struct try_type{ tree *node_var; char unsigned_flag; char long_flag; char long_long_flag;};struct try_type type_sequence[] = { { &integer_type_node, 0, 0, 0}, { &unsigned_type_node, 1, 0, 0}, { &long_integer_type_node, 0, 1, 0}, { &long_unsigned_type_node, 1, 1, 0}, { &long_long_integer_type_node, 0, 1, 1}, { &long_long_unsigned_type_node, 1, 1, 1}};#endif /* 0 */intyylex (){ register int c; register char *p; register int value; int wide_flag = 0; int objc_flag = 0; if (nextchar >= 0) c = nextchar, nextchar = -1; else c = getc (finput); /* Effectively do c = skip_white_space (c) but do it faster in the usual cases. */ while (1) switch (c) { case ' ': case '\t': case '\f': case '\v': case '\b': c = getc (finput); break; case '\r': /* Call skip_white_space so we can warn if appropriate. */ case '\n': case '/': case '\\': c = skip_white_space (c); default: goto found_nonwhite; } found_nonwhite: token_buffer[0] = c; token_buffer[1] = 0;/* yylloc.first_line = lineno; */ switch (c) { case EOF: end_of_file = 1; token_buffer[0] = 0; value = ENDFILE; break; case '$': if (dollars_in_ident) goto letter; return '$'; case 'L': /* Capital L may start a wide-string or wide-character constant. */ { register int c = getc (finput); if (c == '\'') { wide_flag = 1; goto char_constant; } if (c == '"') { wide_flag = 1; goto string_constant; } ungetc (c, finput); } goto letter; case '@': if (!doing_objc_thang) { value = c; break; } else { /* '@' may start a constant string object. */ register int c = getc(finput); if (c == '"') { objc_flag = 1; goto string_constant; } ungetc(c, finput); /* Fall through to treat '@' as the start of an identifier. */ } case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -