X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fada-lex.l;h=1e4bc20f77cbb2187acac642374880548071cdb7;hb=b4991d292edd84c16bd2050bd071198ceae764fe;hp=a52f5054274701e62e21db77392b9a6f15b5732c;hpb=9a76efb656a6acbc22e23976770e79e7a111893b;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/ada-lex.l b/gdb/ada-lex.l index a52f505427..1e4bc20f77 100644 --- a/gdb/ada-lex.l +++ b/gdb/ada-lex.l @@ -1,23 +1,20 @@ /* FLEX lexer for Ada expressions, for GDB. - Copyright (C) 1994, 1997, 1998, 2000, 2001, 2002, 2003, 2007 - Free Software Foundation, Inc. + Copyright (C) 1994-2020 Free Software Foundation, Inc. -This file is part of GDB. + This file is part of GDB. -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 of the License, or -(at your option) any later version. + 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 3 of the License, 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. + 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, Inc., 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ /*----------------------------------------------------------------------*/ @@ -44,6 +41,14 @@ POSEXP (e"+"?{NUM10}) %{ +#include "diagnostics.h" + +/* Some old versions of flex generate code that uses the "register" keyword, + which clang warns about. This was observed for example with flex 2.5.35, + as shipped with macOS 10.12. */ +DIAGNOSTIC_PUSH +DIAGNOSTIC_IGNORE_DEPRECATED_REGISTER + #define NUMERAL_WIDTH 256 #define LONGEST_SIGN ((ULONGEST) 1 << (sizeof(LONGEST) * HOST_CHAR_BIT - 1)) @@ -51,31 +56,40 @@ POSEXP (e"+"?{NUM10}) static char numbuf[NUMERAL_WIDTH]; static void canonicalizeNumeral (char *s1, const char *); static struct stoken processString (const char*, int); -static int processInt (const char *, const char *, const char *); -static int processReal (const char *); +static int processInt (struct parser_state *, const char *, const char *, + const char *); +static int processReal (struct parser_state *, const char *); static struct stoken processId (const char *, int); static int processAttribute (const char *); static int find_dot_all (const char *); +static void rewind_to_char (int); #undef YY_DECL #define YY_DECL static int yylex ( void ) +/* Flex generates a static function "input" which is not used. + Defining YY_NO_INPUT comments it out. */ +#define YY_NO_INPUT + #undef YY_INPUT #define YY_INPUT(BUF, RESULT, MAX_SIZE) \ - if ( *lexptr == '\000' ) \ + if ( *pstate->lexptr == '\000' ) \ (RESULT) = YY_NULL; \ else \ { \ - *(BUF) = *lexptr; \ + *(BUF) = *pstate->lexptr; \ (RESULT) = 1; \ - lexptr += 1; \ + pstate->lexptr += 1; \ } static int find_dot_all (const char *); +/* Depth of parentheses. */ +static int paren_depth; + %} -%option case-insensitive interactive nodefault +%option case-insensitive interactive nodefault noyywrap %s BEFORE_QUAL_QUOTE @@ -87,40 +101,42 @@ static int find_dot_all (const char *); {NUM10}{POSEXP} { canonicalizeNumeral (numbuf, yytext); - return processInt (NULL, numbuf, strrchr(numbuf, 'e')+1); + return processInt (pstate, NULL, numbuf, + strrchr (numbuf, 'e') + 1); } {NUM10} { canonicalizeNumeral (numbuf, yytext); - return processInt (NULL, numbuf, NULL); + return processInt (pstate, NULL, numbuf, NULL); } {NUM10}"#"{HEXDIG}({HEXDIG}|_)*"#"{POSEXP} { canonicalizeNumeral (numbuf, yytext); - return processInt (numbuf, + return processInt (pstate, numbuf, strchr (numbuf, '#') + 1, strrchr(numbuf, '#') + 1); } {NUM10}"#"{HEXDIG}({HEXDIG}|_)*"#" { canonicalizeNumeral (numbuf, yytext); - return processInt (numbuf, strchr (numbuf, '#') + 1, NULL); + return processInt (pstate, numbuf, strchr (numbuf, '#') + 1, + NULL); } "0x"{HEXDIG}+ { canonicalizeNumeral (numbuf, yytext+2); - return processInt ("16#", numbuf, NULL); + return processInt (pstate, "16#", numbuf, NULL); } {NUM10}"."{NUM10}{EXP} { canonicalizeNumeral (numbuf, yytext); - return processReal (numbuf); + return processReal (pstate, numbuf); } {NUM10}"."{NUM10} { canonicalizeNumeral (numbuf, yytext); - return processReal (numbuf); + return processReal (pstate, numbuf); } {NUM10}"#"{NUM16}"."{NUM16}"#"{EXP} { @@ -132,14 +148,14 @@ static int find_dot_all (const char *); } "'"({GRAPHIC}|\")"'" { - yylval.typed_val.type = type_char (); + yylval.typed_val.type = type_char (pstate); yylval.typed_val.val = yytext[1]; return CHARLIT; } "'[\""{HEXDIG}{2}"\"]'" { int v; - yylval.typed_val.type = type_char (); + yylval.typed_val.type = type_char (pstate); sscanf (yytext+3, "%2x", &v); yylval.typed_val.val = v; return CHARLIT; @@ -156,9 +172,19 @@ static int find_dot_all (const char *); if { - while (*lexptr != 'i' && *lexptr != 'I') - lexptr -= 1; - yyrestart(NULL); + rewind_to_char ('i'); + return 0; + } + +task { + rewind_to_char ('t'); + return 0; + } + +thread{WHITE}+{DIG} { + /* This keyword signals the end of the expression and + will be processed separately. */ + rewind_to_char ('t'); return 0; } @@ -178,9 +204,19 @@ rem { return REM; } then { return THEN; } xor { return XOR; } + /* BOOLEAN "KEYWORDS" */ + + /* True and False are not keywords in Ada, but rather enumeration constants. + However, the boolean type is no longer represented as an enum, so True + and False are no longer defined in symbol tables. We compromise by + making them keywords (when bare). */ + +true { return TRUEKEYWORD; } +false { return FALSEKEYWORD; } + /* ATTRIBUTES */ -{TICK}[a-zA-Z][a-zA-Z]+ { return processAttribute (yytext+1); } +{TICK}[a-zA-Z][a-zA-Z_]+ { BEGIN INITIAL; return processAttribute (yytext+1); } /* PUNCTUATION */ @@ -196,10 +232,9 @@ xor { return XOR; } [-&*+./:<>=|;\[\]] { return yytext[0]; } -"," { if (paren_depth == 0 && comma_terminates) +"," { if (paren_depth == 0 && pstate->comma_terminates) { - lexptr -= 1; - yyrestart(NULL); + rewind_to_char (','); return 0; } else @@ -209,8 +244,7 @@ xor { return XOR; } "(" { paren_depth += 1; return '('; } ")" { if (paren_depth == 0) { - lexptr -= 1; - yyrestart(NULL); + rewind_to_char (')'); return 0; } else @@ -259,7 +293,7 @@ xor { return XOR; } "$"({LETTER}|{DIG}|"$")* { yylval.sval.ptr = yytext; yylval.sval.length = yyleng; - return SPECIAL_VARIABLE; + return DOLLAR_VARIABLE; } /* CATCH-ALL ERROR CASE */ @@ -268,14 +302,13 @@ xor { return XOR; } %% #include -#include "gdb_string.h" - /* Initialize the lexer for processing new expression. */ -void +static void lexer_init (FILE *inp) { BEGIN INITIAL; + paren_depth = 0; yyrestart (inp); } @@ -304,13 +337,13 @@ canonicalizeNumeral (char *s1, const char *s2) */ static int -processInt (const char *base0, const char *num0, const char *exp0) +processInt (struct parser_state *par_state, const char *base0, + const char *num0, const char *exp0) { ULONGEST result; long exp; int base; - - char *trailer; + const char *trailer; if (base0 == NULL) base = 10; @@ -327,7 +360,7 @@ processInt (const char *base0, const char *num0, const char *exp0) exp = strtol(exp0, (char **) NULL, 10); errno = 0; - result = strtoulst (num0, (const char **) &trailer, base); + result = strtoulst (num0, &trailer, base); if (errno == ERANGE) error (_("Integer literal out of range")); if (isxdigit(*trailer)) @@ -341,11 +374,11 @@ processInt (const char *base0, const char *num0, const char *exp0) exp -= 1; } - if ((result >> (gdbarch_int_bit (current_gdbarch)-1)) == 0) - yylval.typed_val.type = type_int (); - else if ((result >> (gdbarch_long_bit (current_gdbarch)-1)) == 0) - yylval.typed_val.type = type_long (); - else if (((result >> (gdbarch_long_bit (current_gdbarch)-1)) >> 1) == 0) + if ((result >> (gdbarch_int_bit (par_state->gdbarch ())-1)) == 0) + yylval.typed_val.type = type_int (par_state); + else if ((result >> (gdbarch_long_bit (par_state->gdbarch ())-1)) == 0) + yylval.typed_val.type = type_long (par_state); + else if (((result >> (gdbarch_long_bit (par_state->gdbarch ())-1)) >> 1) == 0) { /* We have a number representable as an unsigned integer quantity. For consistency with the C treatment, we will treat it as an @@ -354,7 +387,8 @@ processInt (const char *base0, const char *num0, const char *exp0) for the mess, but C doesn't officially guarantee that a simple assignment does the trick (no, it doesn't; read the reference manual). */ - yylval.typed_val.type = builtin_type_unsigned_long; + yylval.typed_val.type + = builtin_type (par_state->gdbarch ())->builtin_unsigned_long; if (result & LONGEST_SIGN) yylval.typed_val.val = (LONGEST) (result & ~LONGEST_SIGN) @@ -364,35 +398,34 @@ processInt (const char *base0, const char *num0, const char *exp0) return INT; } else - yylval.typed_val.type = type_long_long (); + yylval.typed_val.type = type_long_long (par_state); yylval.typed_val.val = (LONGEST) result; return INT; } static int -processReal (const char *num0) +processReal (struct parser_state *par_state, const char *num0) { - sscanf (num0, DOUBLEST_SCAN_FORMAT, &yylval.typed_val_float.dval); - - yylval.typed_val_float.type = type_float (); - if (sizeof(DOUBLEST) >= TARGET_DOUBLE_BIT / TARGET_CHAR_BIT) - yylval.typed_val_float.type = type_double (); - if (sizeof(DOUBLEST) >= TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT) - yylval.typed_val_float.type = type_long_double (); + yylval.typed_val_float.type = type_long_double (par_state); + bool parsed = parse_float (num0, strlen (num0), + yylval.typed_val_float.type, + yylval.typed_val_float.val); + gdb_assert (parsed); return FLOAT; } /* Store a canonicalized version of NAME0[0..LEN-1] in yylval.ssym. The - resulting string is valid until the next call to ada_parse. It differs + resulting string is valid until the next call to ada_parse. If + NAME0 contains the substring "___", it is assumed to be already + encoded and the resulting name is equal to it. Similarly, if the name + starts with '<', it is copied verbatim. Otherwise, it differs from NAME0 in that: - + Characters between '...' or <...> are transfered verbatim to - yylval.ssym. - + <, >, and trailing "'" characters in quoted sequences are removed - (a leading quote is preserved to indicate that the name is not to be - GNAT-encoded). + + Characters between '...' are transfered verbatim to yylval.ssym. + + Trailing "'" characters in quoted sequences are removed (a leading quote is + preserved to indicate that the name is not to be GNAT-encoded). + Unquoted whitespace is removed. + Unquoted alphabetic characters are mapped to lower case. Result is returned as a struct stoken, but for convenience, the string @@ -402,12 +435,22 @@ processReal (const char *num0) static struct stoken processId (const char *name0, int len) { - char *name = obstack_alloc (&temp_parse_space, len + 11); + char *name = (char *) obstack_alloc (&temp_parse_space, len + 11); int i0, i; struct stoken result; + result.ptr = name; while (len > 0 && isspace (name0[len-1])) len -= 1; + + if (name0[0] == '<' || strstr (name0, "___") != NULL) + { + strncpy (name, name0, len); + name[len] = '\000'; + result.length = len; + return result; + } + i = i0 = 0; while (i0 < len) { @@ -434,20 +477,10 @@ processId (const char *name0, int len) while (i0 < len && name0[i0] != '\''); i0 += 1; break; - case '<': - i0 += 1; - while (i0 < len && name0[i0] != '>') - { - name[i] = name0[i0]; - i += 1; i0 += 1; - } - i0 += 1; - break; } } name[i] = '\000'; - result.ptr = name; result.length = i; return result; } @@ -464,7 +497,8 @@ processString (const char *text, int len) const char *lim = text + len; struct stoken result; - q = result.ptr = obstack_alloc (&temp_parse_space, len); + q = (char *) obstack_alloc (&temp_parse_space, len); + result.ptr = q; p = text; while (p < lim) { @@ -503,19 +537,20 @@ static int find_dot_all (const char *str) { int i; - for (i = 0; str[i] != '\000'; i += 1) - { - if (str[i] == '.') - { - int i0 = i; - do - i += 1; - while (isspace (str[i])); - if (strncmp (str+i, "all", 3) == 0 - && ! isalnum (str[i+3]) && str[i+3] != '_') - return i0; - } - } + + for (i = 0; str[i] != '\000'; i++) + if (str[i] == '.') + { + int i0 = i; + + do + i += 1; + while (isspace (str[i])); + + if (strncasecmp (str + i, "all", 3) == 0 + && !isalnum (str[i + 3]) && str[i + 3] != '_') + return i0; + } return -1; } @@ -582,10 +617,21 @@ processAttribute (const char *str) return attributes[k].code; } -int -yywrap(void) +/* Back up lexptr by yyleng and then to the rightmost occurrence of + character CH, case-folded (there must be one). WARNING: since + lexptr points to the next input character that Flex has not yet + transferred to its internal buffer, the use of this function + depends on the assumption that Flex calls YY_INPUT only when it is + logically necessary to do so (thus, there is no reading ahead + farther than needed to identify the next token.) */ + +static void +rewind_to_char (int ch) { - return 1; + pstate->lexptr -= yyleng; + while (toupper (*pstate->lexptr) != toupper (ch)) + pstate->lexptr -= 1; + yyrestart (NULL); } /* Dummy definition to suppress warnings about unused static definitions. */ @@ -594,3 +640,5 @@ dummy_function ada_flex_use[] = { (dummy_function) yyunput }; + +DIAGNOSTIC_POP