]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/ada-lex.l
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / ada-lex.l
CommitLineData
c9f66f00 1/* FLEX lexer for Ada expressions, for GDB. -*- c++ -*-
1d506c26 2 Copyright (C) 1994-2024 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_]
315e4ebb 33ID ({LETTER}({LETTER}|{DIG}|[\x80-\xff])*|"<"{LETTER}({LETTER}|{DIG})*">")
14f9c5c9
AS
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
c66ed94a
TT
42/* This must agree with COMPLETION_CHAR below. See the comment there
43 for the explanation. */
44COMPLETE "\001"
45NOT_COMPLETE [^\001]
46
14f9c5c9 47%{
4c4b4cd2 48
e9cb46ab 49#include "diagnostics.h"
d1435379
SM
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,
b8fff44e
MW
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. */
d1435379
SM
56DIAGNOSTIC_PUSH
57DIAGNOSTIC_IGNORE_DEPRECATED_REGISTER
58
14f9c5c9
AS
59#define NUMERAL_WIDTH 256
60#define LONGEST_SIGN ((ULONGEST) 1 << (sizeof(LONGEST) * HOST_CHAR_BIT - 1))
61
4c4b4cd2
PH
62/* Temporary staging for numeric literals. */
63static char numbuf[NUMERAL_WIDTH];
64 static void canonicalizeNumeral (char *s1, const char *);
52ce6436 65static struct stoken processString (const char*, int);
410a0ff2
SDJ
66static int processInt (struct parser_state *, const char *, const char *,
67 const char *);
68static int processReal (struct parser_state *, const char *);
52ce6436 69static struct stoken processId (const char *, int);
4c4b4cd2
PH
70static int processAttribute (const char *);
71static int find_dot_all (const char *);
82d049ab 72static void rewind_to_char (int);
14f9c5c9
AS
73
74#undef YY_DECL
4c4b4cd2 75#define YY_DECL static int yylex ( void )
14f9c5c9 76
0ec6cd0c
JB
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
c66ed94a
TT
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. */
86static bool returned_complete = false;
87
88/* The character we use to represent the completion point. */
89#define COMPLETE_CHAR '\001'
90
14f9c5c9 91#undef YY_INPUT
c66ed94a
TT
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 }
14f9c5c9 110
28aaf3fd
TT
111/* Depth of parentheses. */
112static int paren_depth;
113
14f9c5c9
AS
114%}
115
fcd60b84 116%option case-insensitive interactive nodefault noyywrap
7dc1ef8d 117
52ce6436 118%s BEFORE_QUAL_QUOTE
14f9c5c9
AS
119
120%%
121
122{WHITE} { }
123
124"--".* { yyterminate(); }
125
4c4b4cd2
PH
126{NUM10}{POSEXP} {
127 canonicalizeNumeral (numbuf, yytext);
c9bfa277
TT
128 char *e_ptr = strrchr (numbuf, 'e');
129 *e_ptr = '\0';
130 return processInt (pstate, nullptr, numbuf, e_ptr + 1);
14f9c5c9
AS
131 }
132
4c4b4cd2
PH
133{NUM10} {
134 canonicalizeNumeral (numbuf, yytext);
410a0ff2 135 return processInt (pstate, NULL, numbuf, NULL);
14f9c5c9
AS
136 }
137
138{NUM10}"#"{HEXDIG}({HEXDIG}|_)*"#"{POSEXP} {
139 canonicalizeNumeral (numbuf, yytext);
c9bfa277
TT
140 char *e_ptr = strrchr (numbuf, 'e');
141 *e_ptr = '\0';
410a0ff2 142 return processInt (pstate, numbuf,
4c4b4cd2 143 strchr (numbuf, '#') + 1,
c9bfa277 144 e_ptr + 1);
14f9c5c9
AS
145 }
146
63fc2437
TT
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}|_)*"#" {
14f9c5c9 152 canonicalizeNumeral (numbuf, yytext);
410a0ff2
SDJ
153 return processInt (pstate, numbuf, strchr (numbuf, '#') + 1,
154 NULL);
14f9c5c9
AS
155 }
156
157"0x"{HEXDIG}+ {
158 canonicalizeNumeral (numbuf, yytext+2);
410a0ff2 159 return processInt (pstate, "16#", numbuf, NULL);
14f9c5c9
AS
160 }
161
162
163{NUM10}"."{NUM10}{EXP} {
4c4b4cd2 164 canonicalizeNumeral (numbuf, yytext);
410a0ff2 165 return processReal (pstate, numbuf);
14f9c5c9
AS
166 }
167
168{NUM10}"."{NUM10} {
4c4b4cd2 169 canonicalizeNumeral (numbuf, yytext);
410a0ff2 170 return processReal (pstate, numbuf);
14f9c5c9
AS
171 }
172
173{NUM10}"#"{NUM16}"."{NUM16}"#"{EXP} {
e1d5a0d2 174 error (_("Based real literals not implemented yet."));
14f9c5c9
AS
175 }
176
177{NUM10}"#"{NUM16}"."{NUM16}"#" {
e1d5a0d2 178 error (_("Based real literals not implemented yet."));
14f9c5c9
AS
179 }
180
181<INITIAL>"'"({GRAPHIC}|\")"'" {
e49831ba
TT
182 yylval.typed_char.val = yytext[1];
183 yylval.typed_char.type = type_for_char (pstate, yytext[1]);
14f9c5c9
AS
184 return CHARLIT;
185 }
186
c9f66f00
TT
187<INITIAL>"'[\""{HEXDIG}{2,}"\"]'" {
188 ULONGEST v = strtoulst (yytext+3, nullptr, 16);
e49831ba
TT
189 yylval.typed_char.val = v;
190 yylval.typed_char.type = type_for_char (pstate, v);
14f9c5c9
AS
191 return CHARLIT;
192 }
193
c9f66f00
TT
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,}|\")"\"]")*\" {
52ce6436 198 yylval.sval = processString (yytext+1, yyleng-2);
14f9c5c9
AS
199 return STRING;
200 }
201
52ce6436 202\" {
e1d5a0d2 203 error (_("ill-formed or non-terminated string literal"));
14f9c5c9
AS
204 }
205
14f9c5c9 206
4c4b4cd2 207if {
82d049ab 208 rewind_to_char ('i');
14f9c5c9
AS
209 return 0;
210 }
211
82d049ab
PH
212task {
213 rewind_to_char ('t');
214 return 0;
215 }
216
217thread{WHITE}+{DIG} {
b9ee2233
JB
218 /* This keyword signals the end of the expression and
219 will be processed separately. */
82d049ab 220 rewind_to_char ('t');
70575d34
JB
221 return 0;
222 }
223
14f9c5c9
AS
224 /* ADA KEYWORDS */
225
226abs { return ABS; }
227and { return _AND_; }
228else { return ELSE; }
229in { return IN; }
230mod { return MOD; }
231new { return NEW; }
232not { return NOT; }
233null { return NULL_PTR; }
234or { return OR; }
52ce6436 235others { return OTHERS; }
14f9c5c9
AS
236rem { return REM; }
237then { return THEN; }
238xor { return XOR; }
239
690cc4eb
PH
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
247true { return TRUEKEYWORD; }
248false { return FALSEKEYWORD; }
249
14f9c5c9
AS
250 /* ATTRIBUTES */
251
c66ed94a 252{TICK}([a-z][a-z_]*)?{COMPLETE}? { BEGIN INITIAL; return processAttribute (yytext); }
14f9c5c9
AS
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
c66ed94a 264<BEFORE_QUAL_QUOTE>"'"/{NOT_COMPLETE} { BEGIN INITIAL; return '\''; }
14f9c5c9 265
484e7c5f 266[-&*+{}@/:<>=|;\[\]] { return yytext[0]; }
14f9c5c9 267
8621b685 268"," { if (paren_depth == 0 && pstate->comma_terminates)
14f9c5c9 269 {
82d049ab 270 rewind_to_char (',');
14f9c5c9
AS
271 return 0;
272 }
4c4b4cd2 273 else
14f9c5c9
AS
274 return ',';
275 }
276
277"(" { paren_depth += 1; return '('; }
4c4b4cd2 278")" { if (paren_depth == 0)
14f9c5c9 279 {
82d049ab 280 rewind_to_char (')');
14f9c5c9
AS
281 return 0;
282 }
4c4b4cd2 283 else
14f9c5c9 284 {
4c4b4cd2 285 paren_depth -= 1;
14f9c5c9
AS
286 return ')';
287 }
288 }
289
d4da1b2c 290"."{WHITE}*{ID}{COMPLETE}? {
52ce6436 291 yylval.sval = processId (yytext+1, yyleng-1);
d4da1b2c
TT
292 if (yytext[yyleng - 1] == COMPLETE_CHAR)
293 return DOT_COMPLETE;
4c4b4cd2 294 return DOT_ID;
14f9c5c9
AS
295 }
296
d4da1b2c
TT
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})? {
14f9c5c9 304 int all_posn = find_dot_all (yytext);
14f9c5c9 305
4c4b4cd2 306 if (all_posn == -1 && yytext[yyleng-1] == '\'')
14f9c5c9 307 {
52ce6436
PH
308 BEGIN BEFORE_QUAL_QUOTE;
309 yyless (yyleng-1);
14f9c5c9 310 }
52ce6436 311 else if (all_posn >= 0)
14f9c5c9 312 yyless (all_posn);
d4da1b2c 313 bool is_completion = yytext[yyleng - 1] == COMPLETE_CHAR;
52ce6436 314 yylval.sval = processId (yytext, yyleng);
d4da1b2c 315 return is_completion ? NAME_COMPLETE : NAME;
52ce6436 316 }
14f9c5c9 317
14f9c5c9 318
52ce6436 319 /* GDB EXPRESSION CONSTRUCTS */
14f9c5c9
AS
320
321"'"[^']+"'"{WHITE}*:: {
52ce6436
PH
322 yyless (yyleng - 2);
323 yylval.sval = processId (yytext, yyleng);
324 return NAME;
14f9c5c9
AS
325 }
326
52ce6436 327"::" { return COLONCOLON; }
14f9c5c9 328
14f9c5c9
AS
329 /* REGISTERS AND GDB CONVENIENCE VARIABLES */
330
4c4b4cd2 331"$"({LETTER}|{DIG}|"$")* {
14f9c5c9
AS
332 yylval.sval.ptr = yytext;
333 yylval.sval.length = yyleng;
cfeadda5 334 return DOLLAR_VARIABLE;
14f9c5c9
AS
335 }
336
337 /* CATCH-ALL ERROR CASE */
338
e1d5a0d2 339. { error (_("Invalid character '%s' in expression."), yytext); }
14f9c5c9
AS
340%%
341
342#include <ctype.h>
52ce6436
PH
343/* Initialize the lexer for processing new expression. */
344
e3084549 345static void
4c4b4cd2 346lexer_init (FILE *inp)
14f9c5c9
AS
347{
348 BEGIN INITIAL;
28aaf3fd 349 paren_depth = 0;
c66ed94a 350 returned_complete = false;
14f9c5c9
AS
351 yyrestart (inp);
352}
353
354
4c4b4cd2 355/* Copy S2 to S1, removing all underscores, and downcasing all letters. */
14f9c5c9
AS
356
357static void
4c4b4cd2 358canonicalizeNumeral (char *s1, const char *s2)
14f9c5c9 359{
4c4b4cd2 360 for (; *s2 != '\000'; s2 += 1)
14f9c5c9
AS
361 {
362 if (*s2 != '_')
363 {
364 *s1 = tolower(*s2);
365 s1 += 1;
366 }
367 }
368 s1[0] = '\000';
369}
370
14f9c5c9
AS
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
3bfdcabb 374 an error if the number is improperly formatted. BASE, if NULL, defaults
52ce6436
PH
375 to "10", and EXP to "1". The EXP does not contain a leading 'e' or 'E'.
376 */
14f9c5c9
AS
377
378static int
410a0ff2
SDJ
379processInt (struct parser_state *par_state, const char *base0,
380 const char *num0, const char *exp0)
14f9c5c9 381{
14f9c5c9
AS
382 long exp;
383 int base;
63fc2437
TT
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;
14f9c5c9
AS
389
390 if (base0 == NULL)
391 base = 10;
392 else
4c4b4cd2 393 {
63fc2437
TT
394 char *end_of_base;
395 base = strtol (base0, &end_of_base, 10);
14f9c5c9 396 if (base < 2 || base > 16)
e1d5a0d2 397 error (_("Invalid base: %d."), base);
63fc2437
TT
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 == '#');
14f9c5c9
AS
412 }
413
414 if (exp0 == NULL)
415 exp = 0;
416 else
4c4b4cd2 417 exp = strtol(exp0, (char **) NULL, 10);
14f9c5c9 418
63fc2437
TT
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);
302273ca
TT
425 result *= base;
426 result += dig;
63fc2437
TT
427 ++num0;
428 }
14f9c5c9 429
4c4b4cd2 430 while (exp > 0)
14f9c5c9 431 {
302273ca 432 result *= base;
14f9c5c9
AS
433 exp -= 1;
434 }
4c4b4cd2 435
63fc2437
TT
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,
df86565b 458 fp_type->length ()),
63fc2437
TT
459 type_byte_order (fp_type),
460 true);
461
462 return FLOAT;
463 }
464
e49831ba
TT
465 int_storage.emplace_back (new gdb_mpz (std::move (result)));
466 const gdb_mpz *value = int_storage.back ().get ();
63fc2437 467
ac3afe36
TV
468 int int_bits = gdbarch_int_bit (par_state->gdbarch ());
469 int long_bits = gdbarch_long_bit (par_state->gdbarch ());
470 int long_long_bits = gdbarch_long_long_bit (par_state->gdbarch ());
471
e49831ba 472 if (fits_in_type (1, *value, int_bits, true))
8a2ced4f 473 yylval.typed_val.type = parse_type (par_state)->builtin_int;
e49831ba 474 else if (fits_in_type (1, *value, long_bits, true))
8a2ced4f 475 yylval.typed_val.type = parse_type (par_state)->builtin_long;
e49831ba
TT
476 else if (fits_in_type (1, *value, long_bits, false))
477 yylval.typed_val.type
478 = builtin_type (par_state->gdbarch ())->builtin_unsigned_long;
479 else if (fits_in_type (1, *value, long_long_bits, true))
8a2ced4f 480 yylval.typed_val.type = parse_type (par_state)->builtin_long_long;
e49831ba
TT
481 else if (fits_in_type (1, *value, long_long_bits, false))
482 yylval.typed_val.type
483 = builtin_type (par_state->gdbarch ())->builtin_unsigned_long_long;
484 else if (fits_in_type (1, *value, 128, true))
485 yylval.typed_val.type
486 = language_lookup_primitive_type (par_state->language (),
487 par_state->gdbarch (),
488 "long_long_long_integer");
489 else if (fits_in_type (1, *value, 128, false))
490 yylval.typed_val.type
491 = language_lookup_primitive_type (par_state->language (),
492 par_state->gdbarch (),
493 "unsigned_long_long_long_integer");
ac3afe36
TV
494 else
495 error (_("Integer literal out of range"));
14f9c5c9 496
63fc2437 497 yylval.typed_val.val = value;
14f9c5c9
AS
498 return INT;
499}
500
501static int
410a0ff2 502processReal (struct parser_state *par_state, const char *num0)
14f9c5c9 503{
8a2ced4f 504 yylval.typed_val_float.type = parse_type (par_state)->builtin_long_double;
14f9c5c9 505
edd079d9
UW
506 bool parsed = parse_float (num0, strlen (num0),
507 yylval.typed_val_float.type,
508 yylval.typed_val_float.val);
509 gdb_assert (parsed);
14f9c5c9
AS
510 return FLOAT;
511}
512
52ce6436
PH
513
514/* Store a canonicalized version of NAME0[0..LEN-1] in yylval.ssym. The
718cb7da
JB
515 resulting string is valid until the next call to ada_parse. If
516 NAME0 contains the substring "___", it is assumed to be already
b5ec771e
PA
517 encoded and the resulting name is equal to it. Similarly, if the name
518 starts with '<', it is copied verbatim. Otherwise, it differs
52ce6436 519 from NAME0 in that:
b5ec771e
PA
520 + Characters between '...' are transfered verbatim to yylval.ssym.
521 + Trailing "'" characters in quoted sequences are removed (a leading quote is
522 preserved to indicate that the name is not to be GNAT-encoded).
52ce6436
PH
523 + Unquoted whitespace is removed.
524 + Unquoted alphabetic characters are mapped to lower case.
525 Result is returned as a struct stoken, but for convenience, the string
526 is also null-terminated. Result string valid until the next call of
527 ada_parse.
528 */
529static struct stoken
4c4b4cd2 530processId (const char *name0, int len)
14f9c5c9 531{
224c3ddb 532 char *name = (char *) obstack_alloc (&temp_parse_space, len + 11);
14f9c5c9 533 int i0, i;
52ce6436 534 struct stoken result;
4c4b4cd2 535
718cb7da 536 result.ptr = name;
14f9c5c9
AS
537 while (len > 0 && isspace (name0[len-1]))
538 len -= 1;
718cb7da 539
b5ec771e 540 if (name0[0] == '<' || strstr (name0, "___") != NULL)
718cb7da
JB
541 {
542 strncpy (name, name0, len);
543 name[len] = '\000';
544 result.length = len;
545 return result;
546 }
547
67700be2 548 bool in_quotes = false;
14f9c5c9 549 i = i0 = 0;
4c4b4cd2 550 while (i0 < len)
14f9c5c9 551 {
d4da1b2c
TT
552 if (name0[i0] == COMPLETE_CHAR)
553 {
554 /* Just ignore. */
555 ++i0;
556 }
557 else if (in_quotes)
67700be2
TT
558 name[i++] = name0[i0++];
559 else if (isalnum (name0[i0]))
14f9c5c9
AS
560 {
561 name[i] = tolower (name0[i0]);
562 i += 1; i0 += 1;
563 }
67700be2
TT
564 else if (isspace (name0[i0]))
565 i0 += 1;
566 else if (name0[i0] == '\'')
14f9c5c9 567 {
67700be2
TT
568 /* Copy the starting quote, but not the ending quote. */
569 if (!in_quotes)
570 name[i++] = name0[i0++];
571 in_quotes = !in_quotes;
14f9c5c9 572 }
67700be2
TT
573 else
574 name[i++] = name0[i0++];
14f9c5c9
AS
575 }
576 name[i] = '\000';
577
52ce6436
PH
578 result.length = i;
579 return result;
14f9c5c9
AS
580}
581
52ce6436
PH
582/* Return TEXT[0..LEN-1], a string literal without surrounding quotes,
583 with special hex character notations replaced with characters.
584 Result valid until the next call to ada_parse. */
14f9c5c9 585
52ce6436
PH
586static struct stoken
587processString (const char *text, int len)
14f9c5c9 588{
52ce6436
PH
589 const char *p;
590 char *q;
591 const char *lim = text + len;
592 struct stoken result;
593
224c3ddb 594 q = (char *) obstack_alloc (&temp_parse_space, len);
d7561cbb 595 result.ptr = q;
52ce6436
PH
596 p = text;
597 while (p < lim)
14f9c5c9 598 {
52ce6436
PH
599 if (p[0] == '[' && p[1] == '"' && p+2 < lim)
600 {
601 if (p[2] == '"') /* "...["""]... */
602 {
603 *q = '"';
604 p += 4;
605 }
606 else
607 {
c9f66f00
TT
608 const char *end;
609 ULONGEST chr = strtoulst (p + 2, &end, 16);
610 if (chr > 0xff)
611 error (_("wide strings are not yet supported"));
52ce6436 612 *q = (char) chr;
c9f66f00 613 p = end + 1;
52ce6436
PH
614 }
615 }
616 else
617 *q = *p;
618 q += 1;
619 p += 1;
620 }
621 result.length = q - result.ptr;
622 return result;
14f9c5c9
AS
623}
624
625/* Returns the position within STR of the '.' in a
52ce6436
PH
626 '.{WHITE}*all' component of a dotted name, or -1 if there is none.
627 Note: we actually don't need this routine, since 'all' can never be an
628 Ada identifier. Thus, looking up foo.all or foo.all.x as a name
629 must fail, and will eventually be interpreted as (foo).all or
630 (foo).all.x. However, this does avoid an extraneous lookup. */
631
14f9c5c9 632static int
4c4b4cd2 633find_dot_all (const char *str)
14f9c5c9
AS
634{
635 int i;
a5e619ec
JB
636
637 for (i = 0; str[i] != '\000'; i++)
638 if (str[i] == '.')
639 {
640 int i0 = i;
641
642 do
643 i += 1;
644 while (isspace (str[i]));
645
646 if (strncasecmp (str + i, "all", 3) == 0
647 && !isalnum (str[i + 3]) && str[i + 3] != '_')
648 return i0;
649 }
14f9c5c9 650 return -1;
4c4b4cd2 651}
14f9c5c9
AS
652
653/* Returns non-zero iff string SUBSEQ matches a subsequence of STR, ignoring
4c4b4cd2 654 case. */
14f9c5c9
AS
655
656static int
4c4b4cd2 657subseqMatch (const char *subseq, const char *str)
14f9c5c9
AS
658{
659 if (subseq[0] == '\0')
660 return 1;
661 else if (str[0] == '\0')
662 return 0;
663 else if (tolower (subseq[0]) == tolower (str[0]))
664 return subseqMatch (subseq+1, str+1) || subseqMatch (subseq, str+1);
665 else
666 return subseqMatch (subseq, str+1);
667}
14f9c5c9 668
4c4b4cd2
PH
669
670static struct { const char *name; int code; }
14f9c5c9
AS
671attributes[] = {
672 { "address", TICK_ADDRESS },
673 { "unchecked_access", TICK_ACCESS },
674 { "unrestricted_access", TICK_ACCESS },
675 { "access", TICK_ACCESS },
676 { "first", TICK_FIRST },
677 { "last", TICK_LAST },
678 { "length", TICK_LENGTH },
679 { "max", TICK_MAX },
680 { "min", TICK_MIN },
681 { "modulus", TICK_MODULUS },
682 { "pos", TICK_POS },
683 { "range", TICK_RANGE },
684 { "size", TICK_SIZE },
685 { "tag", TICK_TAG },
686 { "val", TICK_VAL },
22f6f797
TT
687 { "enum_rep", TICK_ENUM_REP },
688 { "enum_val", TICK_ENUM_VAL },
14f9c5c9
AS
689};
690
691/* Return the syntactic code corresponding to the attribute name or
692 abbreviation STR. */
693
694static int
4c4b4cd2 695processAttribute (const char *str)
14f9c5c9 696{
45016746
TT
697 gdb_assert (*str == '\'');
698 ++str;
699 while (isspace (*str))
700 ++str;
701
c66ed94a
TT
702 int len = strlen (str);
703 if (len > 0 && str[len - 1] == COMPLETE_CHAR)
704 {
705 /* This is enforced by YY_INPUT. */
706 gdb_assert (pstate->parse_completion);
707 yylval.sval.ptr = obstack_strndup (&temp_parse_space, str, len - 1);
708 yylval.sval.length = len - 1;
709 return TICK_COMPLETE;
710 }
711
c3f2a373
TT
712 for (const auto &item : attributes)
713 if (strcasecmp (str, item.name) == 0)
714 return item.code;
14f9c5c9 715
6b09f134 716 std::optional<int> found;
c3f2a373
TT
717 for (const auto &item : attributes)
718 if (subseqMatch (str, item.name))
14f9c5c9 719 {
c3f2a373
TT
720 if (!found.has_value ())
721 found = item.code;
4c4b4cd2 722 else
e1d5a0d2 723 error (_("ambiguous attribute name: `%s'"), str);
14f9c5c9 724 }
c3f2a373 725 if (!found.has_value ())
e1d5a0d2 726 error (_("unrecognized attribute: `%s'"), str);
14f9c5c9 727
c3f2a373 728 return *found;
14f9c5c9
AS
729}
730
c66ed94a
TT
731bool
732ada_tick_completer::complete (struct expression *exp,
733 completion_tracker &tracker)
734{
735 completion_list output;
736 for (const auto &item : attributes)
737 {
738 if (strncasecmp (item.name, m_name.c_str (), m_name.length ()) == 0)
739 output.emplace_back (xstrdup (item.name));
740 }
741 tracker.add_completions (std::move (output));
742 return true;
743}
744
82d049ab
PH
745/* Back up lexptr by yyleng and then to the rightmost occurrence of
746 character CH, case-folded (there must be one). WARNING: since
747 lexptr points to the next input character that Flex has not yet
748 transferred to its internal buffer, the use of this function
749 depends on the assumption that Flex calls YY_INPUT only when it is
750 logically necessary to do so (thus, there is no reading ahead
751 farther than needed to identify the next token.) */
752
753static void
754rewind_to_char (int ch)
755{
5776fca3
TT
756 pstate->lexptr -= yyleng;
757 while (toupper (*pstate->lexptr) != toupper (ch))
758 pstate->lexptr -= 1;
82d049ab
PH
759 yyrestart (NULL);
760}
761
23485554
PH
762/* Dummy definition to suppress warnings about unused static definitions. */
763typedef void (*dummy_function) ();
764dummy_function ada_flex_use[] =
765{
375c0479 766 (dummy_function) yyunput
23485554 767};
d1435379
SM
768
769DIAGNOSTIC_POP