xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/ada-lex.l (revision 8b657b0747480f8989760d71343d6dd33f8d4cf9)
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
786