packaging: Add python3-base dependency
[platform/upstream/gdb.git] / gdb / ada-lex.l
1 /* FLEX lexer for Ada expressions, for GDB. -*- c++ -*-
2    Copyright (C) 1994-2023 Free Software Foundation, Inc.
3
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/>.  */
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
27 DIG     [0-9]
28 NUM10   ({DIG}({DIG}|_)*)
29 HEXDIG  [0-9a-f]
30 NUM16   ({HEXDIG}({HEXDIG}|_)*)
31 OCTDIG  [0-7]
32 LETTER  [a-z_]
33 ID      ({LETTER}({LETTER}|{DIG}|[\x80-\xff])*|"<"{LETTER}({LETTER}|{DIG})*">")
34 WHITE   [ \t\n]
35 TICK    ("'"{WHITE}*)
36 GRAPHIC [a-z0-9 #&'()*+,-./:;<>=_|!$%?@\[\]\\^`{}~]
37 OPER    ([-+*/=<>&]|"<="|">="|"**"|"/="|"and"|"or"|"xor"|"not"|"mod"|"rem"|"abs")
38
39 EXP     (e[+-]{NUM10})
40 POSEXP  (e"+"?{NUM10})
41
42 /* This must agree with COMPLETION_CHAR below.  See the comment there
43    for the explanation.  */
44 COMPLETE "\001"
45 NOT_COMPLETE [^\001]
46
47 %{
48
49 #include "diagnostics.h"
50
51 /* Some old versions of flex generate code that uses the "register" keyword,
52    which clang warns about.  This was observed for example with flex 2.5.35,
53    as shipped with macOS 10.12.  The same happens with flex 2.5.37 and g++ 11
54    which defaults to ISO C++17, that does not allow register storage class
55    specifiers.  */
56 DIAGNOSTIC_PUSH
57 DIAGNOSTIC_IGNORE_DEPRECATED_REGISTER
58
59 #define NUMERAL_WIDTH 256
60 #define LONGEST_SIGN ((ULONGEST) 1 << (sizeof(LONGEST) * HOST_CHAR_BIT - 1))
61
62 /* Temporary staging for numeric literals.  */
63 static char numbuf[NUMERAL_WIDTH];
64  static void canonicalizeNumeral (char *s1, const char *);
65 static struct stoken processString (const char*, int);
66 static int processInt (struct parser_state *, const char *, const char *,
67                        const char *);
68 static int processReal (struct parser_state *, const char *);
69 static struct stoken processId (const char *, int);
70 static int processAttribute (const char *);
71 static int find_dot_all (const char *);
72 static void rewind_to_char (int);
73
74 #undef YY_DECL
75 #define YY_DECL static int yylex ( void )
76
77 /* Flex generates a static function "input" which is not used.
78    Defining YY_NO_INPUT comments it out.  */
79 #define YY_NO_INPUT
80
81 /* When completing, we'll return a special character at the end of the
82    input, to signal the completion position to the lexer.  This is
83    done because flex does not have a generally useful way to detect
84    EOF in a pattern.  This variable records whether the special
85    character has been emitted.  */
86 static bool returned_complete = false;
87
88 /* The character we use to represent the completion point.  */
89 #define COMPLETE_CHAR '\001'
90
91 #undef YY_INPUT
92 #define YY_INPUT(BUF, RESULT, MAX_SIZE)                                 \
93   if ( *pstate->lexptr == '\000' )                                      \
94     {                                                                   \
95       if (pstate->parse_completion && !returned_complete)               \
96         {                                                               \
97           returned_complete = true;                                     \
98           *(BUF) = COMPLETE_CHAR;                                       \
99           (RESULT) = 1;                                                 \
100         }                                                               \
101       else                                                              \
102         (RESULT) = YY_NULL;                                             \
103     }                                                                   \
104   else                                                                  \
105     {                                                                   \
106       *(BUF) = *pstate->lexptr == COMPLETE_CHAR ? ' ' : *pstate->lexptr; \
107       (RESULT) = 1;                                                     \
108       pstate->lexptr += 1;                                              \
109     }
110
111 /* Depth of parentheses.  */
112 static int paren_depth;
113
114 %}
115
116 %option case-insensitive interactive nodefault noyywrap
117
118 %s BEFORE_QUAL_QUOTE
119
120 %%
121
122 {WHITE}          { }
123
124 "--".*           { yyterminate(); }
125
126 {NUM10}{POSEXP}  {
127                    canonicalizeNumeral (numbuf, yytext);
128                    char *e_ptr = strrchr (numbuf, 'e');
129                    *e_ptr = '\0';
130                    return processInt (pstate, nullptr, numbuf, e_ptr + 1);
131                  }
132
133 {NUM10}          {
134                    canonicalizeNumeral (numbuf, yytext);
135                    return processInt (pstate, NULL, numbuf, NULL);
136                  }
137
138 {NUM10}"#"{HEXDIG}({HEXDIG}|_)*"#"{POSEXP} {
139                    canonicalizeNumeral (numbuf, yytext);
140                    char *e_ptr = strrchr (numbuf, 'e');
141                    *e_ptr = '\0';
142                    return processInt (pstate, numbuf,
143                                       strchr (numbuf, '#') + 1,
144                                       e_ptr + 1);
145                  }
146
147         /* The "llf" is a gdb extension to allow a floating-point
148            constant to be written in some other base.  The
149            floating-point number is formed by reinterpreting the
150            bytes, allowing direct control over the bits.  */
151 {NUM10}(l{0,2}f)?"#"{HEXDIG}({HEXDIG}|_)*"#" {
152                    canonicalizeNumeral (numbuf, yytext);
153                    return processInt (pstate, numbuf, strchr (numbuf, '#') + 1,
154                                       NULL);
155                  }
156
157 "0x"{HEXDIG}+   {
158                   canonicalizeNumeral (numbuf, yytext+2);
159                   return processInt (pstate, "16#", numbuf, NULL);
160                 }
161
162
163 {NUM10}"."{NUM10}{EXP} {
164                    canonicalizeNumeral (numbuf, yytext);
165                    return processReal (pstate, numbuf);
166                 }
167
168 {NUM10}"."{NUM10} {
169                    canonicalizeNumeral (numbuf, yytext);
170                    return processReal (pstate, numbuf);
171                 }
172
173 {NUM10}"#"{NUM16}"."{NUM16}"#"{EXP} {
174                    error (_("Based real literals not implemented yet."));
175                 }
176
177 {NUM10}"#"{NUM16}"."{NUM16}"#" {
178                    error (_("Based real literals not implemented yet."));
179                 }
180
181 <INITIAL>"'"({GRAPHIC}|\")"'" {
182                    yylval.typed_val.val = yytext[1];
183                    yylval.typed_val.type = type_for_char (pstate, yytext[1]);
184                    return CHARLIT;
185                 }
186
187 <INITIAL>"'[\""{HEXDIG}{2,}"\"]'"   {
188                    ULONGEST v = strtoulst (yytext+3, nullptr, 16);
189                    yylval.typed_val.val = v;
190                    yylval.typed_val.type = type_for_char (pstate, v);
191                    return CHARLIT;
192                 }
193
194         /* Note that we don't handle bracket sequences of more than 2
195            digits here.  Currently there's no support for wide or
196            wide-wide strings.  */
197 \"({GRAPHIC}|"[\""({HEXDIG}{2,}|\")"\"]")*\"   {
198                    yylval.sval = processString (yytext+1, yyleng-2);
199                    return STRING;
200                 }
201
202 \"              {
203                    error (_("ill-formed or non-terminated string literal"));
204                 }
205
206
207 if              {
208                   rewind_to_char ('i');
209                   return 0;
210                 }
211
212 task            {
213                   rewind_to_char ('t');
214                   return 0;
215                 }
216
217 thread{WHITE}+{DIG} {
218                   /* This keyword signals the end of the expression and
219                      will be processed separately.  */
220                   rewind_to_char ('t');
221                   return 0;
222                 }
223
224         /* ADA KEYWORDS */
225
226 abs             { return ABS; }
227 and             { return _AND_; }
228 else            { return ELSE; }
229 in              { return IN; }
230 mod             { return MOD; }
231 new             { return NEW; }
232 not             { return NOT; }
233 null            { return NULL_PTR; }
234 or              { return OR; }
235 others          { return OTHERS; }
236 rem             { return REM; }
237 then            { return THEN; }
238 xor             { return XOR; }
239
240         /* BOOLEAN "KEYWORDS" */
241
242  /* True and False are not keywords in Ada, but rather enumeration constants.
243     However, the boolean type is no longer represented as an enum, so True
244     and False are no longer defined in symbol tables.  We compromise by
245     making them keywords (when bare). */
246
247 true            { return TRUEKEYWORD; }
248 false           { return FALSEKEYWORD; }
249
250         /* ATTRIBUTES */
251
252 {TICK}([a-z][a-z_]*)?{COMPLETE}? { BEGIN INITIAL; return processAttribute (yytext); }
253
254         /* PUNCTUATION */
255
256 "=>"            { return ARROW; }
257 ".."            { return DOTDOT; }
258 "**"            { return STARSTAR; }
259 ":="            { return ASSIGN; }
260 "/="            { return NOTEQUAL; }
261 "<="            { return LEQ; }
262 ">="            { return GEQ; }
263
264 <BEFORE_QUAL_QUOTE>"'"/{NOT_COMPLETE} { BEGIN INITIAL; return '\''; }
265
266 [-&*+{}@/:<>=|;\[\]] { return yytext[0]; }
267
268 ","             { if (paren_depth == 0 && pstate->comma_terminates)
269                     {
270                       rewind_to_char (',');
271                       return 0;
272                     }
273                   else
274                     return ',';
275                 }
276
277 "("             { paren_depth += 1; return '('; }
278 ")"             { if (paren_depth == 0)
279                     {
280                       rewind_to_char (')');
281                       return 0;
282                     }
283                   else
284                     {
285                       paren_depth -= 1;
286                       return ')';
287                     }
288                 }
289
290 "."{WHITE}*{ID}{COMPLETE}? {
291                   yylval.sval = processId (yytext+1, yyleng-1);
292                   if (yytext[yyleng - 1] == COMPLETE_CHAR)
293                     return DOT_COMPLETE;
294                   return DOT_ID;
295                 }
296
297 "."{WHITE}*{COMPLETE} {
298                   yylval.sval.ptr = "";
299                   yylval.sval.length = 0;
300                   return DOT_COMPLETE;
301                 }
302
303 {ID}({WHITE}*"."{WHITE}*({ID}|\"{OPER}\"))*(" "*"'"|{COMPLETE})?  {
304                   int all_posn = find_dot_all (yytext);
305
306                   if (all_posn == -1 && yytext[yyleng-1] == '\'')
307                     {
308                       BEGIN BEFORE_QUAL_QUOTE;
309                       yyless (yyleng-1);
310                     }
311                   else if (all_posn >= 0)
312                     yyless (all_posn);
313                   bool is_completion = yytext[yyleng - 1] == COMPLETE_CHAR;
314                   yylval.sval = processId (yytext, yyleng);
315                   return is_completion ? NAME_COMPLETE : NAME;
316                }
317
318
319         /* GDB EXPRESSION CONSTRUCTS  */
320
321 "'"[^']+"'"{WHITE}*:: {
322                   yyless (yyleng - 2);
323                   yylval.sval = processId (yytext, yyleng);
324                   return NAME;
325                 }
326
327 "::"            { return COLONCOLON; }
328
329         /* REGISTERS AND GDB CONVENIENCE VARIABLES */
330
331 "$"({LETTER}|{DIG}|"$")*  {
332                   yylval.sval.ptr = yytext;
333                   yylval.sval.length = yyleng;
334                   return DOLLAR_VARIABLE;
335                 }
336
337         /* CATCH-ALL ERROR CASE */
338
339 .               { error (_("Invalid character '%s' in expression."), yytext); }
340 %%
341
342 #include <ctype.h>
343 /* Initialize the lexer for processing new expression. */
344
345 static void
346 lexer_init (FILE *inp)
347 {
348   BEGIN INITIAL;
349   paren_depth = 0;
350   returned_complete = false;
351   yyrestart (inp);
352 }
353
354
355 /* Copy S2 to S1, removing all underscores, and downcasing all letters.  */
356
357 static void
358 canonicalizeNumeral (char *s1, const char *s2)
359 {
360   for (; *s2 != '\000'; s2 += 1)
361     {
362       if (*s2 != '_')
363         {
364           *s1 = tolower(*s2);
365           s1 += 1;
366         }
367     }
368   s1[0] = '\000';
369 }
370
371 /* Interprets the prefix of NUM that consists of digits of the given BASE
372    as an integer of that BASE, with the string EXP as an exponent.
373    Puts value in yylval, and returns INT, if the string is valid.  Causes
374    an error if the number is improperly formated.   BASE, if NULL, defaults
375    to "10", and EXP to "1".  The EXP does not contain a leading 'e' or 'E'.
376  */
377
378 static int
379 processInt (struct parser_state *par_state, const char *base0,
380             const char *num0, const char *exp0)
381 {
382   long exp;
383   int base;
384   /* For the based literal with an "f" prefix, we'll return a
385      floating-point number.  This counts the the number of "l"s seen,
386      to decide the width of the floating-point number to return.  -1
387      means no "f".  */
388   int floating_point_l_count = -1;
389
390   if (base0 == NULL)
391     base = 10;
392   else
393     {
394       char *end_of_base;
395       base = strtol (base0, &end_of_base, 10);
396       if (base < 2 || base > 16)
397         error (_("Invalid base: %d."), base);
398       while (*end_of_base == 'l')
399         {
400           ++floating_point_l_count;
401           ++end_of_base;
402         }
403       /* This assertion is ensured by the pattern.  */
404       gdb_assert (floating_point_l_count == -1 || *end_of_base == 'f');
405       if (*end_of_base == 'f')
406         {
407           ++end_of_base;
408           ++floating_point_l_count;
409         }
410       /* This assertion is ensured by the pattern.  */
411       gdb_assert (*end_of_base == '#');
412     }
413
414   if (exp0 == NULL)
415     exp = 0;
416   else
417     exp = strtol(exp0, (char **) NULL, 10);
418
419   gdb_mpz result;
420   while (isxdigit (*num0))
421     {
422       int dig = fromhex (*num0);
423       if (dig >= base)
424         error (_("Invalid digit `%c' in based literal"), *num0);
425       mpz_mul_ui (result.val, result.val, base);
426       mpz_add_ui (result.val, result.val, dig);
427       ++num0;
428     }
429
430   while (exp > 0)
431     {
432       mpz_mul_ui (result.val, result.val, base);
433       exp -= 1;
434     }
435
436   if (floating_point_l_count > -1)
437     {
438       struct type *fp_type;
439       if (floating_point_l_count == 0)
440         fp_type = language_lookup_primitive_type (par_state->language (),
441                                                   par_state->gdbarch (),
442                                                   "float");
443       else if (floating_point_l_count == 1)
444         fp_type = language_lookup_primitive_type (par_state->language (),
445                                                   par_state->gdbarch (),
446                                                   "long_float");
447       else
448         {
449           /* This assertion is ensured by the pattern.  */
450           gdb_assert (floating_point_l_count == 2);
451           fp_type = language_lookup_primitive_type (par_state->language (),
452                                                     par_state->gdbarch (),
453                                                     "long_long_float");
454         }
455
456       yylval.typed_val_float.type = fp_type;
457       result.write (gdb::make_array_view (yylval.typed_val_float.val,
458                                           fp_type->length ()),
459                     type_byte_order (fp_type),
460                     true);
461
462       return FLOAT;
463     }
464
465   gdb_mpz maxval (ULONGEST_MAX);
466   if (mpz_cmp (result.val, maxval.val) > 0)
467     error (_("Integer literal out of range"));
468
469   int int_bits = gdbarch_int_bit (par_state->gdbarch ());
470   int long_bits = gdbarch_long_bit (par_state->gdbarch ());
471   int long_long_bits = gdbarch_long_long_bit (par_state->gdbarch ());
472
473   ULONGEST value = result.as_integer<ULONGEST> ();
474   if (fits_in_type (1, value, int_bits, true))
475     yylval.typed_val.type = type_int (par_state);
476   else if (fits_in_type (1, value, long_bits, true))
477     yylval.typed_val.type = type_long (par_state);
478   else if (fits_in_type (1, value, long_bits, false))
479     {
480       /* We have a number representable as an unsigned integer quantity.
481          For consistency with the C treatment, we will treat it as an
482          anonymous modular (unsigned) quantity.  Alas, the types are such
483          that we need to store .val as a signed quantity.  Sorry
484          for the mess, but C doesn't officially guarantee that a simple
485          assignment does the trick (no, it doesn't; read the reference manual).
486        */
487       yylval.typed_val.type
488         = builtin_type (par_state->gdbarch ())->builtin_unsigned_long;
489       if (value & LONGEST_SIGN)
490         yylval.typed_val.val =
491           (LONGEST) (value & ~LONGEST_SIGN)
492           - (LONGEST_SIGN>>1) - (LONGEST_SIGN>>1);
493       else
494         yylval.typed_val.val = (LONGEST) value;
495       return INT;
496     }
497   else if (fits_in_type (1, value, long_long_bits, true))
498     yylval.typed_val.type = type_long_long (par_state);
499   else if (fits_in_type (1, value, long_long_bits, false))
500     {
501       yylval.typed_val.type
502         = builtin_type (par_state->gdbarch ())->builtin_unsigned_long_long;
503       /* See unsigned long case above.  */
504       if (value & LONGEST_SIGN)
505         yylval.typed_val.val =
506           (LONGEST) (value & ~LONGEST_SIGN)
507           - (LONGEST_SIGN>>1) - (LONGEST_SIGN>>1);
508       else
509         yylval.typed_val.val = (LONGEST) value;
510       return INT;
511     }
512   else
513     error (_("Integer literal out of range"));
514
515   yylval.typed_val.val = value;
516   return INT;
517 }
518
519 static int
520 processReal (struct parser_state *par_state, const char *num0)
521 {
522   yylval.typed_val_float.type = type_long_double (par_state);
523
524   bool parsed = parse_float (num0, strlen (num0),
525                              yylval.typed_val_float.type,
526                              yylval.typed_val_float.val);
527   gdb_assert (parsed);
528   return FLOAT;
529 }
530
531
532 /* Store a canonicalized version of NAME0[0..LEN-1] in yylval.ssym.  The
533    resulting string is valid until the next call to ada_parse.  If
534    NAME0 contains the substring "___", it is assumed to be already
535    encoded and the resulting name is equal to it.  Similarly, if the name
536    starts with '<', it is copied verbatim.  Otherwise, it differs
537    from NAME0 in that:
538     + Characters between '...' are transfered verbatim to yylval.ssym.
539     + Trailing "'" characters in quoted sequences are removed (a leading quote is
540       preserved to indicate that the name is not to be GNAT-encoded).
541     + Unquoted whitespace is removed.
542     + Unquoted alphabetic characters are mapped to lower case.
543    Result is returned as a struct stoken, but for convenience, the string
544    is also null-terminated.  Result string valid until the next call of
545    ada_parse.
546  */
547 static struct stoken
548 processId (const char *name0, int len)
549 {
550   char *name = (char *) obstack_alloc (&temp_parse_space, len + 11);
551   int i0, i;
552   struct stoken result;
553
554   result.ptr = name;
555   while (len > 0 && isspace (name0[len-1]))
556     len -= 1;
557
558   if (name0[0] == '<' || strstr (name0, "___") != NULL)
559     {
560       strncpy (name, name0, len);
561       name[len] = '\000';
562       result.length = len;
563       return result;
564     }
565
566   bool in_quotes = false;
567   i = i0 = 0;
568   while (i0 < len)
569     {
570       if (name0[i0] == COMPLETE_CHAR)
571         {
572           /* Just ignore.  */
573           ++i0;
574         }
575       else if (in_quotes)
576         name[i++] = name0[i0++];
577       else if (isalnum (name0[i0]))
578         {
579           name[i] = tolower (name0[i0]);
580           i += 1; i0 += 1;
581         }
582       else if (isspace (name0[i0]))
583         i0 += 1;
584       else if (name0[i0] == '\'')
585         {
586           /* Copy the starting quote, but not the ending quote.  */
587           if (!in_quotes)
588             name[i++] = name0[i0++];
589           in_quotes = !in_quotes;
590         }
591       else
592         name[i++] = name0[i0++];
593     }
594   name[i] = '\000';
595
596   result.length = i;
597   return result;
598 }
599
600 /* Return TEXT[0..LEN-1], a string literal without surrounding quotes,
601    with special hex character notations replaced with characters. 
602    Result valid until the next call to ada_parse.  */
603
604 static struct stoken
605 processString (const char *text, int len)
606 {
607   const char *p;
608   char *q;
609   const char *lim = text + len;
610   struct stoken result;
611
612   q = (char *) obstack_alloc (&temp_parse_space, len);
613   result.ptr = q;
614   p = text;
615   while (p < lim)
616     {
617       if (p[0] == '[' && p[1] == '"' && p+2 < lim)
618          {
619            if (p[2] == '"')  /* "...["""]... */
620              {
621                *q = '"';
622                p += 4;
623              }
624            else
625              {
626                const char *end;
627                ULONGEST chr = strtoulst (p + 2, &end, 16);
628                if (chr > 0xff)
629                  error (_("wide strings are not yet supported"));
630                *q = (char) chr;
631                p = end + 1;
632              }
633          }
634        else
635          *q = *p;
636        q += 1;
637        p += 1;
638      }
639   result.length = q - result.ptr;
640   return result;
641 }
642
643 /* Returns the position within STR of the '.' in a
644    '.{WHITE}*all' component of a dotted name, or -1 if there is none.
645    Note: we actually don't need this routine, since 'all' can never be an
646    Ada identifier.  Thus, looking up foo.all or foo.all.x as a name
647    must fail, and will eventually be interpreted as (foo).all or
648    (foo).all.x.  However, this does avoid an extraneous lookup. */
649
650 static int
651 find_dot_all (const char *str)
652 {
653   int i;
654
655   for (i = 0; str[i] != '\000'; i++)
656     if (str[i] == '.')
657       {
658         int i0 = i;
659
660         do
661           i += 1;
662         while (isspace (str[i]));
663
664         if (strncasecmp (str + i, "all", 3) == 0
665             && !isalnum (str[i + 3]) && str[i + 3] != '_')
666           return i0;
667       }
668   return -1;
669 }
670
671 /* Returns non-zero iff string SUBSEQ matches a subsequence of STR, ignoring
672    case.  */
673
674 static int
675 subseqMatch (const char *subseq, const char *str)
676 {
677   if (subseq[0] == '\0')
678     return 1;
679   else if (str[0] == '\0')
680     return 0;
681   else if (tolower (subseq[0]) == tolower (str[0]))
682     return subseqMatch (subseq+1, str+1) || subseqMatch (subseq, str+1);
683   else
684     return subseqMatch (subseq, str+1);
685 }
686
687
688 static struct { const char *name; int code; }
689 attributes[] = {
690   { "address", TICK_ADDRESS },
691   { "unchecked_access", TICK_ACCESS },
692   { "unrestricted_access", TICK_ACCESS },
693   { "access", TICK_ACCESS },
694   { "first", TICK_FIRST },
695   { "last", TICK_LAST },
696   { "length", TICK_LENGTH },
697   { "max", TICK_MAX },
698   { "min", TICK_MIN },
699   { "modulus", TICK_MODULUS },
700   { "pos", TICK_POS },
701   { "range", TICK_RANGE },
702   { "size", TICK_SIZE },
703   { "tag", TICK_TAG },
704   { "val", TICK_VAL },
705 };
706
707 /* Return the syntactic code corresponding to the attribute name or
708    abbreviation STR.  */
709
710 static int
711 processAttribute (const char *str)
712 {
713   gdb_assert (*str == '\'');
714   ++str;
715   while (isspace (*str))
716     ++str;
717
718   int len = strlen (str);
719   if (len > 0 && str[len - 1] == COMPLETE_CHAR)
720     {
721       /* This is enforced by YY_INPUT.  */
722       gdb_assert (pstate->parse_completion);
723       yylval.sval.ptr = obstack_strndup (&temp_parse_space, str, len - 1);
724       yylval.sval.length = len - 1;
725       return TICK_COMPLETE;
726     }
727
728   for (const auto &item : attributes)
729     if (strcasecmp (str, item.name) == 0)
730       return item.code;
731
732   gdb::optional<int> found;
733   for (const auto &item : attributes)
734     if (subseqMatch (str, item.name))
735       {
736         if (!found.has_value ())
737           found = item.code;
738         else
739           error (_("ambiguous attribute name: `%s'"), str);
740       }
741   if (!found.has_value ())
742     error (_("unrecognized attribute: `%s'"), str);
743
744   return *found;
745 }
746
747 bool
748 ada_tick_completer::complete (struct expression *exp,
749                               completion_tracker &tracker)
750 {
751   completion_list output;
752   for (const auto &item : attributes)
753     {
754       if (strncasecmp (item.name, m_name.c_str (), m_name.length ()) == 0)
755         output.emplace_back (xstrdup (item.name));
756     }
757   tracker.add_completions (std::move (output));
758   return true;
759 }
760
761 /* Back up lexptr by yyleng and then to the rightmost occurrence of
762    character CH, case-folded (there must be one).  WARNING: since
763    lexptr points to the next input character that Flex has not yet
764    transferred to its internal buffer, the use of this function
765    depends on the assumption that Flex calls YY_INPUT only when it is
766    logically necessary to do so (thus, there is no reading ahead
767    farther than needed to identify the next token.)  */
768
769 static void
770 rewind_to_char (int ch)
771 {
772   pstate->lexptr -= yyleng;
773   while (toupper (*pstate->lexptr) != toupper (ch))
774     pstate->lexptr -= 1;
775   yyrestart (NULL);
776 }
777
778 /* Dummy definition to suppress warnings about unused static definitions. */
779 typedef void (*dummy_function) ();
780 dummy_function ada_flex_use[] = 
781
782   (dummy_function) yyunput
783 };
784
785 DIAGNOSTIC_POP