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