gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / ada-lex.l
CommitLineData
14f9c5c9 1/* FLEX lexer for Ada expressions, for GDB.
b811d2c2 2 Copyright (C) 1994-2020 Free Software Foundation, Inc.
14f9c5c9 3
5b1ba0e5
NS
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>. */
14f9c5c9
AS
18
19/*----------------------------------------------------------------------*/
20
21/* The converted version of this file is to be included in ada-exp.y, */
22/* the Ada parser for gdb. The function yylex obtains characters from */
23/* the global pointer lexptr. It returns a syntactic category for */
24/* each successive token and places a semantic value into yylval */
25/* (ada-lval), defined by the parser. */
26
14f9c5c9
AS
27DIG [0-9]
28NUM10 ({DIG}({DIG}|_)*)
29HEXDIG [0-9a-f]
30NUM16 ({HEXDIG}({HEXDIG}|_)*)
31OCTDIG [0-7]
32LETTER [a-z_]
33ID ({LETTER}({LETTER}|{DIG})*|"<"{LETTER}({LETTER}|{DIG})*">")
34WHITE [ \t\n]
35TICK ("'"{WHITE}*)
36GRAPHIC [a-z0-9 #&'()*+,-./:;<>=_|!$%?@\[\]\\^`{}~]
37OPER ([-+*/=<>&]|"<="|">="|"**"|"/="|"and"|"or"|"xor"|"not"|"mod"|"rem"|"abs")
38
39EXP (e[+-]{NUM10})
40POSEXP (e"+"?{NUM10})
41
42%{
4c4b4cd2 43
e9cb46ab 44#include "diagnostics.h"
d1435379
SM
45
46/* Some old versions of flex generate code that uses the "register" keyword,
47 which clang warns about. This was observed for example with flex 2.5.35,
48 as shipped with macOS 10.12. */
49DIAGNOSTIC_PUSH
50DIAGNOSTIC_IGNORE_DEPRECATED_REGISTER
51
14f9c5c9
AS
52#define NUMERAL_WIDTH 256
53#define LONGEST_SIGN ((ULONGEST) 1 << (sizeof(LONGEST) * HOST_CHAR_BIT - 1))
54
4c4b4cd2
PH
55/* Temporary staging for numeric literals. */
56static char numbuf[NUMERAL_WIDTH];
57 static void canonicalizeNumeral (char *s1, const char *);
52ce6436 58static struct stoken processString (const char*, int);
410a0ff2
SDJ
59static int processInt (struct parser_state *, const char *, const char *,
60 const char *);
61static int processReal (struct parser_state *, const char *);
52ce6436 62static struct stoken processId (const char *, int);
4c4b4cd2
PH
63static int processAttribute (const char *);
64static int find_dot_all (const char *);
82d049ab 65static void rewind_to_char (int);
14f9c5c9
AS
66
67#undef YY_DECL
4c4b4cd2 68#define YY_DECL static int yylex ( void )
14f9c5c9 69
0ec6cd0c
JB
70/* Flex generates a static function "input" which is not used.
71 Defining YY_NO_INPUT comments it out. */
72#define YY_NO_INPUT
73
14f9c5c9
AS
74#undef YY_INPUT
75#define YY_INPUT(BUF, RESULT, MAX_SIZE) \
5776fca3 76 if ( *pstate->lexptr == '\000' ) \
14f9c5c9
AS
77 (RESULT) = YY_NULL; \
78 else \
79 { \
5776fca3 80 *(BUF) = *pstate->lexptr; \
14f9c5c9 81 (RESULT) = 1; \
5776fca3 82 pstate->lexptr += 1; \
14f9c5c9
AS
83 }
84
4c4b4cd2 85static int find_dot_all (const char *);
14f9c5c9 86
28aaf3fd
TT
87/* Depth of parentheses. */
88static int paren_depth;
89
14f9c5c9
AS
90%}
91
fcd60b84 92%option case-insensitive interactive nodefault noyywrap
7dc1ef8d 93
52ce6436 94%s BEFORE_QUAL_QUOTE
14f9c5c9
AS
95
96%%
97
98{WHITE} { }
99
100"--".* { yyterminate(); }
101
4c4b4cd2
PH
102{NUM10}{POSEXP} {
103 canonicalizeNumeral (numbuf, yytext);
410a0ff2
SDJ
104 return processInt (pstate, NULL, numbuf,
105 strrchr (numbuf, 'e') + 1);
14f9c5c9
AS
106 }
107
4c4b4cd2
PH
108{NUM10} {
109 canonicalizeNumeral (numbuf, yytext);
410a0ff2 110 return processInt (pstate, NULL, numbuf, NULL);
14f9c5c9
AS
111 }
112
113{NUM10}"#"{HEXDIG}({HEXDIG}|_)*"#"{POSEXP} {
114 canonicalizeNumeral (numbuf, yytext);
410a0ff2 115 return processInt (pstate, numbuf,
4c4b4cd2 116 strchr (numbuf, '#') + 1,
14f9c5c9
AS
117 strrchr(numbuf, '#') + 1);
118 }
119
120{NUM10}"#"{HEXDIG}({HEXDIG}|_)*"#" {
121 canonicalizeNumeral (numbuf, yytext);
410a0ff2
SDJ
122 return processInt (pstate, numbuf, strchr (numbuf, '#') + 1,
123 NULL);
14f9c5c9
AS
124 }
125
126"0x"{HEXDIG}+ {
127 canonicalizeNumeral (numbuf, yytext+2);
410a0ff2 128 return processInt (pstate, "16#", numbuf, NULL);
14f9c5c9
AS
129 }
130
131
132{NUM10}"."{NUM10}{EXP} {
4c4b4cd2 133 canonicalizeNumeral (numbuf, yytext);
410a0ff2 134 return processReal (pstate, numbuf);
14f9c5c9
AS
135 }
136
137{NUM10}"."{NUM10} {
4c4b4cd2 138 canonicalizeNumeral (numbuf, yytext);
410a0ff2 139 return processReal (pstate, numbuf);
14f9c5c9
AS
140 }
141
142{NUM10}"#"{NUM16}"."{NUM16}"#"{EXP} {
e1d5a0d2 143 error (_("Based real literals not implemented yet."));
14f9c5c9
AS
144 }
145
146{NUM10}"#"{NUM16}"."{NUM16}"#" {
e1d5a0d2 147 error (_("Based real literals not implemented yet."));
14f9c5c9
AS
148 }
149
150<INITIAL>"'"({GRAPHIC}|\")"'" {
410a0ff2 151 yylval.typed_val.type = type_char (pstate);
14f9c5c9
AS
152 yylval.typed_val.val = yytext[1];
153 return CHARLIT;
154 }
155
156<INITIAL>"'[\""{HEXDIG}{2}"\"]'" {
157 int v;
410a0ff2 158 yylval.typed_val.type = type_char (pstate);
14f9c5c9
AS
159 sscanf (yytext+3, "%2x", &v);
160 yylval.typed_val.val = v;
161 return CHARLIT;
162 }
163
52ce6436
PH
164\"({GRAPHIC}|"[\""({HEXDIG}{2}|\")"\"]")*\" {
165 yylval.sval = processString (yytext+1, yyleng-2);
14f9c5c9
AS
166 return STRING;
167 }
168
52ce6436 169\" {
e1d5a0d2 170 error (_("ill-formed or non-terminated string literal"));
14f9c5c9
AS
171 }
172
14f9c5c9 173
4c4b4cd2 174if {
82d049ab 175 rewind_to_char ('i');
14f9c5c9
AS
176 return 0;
177 }
178
82d049ab
PH
179task {
180 rewind_to_char ('t');
181 return 0;
182 }
183
184thread{WHITE}+{DIG} {
b9ee2233
JB
185 /* This keyword signals the end of the expression and
186 will be processed separately. */
82d049ab 187 rewind_to_char ('t');
70575d34
JB
188 return 0;
189 }
190
14f9c5c9
AS
191 /* ADA KEYWORDS */
192
193abs { return ABS; }
194and { return _AND_; }
195else { return ELSE; }
196in { return IN; }
197mod { return MOD; }
198new { return NEW; }
199not { return NOT; }
200null { return NULL_PTR; }
201or { return OR; }
52ce6436 202others { return OTHERS; }
14f9c5c9
AS
203rem { return REM; }
204then { return THEN; }
205xor { return XOR; }
206
690cc4eb
PH
207 /* BOOLEAN "KEYWORDS" */
208
209 /* True and False are not keywords in Ada, but rather enumeration constants.
210 However, the boolean type is no longer represented as an enum, so True
211 and False are no longer defined in symbol tables. We compromise by
212 making them keywords (when bare). */
213
214true { return TRUEKEYWORD; }
215false { return FALSEKEYWORD; }
216
14f9c5c9
AS
217 /* ATTRIBUTES */
218
4268ec18 219{TICK}[a-zA-Z][a-zA-Z_]+ { BEGIN INITIAL; return processAttribute (yytext+1); }
14f9c5c9
AS
220
221 /* PUNCTUATION */
222
223"=>" { return ARROW; }
224".." { return DOTDOT; }
225"**" { return STARSTAR; }
226":=" { return ASSIGN; }
227"/=" { return NOTEQUAL; }
228"<=" { return LEQ; }
229">=" { return GEQ; }
230
231<BEFORE_QUAL_QUOTE>"'" { BEGIN INITIAL; return '\''; }
232
233[-&*+./:<>=|;\[\]] { return yytext[0]; }
234
8621b685 235"," { if (paren_depth == 0 && pstate->comma_terminates)
14f9c5c9 236 {
82d049ab 237 rewind_to_char (',');
14f9c5c9
AS
238 return 0;
239 }
4c4b4cd2 240 else
14f9c5c9
AS
241 return ',';
242 }
243
244"(" { paren_depth += 1; return '('; }
4c4b4cd2 245")" { if (paren_depth == 0)
14f9c5c9 246 {
82d049ab 247 rewind_to_char (')');
14f9c5c9
AS
248 return 0;
249 }
4c4b4cd2 250 else
14f9c5c9 251 {
4c4b4cd2 252 paren_depth -= 1;
14f9c5c9
AS
253 return ')';
254 }
255 }
256
257"."{WHITE}*all { return DOT_ALL; }
258
4c4b4cd2 259"."{WHITE}*{ID} {
52ce6436 260 yylval.sval = processId (yytext+1, yyleng-1);
4c4b4cd2 261 return DOT_ID;
14f9c5c9
AS
262 }
263
4c4b4cd2 264{ID}({WHITE}*"."{WHITE}*({ID}|\"{OPER}\"))*(" "*"'")? {
14f9c5c9 265 int all_posn = find_dot_all (yytext);
14f9c5c9 266
4c4b4cd2 267 if (all_posn == -1 && yytext[yyleng-1] == '\'')
14f9c5c9 268 {
52ce6436
PH
269 BEGIN BEFORE_QUAL_QUOTE;
270 yyless (yyleng-1);
14f9c5c9 271 }
52ce6436 272 else if (all_posn >= 0)
14f9c5c9 273 yyless (all_posn);
52ce6436
PH
274 yylval.sval = processId (yytext, yyleng);
275 return NAME;
276 }
14f9c5c9 277
14f9c5c9 278
52ce6436 279 /* GDB EXPRESSION CONSTRUCTS */
14f9c5c9
AS
280
281"'"[^']+"'"{WHITE}*:: {
52ce6436
PH
282 yyless (yyleng - 2);
283 yylval.sval = processId (yytext, yyleng);
284 return NAME;
14f9c5c9
AS
285 }
286
52ce6436 287"::" { return COLONCOLON; }
14f9c5c9
AS
288
289[{}@] { return yytext[0]; }
290
14f9c5c9
AS
291 /* REGISTERS AND GDB CONVENIENCE VARIABLES */
292
4c4b4cd2 293"$"({LETTER}|{DIG}|"$")* {
14f9c5c9
AS
294 yylval.sval.ptr = yytext;
295 yylval.sval.length = yyleng;
cfeadda5 296 return DOLLAR_VARIABLE;
14f9c5c9
AS
297 }
298
299 /* CATCH-ALL ERROR CASE */
300
e1d5a0d2 301. { error (_("Invalid character '%s' in expression."), yytext); }
14f9c5c9
AS
302%%
303
304#include <ctype.h>
52ce6436
PH
305/* Initialize the lexer for processing new expression. */
306
e3084549 307static void
4c4b4cd2 308lexer_init (FILE *inp)
14f9c5c9
AS
309{
310 BEGIN INITIAL;
28aaf3fd 311 paren_depth = 0;
14f9c5c9
AS
312 yyrestart (inp);
313}
314
315
4c4b4cd2 316/* Copy S2 to S1, removing all underscores, and downcasing all letters. */
14f9c5c9
AS
317
318static void
4c4b4cd2 319canonicalizeNumeral (char *s1, const char *s2)
14f9c5c9 320{
4c4b4cd2 321 for (; *s2 != '\000'; s2 += 1)
14f9c5c9
AS
322 {
323 if (*s2 != '_')
324 {
325 *s1 = tolower(*s2);
326 s1 += 1;
327 }
328 }
329 s1[0] = '\000';
330}
331
14f9c5c9
AS
332/* Interprets the prefix of NUM that consists of digits of the given BASE
333 as an integer of that BASE, with the string EXP as an exponent.
334 Puts value in yylval, and returns INT, if the string is valid. Causes
4c4b4cd2 335 an error if the number is improperly formated. BASE, if NULL, defaults
52ce6436
PH
336 to "10", and EXP to "1". The EXP does not contain a leading 'e' or 'E'.
337 */
14f9c5c9
AS
338
339static int
410a0ff2
SDJ
340processInt (struct parser_state *par_state, const char *base0,
341 const char *num0, const char *exp0)
14f9c5c9
AS
342{
343 ULONGEST result;
344 long exp;
345 int base;
a0bcdaa7 346 const char *trailer;
14f9c5c9
AS
347
348 if (base0 == NULL)
349 base = 10;
350 else
4c4b4cd2
PH
351 {
352 base = strtol (base0, (char **) NULL, 10);
14f9c5c9 353 if (base < 2 || base > 16)
e1d5a0d2 354 error (_("Invalid base: %d."), base);
14f9c5c9
AS
355 }
356
357 if (exp0 == NULL)
358 exp = 0;
359 else
4c4b4cd2 360 exp = strtol(exp0, (char **) NULL, 10);
14f9c5c9
AS
361
362 errno = 0;
a0bcdaa7 363 result = strtoulst (num0, &trailer, base);
14f9c5c9 364 if (errno == ERANGE)
e1d5a0d2 365 error (_("Integer literal out of range"));
14f9c5c9 366 if (isxdigit(*trailer))
e1d5a0d2 367 error (_("Invalid digit `%c' in based literal"), *trailer);
14f9c5c9 368
4c4b4cd2 369 while (exp > 0)
14f9c5c9
AS
370 {
371 if (result > (ULONG_MAX / base))
e1d5a0d2 372 error (_("Integer literal out of range"));
14f9c5c9
AS
373 result *= base;
374 exp -= 1;
375 }
4c4b4cd2 376
fa9f5be6 377 if ((result >> (gdbarch_int_bit (par_state->gdbarch ())-1)) == 0)
410a0ff2 378 yylval.typed_val.type = type_int (par_state);
fa9f5be6 379 else if ((result >> (gdbarch_long_bit (par_state->gdbarch ())-1)) == 0)
410a0ff2 380 yylval.typed_val.type = type_long (par_state);
fa9f5be6 381 else if (((result >> (gdbarch_long_bit (par_state->gdbarch ())-1)) >> 1) == 0)
14f9c5c9
AS
382 {
383 /* We have a number representable as an unsigned integer quantity.
4c4b4cd2 384 For consistency with the C treatment, we will treat it as an
14f9c5c9 385 anonymous modular (unsigned) quantity. Alas, the types are such
4c4b4cd2 386 that we need to store .val as a signed quantity. Sorry
14f9c5c9
AS
387 for the mess, but C doesn't officially guarantee that a simple
388 assignment does the trick (no, it doesn't; read the reference manual).
389 */
3e79cecf 390 yylval.typed_val.type
fa9f5be6 391 = builtin_type (par_state->gdbarch ())->builtin_unsigned_long;
14f9c5c9 392 if (result & LONGEST_SIGN)
4c4b4cd2
PH
393 yylval.typed_val.val =
394 (LONGEST) (result & ~LONGEST_SIGN)
14f9c5c9
AS
395 - (LONGEST_SIGN>>1) - (LONGEST_SIGN>>1);
396 else
397 yylval.typed_val.val = (LONGEST) result;
398 return INT;
399 }
4c4b4cd2 400 else
410a0ff2 401 yylval.typed_val.type = type_long_long (par_state);
14f9c5c9
AS
402
403 yylval.typed_val.val = (LONGEST) result;
404 return INT;
405}
406
407static int
410a0ff2 408processReal (struct parser_state *par_state, const char *num0)
14f9c5c9 409{
edd079d9 410 yylval.typed_val_float.type = type_long_double (par_state);
14f9c5c9 411
edd079d9
UW
412 bool parsed = parse_float (num0, strlen (num0),
413 yylval.typed_val_float.type,
414 yylval.typed_val_float.val);
415 gdb_assert (parsed);
14f9c5c9
AS
416 return FLOAT;
417}
418
52ce6436
PH
419
420/* Store a canonicalized version of NAME0[0..LEN-1] in yylval.ssym. The
718cb7da
JB
421 resulting string is valid until the next call to ada_parse. If
422 NAME0 contains the substring "___", it is assumed to be already
b5ec771e
PA
423 encoded and the resulting name is equal to it. Similarly, if the name
424 starts with '<', it is copied verbatim. Otherwise, it differs
52ce6436 425 from NAME0 in that:
b5ec771e
PA
426 + Characters between '...' are transfered verbatim to yylval.ssym.
427 + Trailing "'" characters in quoted sequences are removed (a leading quote is
428 preserved to indicate that the name is not to be GNAT-encoded).
52ce6436
PH
429 + Unquoted whitespace is removed.
430 + Unquoted alphabetic characters are mapped to lower case.
431 Result is returned as a struct stoken, but for convenience, the string
432 is also null-terminated. Result string valid until the next call of
433 ada_parse.
434 */
435static struct stoken
4c4b4cd2 436processId (const char *name0, int len)
14f9c5c9 437{
224c3ddb 438 char *name = (char *) obstack_alloc (&temp_parse_space, len + 11);
14f9c5c9 439 int i0, i;
52ce6436 440 struct stoken result;
4c4b4cd2 441
718cb7da 442 result.ptr = name;
14f9c5c9
AS
443 while (len > 0 && isspace (name0[len-1]))
444 len -= 1;
718cb7da 445
b5ec771e 446 if (name0[0] == '<' || strstr (name0, "___") != NULL)
718cb7da
JB
447 {
448 strncpy (name, name0, len);
449 name[len] = '\000';
450 result.length = len;
451 return result;
452 }
453
14f9c5c9 454 i = i0 = 0;
4c4b4cd2 455 while (i0 < len)
14f9c5c9
AS
456 {
457 if (isalnum (name0[i0]))
458 {
459 name[i] = tolower (name0[i0]);
460 i += 1; i0 += 1;
461 }
4c4b4cd2 462 else switch (name0[i0])
14f9c5c9
AS
463 {
464 default:
465 name[i] = name0[i0];
466 i += 1; i0 += 1;
467 break;
468 case ' ': case '\t':
469 i0 += 1;
470 break;
471 case '\'':
52ce6436 472 do
14f9c5c9
AS
473 {
474 name[i] = name0[i0];
475 i += 1; i0 += 1;
476 }
52ce6436 477 while (i0 < len && name0[i0] != '\'');
14f9c5c9
AS
478 i0 += 1;
479 break;
14f9c5c9
AS
480 }
481 }
482 name[i] = '\000';
483
52ce6436
PH
484 result.length = i;
485 return result;
14f9c5c9
AS
486}
487
52ce6436
PH
488/* Return TEXT[0..LEN-1], a string literal without surrounding quotes,
489 with special hex character notations replaced with characters.
490 Result valid until the next call to ada_parse. */
14f9c5c9 491
52ce6436
PH
492static struct stoken
493processString (const char *text, int len)
14f9c5c9 494{
52ce6436
PH
495 const char *p;
496 char *q;
497 const char *lim = text + len;
498 struct stoken result;
499
224c3ddb 500 q = (char *) obstack_alloc (&temp_parse_space, len);
d7561cbb 501 result.ptr = q;
52ce6436
PH
502 p = text;
503 while (p < lim)
14f9c5c9 504 {
52ce6436
PH
505 if (p[0] == '[' && p[1] == '"' && p+2 < lim)
506 {
507 if (p[2] == '"') /* "...["""]... */
508 {
509 *q = '"';
510 p += 4;
511 }
512 else
513 {
514 int chr;
515 sscanf (p+2, "%2x", &chr);
516 *q = (char) chr;
517 p += 5;
518 }
519 }
520 else
521 *q = *p;
522 q += 1;
523 p += 1;
524 }
525 result.length = q - result.ptr;
526 return result;
14f9c5c9
AS
527}
528
529/* Returns the position within STR of the '.' in a
52ce6436
PH
530 '.{WHITE}*all' component of a dotted name, or -1 if there is none.
531 Note: we actually don't need this routine, since 'all' can never be an
532 Ada identifier. Thus, looking up foo.all or foo.all.x as a name
533 must fail, and will eventually be interpreted as (foo).all or
534 (foo).all.x. However, this does avoid an extraneous lookup. */
535
14f9c5c9 536static int
4c4b4cd2 537find_dot_all (const char *str)
14f9c5c9
AS
538{
539 int i;
a5e619ec
JB
540
541 for (i = 0; str[i] != '\000'; i++)
542 if (str[i] == '.')
543 {
544 int i0 = i;
545
546 do
547 i += 1;
548 while (isspace (str[i]));
549
550 if (strncasecmp (str + i, "all", 3) == 0
551 && !isalnum (str[i + 3]) && str[i + 3] != '_')
552 return i0;
553 }
14f9c5c9 554 return -1;
4c4b4cd2 555}
14f9c5c9
AS
556
557/* Returns non-zero iff string SUBSEQ matches a subsequence of STR, ignoring
4c4b4cd2 558 case. */
14f9c5c9
AS
559
560static int
4c4b4cd2 561subseqMatch (const char *subseq, const char *str)
14f9c5c9
AS
562{
563 if (subseq[0] == '\0')
564 return 1;
565 else if (str[0] == '\0')
566 return 0;
567 else if (tolower (subseq[0]) == tolower (str[0]))
568 return subseqMatch (subseq+1, str+1) || subseqMatch (subseq, str+1);
569 else
570 return subseqMatch (subseq, str+1);
571}
14f9c5c9 572
4c4b4cd2
PH
573
574static struct { const char *name; int code; }
14f9c5c9
AS
575attributes[] = {
576 { "address", TICK_ADDRESS },
577 { "unchecked_access", TICK_ACCESS },
578 { "unrestricted_access", TICK_ACCESS },
579 { "access", TICK_ACCESS },
580 { "first", TICK_FIRST },
581 { "last", TICK_LAST },
582 { "length", TICK_LENGTH },
583 { "max", TICK_MAX },
584 { "min", TICK_MIN },
585 { "modulus", TICK_MODULUS },
586 { "pos", TICK_POS },
587 { "range", TICK_RANGE },
588 { "size", TICK_SIZE },
589 { "tag", TICK_TAG },
590 { "val", TICK_VAL },
591 { NULL, -1 }
592};
593
594/* Return the syntactic code corresponding to the attribute name or
595 abbreviation STR. */
596
597static int
4c4b4cd2 598processAttribute (const char *str)
14f9c5c9
AS
599{
600 int i, k;
601
602 for (i = 0; attributes[i].code != -1; i += 1)
603 if (strcasecmp (str, attributes[i].name) == 0)
604 return attributes[i].code;
605
606 for (i = 0, k = -1; attributes[i].code != -1; i += 1)
4c4b4cd2 607 if (subseqMatch (str, attributes[i].name))
14f9c5c9
AS
608 {
609 if (k == -1)
610 k = i;
4c4b4cd2 611 else
e1d5a0d2 612 error (_("ambiguous attribute name: `%s'"), str);
14f9c5c9
AS
613 }
614 if (k == -1)
e1d5a0d2 615 error (_("unrecognized attribute: `%s'"), str);
14f9c5c9
AS
616
617 return attributes[k].code;
618}
619
82d049ab
PH
620/* Back up lexptr by yyleng and then to the rightmost occurrence of
621 character CH, case-folded (there must be one). WARNING: since
622 lexptr points to the next input character that Flex has not yet
623 transferred to its internal buffer, the use of this function
624 depends on the assumption that Flex calls YY_INPUT only when it is
625 logically necessary to do so (thus, there is no reading ahead
626 farther than needed to identify the next token.) */
627
628static void
629rewind_to_char (int ch)
630{
5776fca3
TT
631 pstate->lexptr -= yyleng;
632 while (toupper (*pstate->lexptr) != toupper (ch))
633 pstate->lexptr -= 1;
82d049ab
PH
634 yyrestart (NULL);
635}
636
23485554
PH
637/* Dummy definition to suppress warnings about unused static definitions. */
638typedef void (*dummy_function) ();
639dummy_function ada_flex_use[] =
640{
375c0479 641 (dummy_function) yyunput
23485554 642};
d1435379
SM
643
644DIAGNOSTIC_POP
This page took 1.070806 seconds and 4 git commands to generate.