📄 c-lex.c
字号:
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; 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; } p = token_buffer; *p++ = '@'; c = getc (finput); while (isalnum (c) || c == '_') { if (p >= token_buffer + maxtoken) p = extend_token_buffer (p); *p++ = c; c = getc (finput); } *p = 0; nextchar = c; value = recognize_objc_keyword (token_buffer + 1); if (value != 0) break; error ("invalid Objective C keyword `%s'", token_buffer); /* Cause a syntax error--1 is not a valid token type. */ value = 1; break; 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': case '_': letter: p = token_buffer; while (isalnum (c) || c == '_' || c == '$' || c == '@') { if (p >= token_buffer + maxtoken) p = extend_token_buffer (p); if (c == '$' && ! dollars_in_ident) break; *p++ = c; c = getc (finput); } *p = 0; nextchar = c; value = IDENTIFIER; yylval.itype = 0; /* Try to recognize a keyword. Uses minimum-perfect hash function */ { register struct resword *ptr; if (ptr = is_reserved_word (token_buffer, p - token_buffer)) { if (ptr->rid) yylval.ttype = ridpointers[(int) ptr->rid]; value = (int) ptr->token; /* Even if we decided to recognize asm, still perhaps warn. */ if (pedantic && (value == ASM_KEYWORD || value == TYPEOF || ptr->rid == RID_INLINE) && token_buffer[0] != '_') pedwarn ("ANSI does not permit the keyword `%s'", token_buffer); } } /* If we did not find a keyword, look for an identifier (or a typename). */ if (value == IDENTIFIER) { yylval.ttype = get_identifier (token_buffer); lastiddecl = lookup_name (yylval.ttype); if (lastiddecl != 0 && TREE_CODE (lastiddecl) == TYPE_DECL) value = TYPENAME; /* A user-invisible read-only initialized variable should be replaced by its value. We handle only strings since that's the only case used in C. */ else if (lastiddecl != 0 && TREE_CODE (lastiddecl) == VAR_DECL && DECL_IGNORED_P (lastiddecl) && TREE_READONLY (lastiddecl) && DECL_INITIAL (lastiddecl) != 0 && TREE_CODE (DECL_INITIAL (lastiddecl)) == STRING_CST) { yylval.ttype = DECL_INITIAL (lastiddecl); value = STRING; } else if (doing_objc_thang) { tree objc_interface_decl = lookup_interface (yylval.ttype); if (objc_interface_decl) { value = CLASSNAME; yylval.ttype = objc_interface_decl; } } } break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '.': { int base = 10; int count = 0; int largest_digit = 0; int numdigits = 0; /* for multi-precision arithmetic, we actually store only HOST_BITS_PER_CHAR bits in each part. The number of parts is chosen so as to be sufficient to hold the enough bits to fit into the two HOST_WIDE_INTs that contain the integer value (this is always at least as many bits as are in a target `long long' value, but may be wider). */#define TOTAL_PARTS ((HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR) * 2 + 2) int parts[TOTAL_PARTS]; int overflow = 0; enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS} floatflag = NOT_FLOAT; for (count = 0; count < TOTAL_PARTS; count++) parts[count] = 0; p = token_buffer; *p++ = c; if (c == '0') { *p++ = (c = getc (finput)); if ((c == 'x') || (c == 'X')) { base = 16; *p++ = (c = getc (finput)); } /* Leading 0 forces octal unless the 0 is the only digit. */ else if (c >= '0' && c <= '9') { base = 8; numdigits++; } else numdigits++; } /* Read all the digits-and-decimal-points. */ while (c == '.' || (isalnum (c) && (c != 'l') && (c != 'L') && (c != 'u') && (c != 'U') && (floatflag == NOT_FLOAT || ((c != 'f') && (c != 'F'))))) { if (c == '.') { if (base == 16) error ("floating constant may not be in radix 16"); if (floatflag == AFTER_POINT) { error ("malformed floating constant"); floatflag = TOO_MANY_POINTS; } else floatflag = AFTER_POINT; base = 10; *p++ = c = getc (finput); /* Accept '.' as the start of a floating-point number only when it is followed by a digit. Otherwise, unread the following non-digit and use the '.' as a structural token. */ if (p == token_buffer + 2 && !isdigit (c)) { if (c == '.') { c = getc (finput); if (c == '.') { *p++ = c; *p = 0; return ELLIPSIS; } error ("parse error at `..'"); } ungetc (c, finput); token_buffer[1] = 0; value = '.'; goto done; } } else { /* It is not a decimal point. It should be a digit (perhaps a hex digit). */ if (isdigit (c)) { c = c - '0'; } else if (base <= 10) { if ((c&~040) == 'E') { base = 10; floatflag = AFTER_POINT; break; /* start of exponent */ } error ("nondigits in number and not hexadecimal"); c = 0; } else if (c >= 'a') { c = c - 'a' + 10; } else { c = c - 'A' + 10; } if (c >= largest_digit) largest_digit = c; numdigits++; for (count = 0; count < TOTAL_PARTS; count++) { parts[count] *= base; if (count) { parts[count] += (parts[count-1] >> HOST_BITS_PER_CHAR); parts[count-1] &= (1 << HOST_BITS_PER_CHAR) - 1; } else parts[0] += c; } /* If the extra highest-order part ever gets anything in it, the number is certainly too big. */ if (parts[TOTAL_PARTS - 1] != 0) overflow = 1; if (p >= token_buffer + maxtoken - 3) p = extend_token_buffer (p); *p++ = (c = getc (finput)); } } if (numdigits == 0) error ("numeric constant with no digits"); if (largest_digit >= base) error ("numeric constant contains digits beyond the radix"); /* Remove terminating char from the token buffer and delimit the string */ *--p = 0; if (floatflag != NOT_FLOAT) { tree type = double_type_node; int garbage_chars = 0, exceeds_double = 0; REAL_VALUE_TYPE value; jmp_buf handler; /* Read explicit exponent if any, and put it in tokenbuf. */ if ((c == 'e') || (c == 'E')) { if (p >= token_buffer + maxtoken - 3) p = extend_token_buffer (p); *p++ = c; c = getc (finput); if ((c == '+') || (c == '-')) { *p++ = c; c = getc (finput); } if (! isdigit (c)) error ("floating constant exponent has no digits"); while (isdigit (c)) { if (p >= token_buffer + maxtoken - 3) p = extend_token_buffer (p); *p++ = c; c = getc (finput); } } *p = 0; errno = 0; /* Convert string to a double, checking for overflow. */ if (setjmp (handler)) { error ("floating constant out of range"); value = dconst0; } else { set_float_handler (handler); value = REAL_VALUE_ATOF (token_buffer); set_float_handler (NULL_PTR); }#ifdef ERANGE if (errno == ERANGE && !flag_traditional && pedantic) { /* ERANGE is also reported for underflow, so test the value to distinguish overflow from that. */ if (REAL_VALUES_LESS (dconst1, value) || REAL_VALUES_LESS (value, dconstm1)) { pedwarn ("floating point number exceeds range of `double'"); exceeds_double = 1; } }#endif /* Read the suffixes to choose a data type. */ switch (c) { case 'f': case 'F': type = float_type_node; value = REAL_VALUE_TRUNCATE (TYPE_MODE (type), value); if (REAL_VALUE_ISINF (value) && ! exceeds_double && pedantic) pedwarn ("floating point number exceeds range of `float'"); garbage_chars = -1; break; case 'l': case 'L': type = long_double_type_node; garbage_chars = -1; break; } /* Note: garbage_chars is -1 if first char is *not* garbage. */ while (isalnum (c)) { if (p >= token_buffer + maxtoken - 3) p = extend_token_buffer (p); *p++ = c; c = getc (finput); garbage_chars++; } if (garbage_chars > 0) error ("garbage at end of number"); /* Create a node with determined type and value. */ yylval.ttype = build_real (type, value); ungetc (c, finput); *p = 0; } else { tree traditional_type, ansi_type, type; HOST_WIDE_INT high, low; int spec_unsigned = 0; int spec_long = 0; int spec_long_long = 0; int bytes, warn, i; while (1) { if (c == 'u' || c == 'U') { if (spec_unsigned) error ("two `u's in integer constant"); spec_unsigned = 1; } else if (c == 'l' || c == 'L') { if (spec_long) { if (spec_long_long) error ("three `l's in integer constant"); else if (pedantic) pedwarn ("ANSI C forbids long long integer constants"); spec_long_long = 1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -