Commit | Line | Data |
---|---|---|
14f9c5c9 | 1 | /* FLEX lexer for Ada expressions, for GDB. |
4c4b4cd2 | 2 | Copyright (C) 1994, 1997, 1998, 2000, 2001, 2002, 2003 |
14f9c5c9 AS |
3 | Free Software Foundation, Inc. |
4 | ||
5 | This file is part of GDB. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program; if not, write to the Free Software | |
197e01b6 EZ |
19 | Foundation, Inc., 51 Franklin Street, Fifth Floor, |
20 | Boston, MA 02110-1301, USA. */ | |
14f9c5c9 AS |
21 | |
22 | /*----------------------------------------------------------------------*/ | |
23 | ||
24 | /* The converted version of this file is to be included in ada-exp.y, */ | |
25 | /* the Ada parser for gdb. The function yylex obtains characters from */ | |
26 | /* the global pointer lexptr. It returns a syntactic category for */ | |
27 | /* each successive token and places a semantic value into yylval */ | |
28 | /* (ada-lval), defined by the parser. */ | |
29 | ||
14f9c5c9 AS |
30 | DIG [0-9] |
31 | NUM10 ({DIG}({DIG}|_)*) | |
32 | HEXDIG [0-9a-f] | |
33 | NUM16 ({HEXDIG}({HEXDIG}|_)*) | |
34 | OCTDIG [0-7] | |
35 | LETTER [a-z_] | |
36 | ID ({LETTER}({LETTER}|{DIG})*|"<"{LETTER}({LETTER}|{DIG})*">") | |
37 | WHITE [ \t\n] | |
38 | TICK ("'"{WHITE}*) | |
39 | GRAPHIC [a-z0-9 #&'()*+,-./:;<>=_|!$%?@\[\]\\^`{}~] | |
40 | OPER ([-+*/=<>&]|"<="|">="|"**"|"/="|"and"|"or"|"xor"|"not"|"mod"|"rem"|"abs") | |
41 | ||
42 | EXP (e[+-]{NUM10}) | |
43 | POSEXP (e"+"?{NUM10}) | |
44 | ||
45 | %{ | |
4c4b4cd2 | 46 | |
14f9c5c9 AS |
47 | #define NUMERAL_WIDTH 256 |
48 | #define LONGEST_SIGN ((ULONGEST) 1 << (sizeof(LONGEST) * HOST_CHAR_BIT - 1)) | |
49 | ||
4c4b4cd2 PH |
50 | /* Temporary staging for numeric literals. */ |
51 | static char numbuf[NUMERAL_WIDTH]; | |
52 | static void canonicalizeNumeral (char *s1, const char *); | |
53 | static int processInt (const char *, const char *, const char *); | |
54 | static int processReal (const char *); | |
55 | static int processId (const char *, int); | |
56 | static int processAttribute (const char *); | |
57 | static int find_dot_all (const char *); | |
14f9c5c9 AS |
58 | |
59 | #undef YY_DECL | |
4c4b4cd2 | 60 | #define YY_DECL static int yylex ( void ) |
14f9c5c9 AS |
61 | |
62 | #undef YY_INPUT | |
63 | #define YY_INPUT(BUF, RESULT, MAX_SIZE) \ | |
64 | if ( *lexptr == '\000' ) \ | |
65 | (RESULT) = YY_NULL; \ | |
66 | else \ | |
67 | { \ | |
68 | *(BUF) = *lexptr; \ | |
69 | (RESULT) = 1; \ | |
70 | lexptr += 1; \ | |
71 | } | |
72 | ||
73 | static char *tempbuf = NULL; | |
74 | static int tempbufsize = 0; | |
75 | static int tempbuf_len; | |
4c4b4cd2 | 76 | static struct block *left_block_context; |
14f9c5c9 AS |
77 | |
78 | static void resize_tempbuf (unsigned int); | |
79 | ||
4c4b4cd2 | 80 | static void block_lookup (char *, char *); |
14f9c5c9 | 81 | |
4c4b4cd2 | 82 | static int name_lookup (char *, char *, int *, int); |
14f9c5c9 | 83 | |
4c4b4cd2 | 84 | static int find_dot_all (const char *); |
14f9c5c9 AS |
85 | |
86 | %} | |
87 | ||
7dc1ef8d PH |
88 | %option case-insensitive interactive nodefault |
89 | ||
14f9c5c9 AS |
90 | %s IN_STRING BEFORE_QUAL_QUOTE |
91 | ||
92 | %% | |
93 | ||
94 | {WHITE} { } | |
95 | ||
96 | "--".* { yyterminate(); } | |
97 | ||
4c4b4cd2 PH |
98 | {NUM10}{POSEXP} { |
99 | canonicalizeNumeral (numbuf, yytext); | |
14f9c5c9 AS |
100 | return processInt (NULL, numbuf, strrchr(numbuf, 'e')+1); |
101 | } | |
102 | ||
4c4b4cd2 PH |
103 | {NUM10} { |
104 | canonicalizeNumeral (numbuf, yytext); | |
14f9c5c9 AS |
105 | return processInt (NULL, numbuf, NULL); |
106 | } | |
107 | ||
108 | {NUM10}"#"{HEXDIG}({HEXDIG}|_)*"#"{POSEXP} { | |
109 | canonicalizeNumeral (numbuf, yytext); | |
110 | return processInt (numbuf, | |
4c4b4cd2 | 111 | strchr (numbuf, '#') + 1, |
14f9c5c9 AS |
112 | strrchr(numbuf, '#') + 1); |
113 | } | |
114 | ||
115 | {NUM10}"#"{HEXDIG}({HEXDIG}|_)*"#" { | |
116 | canonicalizeNumeral (numbuf, yytext); | |
117 | return processInt (numbuf, strchr (numbuf, '#') + 1, NULL); | |
118 | } | |
119 | ||
120 | "0x"{HEXDIG}+ { | |
121 | canonicalizeNumeral (numbuf, yytext+2); | |
122 | return processInt ("16#", numbuf, NULL); | |
123 | } | |
124 | ||
125 | ||
126 | {NUM10}"."{NUM10}{EXP} { | |
4c4b4cd2 | 127 | canonicalizeNumeral (numbuf, yytext); |
14f9c5c9 AS |
128 | return processReal (numbuf); |
129 | } | |
130 | ||
131 | {NUM10}"."{NUM10} { | |
4c4b4cd2 | 132 | canonicalizeNumeral (numbuf, yytext); |
14f9c5c9 AS |
133 | return processReal (numbuf); |
134 | } | |
135 | ||
136 | {NUM10}"#"{NUM16}"."{NUM16}"#"{EXP} { | |
137 | error ("Based real literals not implemented yet."); | |
138 | } | |
139 | ||
140 | {NUM10}"#"{NUM16}"."{NUM16}"#" { | |
141 | error ("Based real literals not implemented yet."); | |
142 | } | |
143 | ||
144 | <INITIAL>"'"({GRAPHIC}|\")"'" { | |
72d5681a | 145 | yylval.typed_val.type = type_char (); |
14f9c5c9 AS |
146 | yylval.typed_val.val = yytext[1]; |
147 | return CHARLIT; | |
148 | } | |
149 | ||
150 | <INITIAL>"'[\""{HEXDIG}{2}"\"]'" { | |
151 | int v; | |
72d5681a | 152 | yylval.typed_val.type = type_char (); |
14f9c5c9 AS |
153 | sscanf (yytext+3, "%2x", &v); |
154 | yylval.typed_val.val = v; | |
155 | return CHARLIT; | |
156 | } | |
157 | ||
4c4b4cd2 | 158 | <INITIAL>\" { |
14f9c5c9 AS |
159 | tempbuf_len = 0; |
160 | BEGIN IN_STRING; | |
161 | } | |
162 | ||
163 | <IN_STRING>{GRAPHIC}*\" { | |
164 | resize_tempbuf (yyleng+tempbuf_len); | |
165 | strncpy (tempbuf+tempbuf_len, yytext, yyleng-1); | |
166 | tempbuf_len += yyleng-1; | |
167 | yylval.sval.ptr = tempbuf; | |
168 | yylval.sval.length = tempbuf_len; | |
169 | BEGIN INITIAL; | |
170 | return STRING; | |
171 | } | |
172 | ||
173 | <IN_STRING>{GRAPHIC}*"[\""{HEXDIG}{2}"\"]" { | |
174 | int n; | |
175 | resize_tempbuf (yyleng-5+tempbuf_len+1); | |
176 | strncpy (tempbuf+tempbuf_len, yytext, yyleng-6); | |
177 | sscanf(yytext+yyleng-4, "%2x", &n); | |
178 | tempbuf[yyleng-6+tempbuf_len] = (char) n; | |
179 | tempbuf_len += yyleng-5; | |
180 | } | |
181 | ||
182 | <IN_STRING>{GRAPHIC}*"[\"\"\"]" { | |
183 | int n; | |
184 | resize_tempbuf (yyleng-4+tempbuf_len+1); | |
185 | strncpy (tempbuf+tempbuf_len, yytext, yyleng-6); | |
186 | tempbuf[yyleng-5+tempbuf_len] = '"'; | |
187 | tempbuf_len += yyleng-4; | |
188 | } | |
189 | ||
4c4b4cd2 PH |
190 | if { |
191 | while (*lexptr != 'i' && *lexptr != 'I') | |
192 | lexptr -= 1; | |
193 | yyrestart(NULL); | |
14f9c5c9 AS |
194 | return 0; |
195 | } | |
196 | ||
197 | /* ADA KEYWORDS */ | |
198 | ||
199 | abs { return ABS; } | |
200 | and { return _AND_; } | |
201 | else { return ELSE; } | |
202 | in { return IN; } | |
203 | mod { return MOD; } | |
204 | new { return NEW; } | |
205 | not { return NOT; } | |
206 | null { return NULL_PTR; } | |
207 | or { return OR; } | |
208 | rem { return REM; } | |
209 | then { return THEN; } | |
210 | xor { return XOR; } | |
211 | ||
212 | /* ATTRIBUTES */ | |
213 | ||
214 | {TICK}[a-zA-Z][a-zA-Z]+ { return processAttribute (yytext+1); } | |
215 | ||
216 | /* PUNCTUATION */ | |
217 | ||
218 | "=>" { return ARROW; } | |
219 | ".." { return DOTDOT; } | |
220 | "**" { return STARSTAR; } | |
221 | ":=" { return ASSIGN; } | |
222 | "/=" { return NOTEQUAL; } | |
223 | "<=" { return LEQ; } | |
224 | ">=" { return GEQ; } | |
225 | ||
226 | <BEFORE_QUAL_QUOTE>"'" { BEGIN INITIAL; return '\''; } | |
227 | ||
228 | [-&*+./:<>=|;\[\]] { return yytext[0]; } | |
229 | ||
230 | "," { if (paren_depth == 0 && comma_terminates) | |
231 | { | |
232 | lexptr -= 1; | |
233 | yyrestart(NULL); | |
234 | return 0; | |
235 | } | |
4c4b4cd2 | 236 | else |
14f9c5c9 AS |
237 | return ','; |
238 | } | |
239 | ||
240 | "(" { paren_depth += 1; return '('; } | |
4c4b4cd2 | 241 | ")" { if (paren_depth == 0) |
14f9c5c9 AS |
242 | { |
243 | lexptr -= 1; | |
244 | yyrestart(NULL); | |
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} { |
14f9c5c9 | 257 | processId (yytext+1, yyleng-1); |
4c4b4cd2 | 258 | return DOT_ID; |
14f9c5c9 AS |
259 | } |
260 | ||
4c4b4cd2 | 261 | {ID}({WHITE}*"."{WHITE}*({ID}|\"{OPER}\"))*(" "*"'")? { |
14f9c5c9 AS |
262 | int all_posn = find_dot_all (yytext); |
263 | int token_type, segments, k; | |
264 | int quote_follows; | |
265 | ||
4c4b4cd2 | 266 | if (all_posn == -1 && yytext[yyleng-1] == '\'') |
14f9c5c9 AS |
267 | { |
268 | quote_follows = 1; | |
4c4b4cd2 PH |
269 | do { |
270 | yyless (yyleng-1); | |
14f9c5c9 AS |
271 | } while (yytext[yyleng-1] == ' '); |
272 | } | |
273 | else | |
4c4b4cd2 PH |
274 | quote_follows = 0; |
275 | ||
14f9c5c9 AS |
276 | if (all_posn >= 0) |
277 | yyless (all_posn); | |
278 | processId(yytext, yyleng); | |
4c4b4cd2 PH |
279 | segments = name_lookup (ada_encode (yylval.ssym.stoken.ptr), |
280 | yylval.ssym.stoken.ptr, | |
281 | &token_type, | |
282 | MAX_RENAMING_CHAIN_LENGTH); | |
14f9c5c9 AS |
283 | left_block_context = NULL; |
284 | for (k = yyleng; segments > 0 && k > 0; k -= 1) | |
285 | { | |
286 | if (yytext[k-1] == '.') | |
287 | segments -= 1; | |
288 | quote_follows = 0; | |
289 | } | |
290 | if (k <= 0) | |
291 | error ("confused by name %s", yytext); | |
292 | yyless (k); | |
4c4b4cd2 | 293 | if (quote_follows) |
14f9c5c9 AS |
294 | BEGIN BEFORE_QUAL_QUOTE; |
295 | return token_type; | |
296 | } | |
297 | ||
298 | /* GDB EXPRESSION CONSTRUCTS */ | |
299 | ||
300 | ||
301 | "'"[^']+"'"{WHITE}*:: { | |
302 | processId(yytext, yyleng-2); | |
303 | block_lookup (yylval.ssym.stoken.ptr, yylval.ssym.stoken.ptr); | |
304 | return BLOCKNAME; | |
305 | } | |
306 | ||
4c4b4cd2 | 307 | {ID}({WHITE}*"."{WHITE}*({ID}|\"{OPER}\"))*{WHITE}*:: { |
14f9c5c9 | 308 | processId(yytext, yyleng-2); |
4c4b4cd2 | 309 | block_lookup (ada_encode (yylval.ssym.stoken.ptr), |
14f9c5c9 AS |
310 | yylval.ssym.stoken.ptr); |
311 | return BLOCKNAME; | |
312 | } | |
313 | ||
314 | [{}@] { return yytext[0]; } | |
315 | ||
14f9c5c9 AS |
316 | /* REGISTERS AND GDB CONVENIENCE VARIABLES */ |
317 | ||
4c4b4cd2 | 318 | "$"({LETTER}|{DIG}|"$")* { |
14f9c5c9 AS |
319 | yylval.sval.ptr = yytext; |
320 | yylval.sval.length = yyleng; | |
4c4b4cd2 | 321 | return SPECIAL_VARIABLE; |
14f9c5c9 AS |
322 | } |
323 | ||
324 | /* CATCH-ALL ERROR CASE */ | |
325 | ||
326 | . { error ("Invalid character '%s' in expression.", yytext); } | |
327 | %% | |
328 | ||
329 | #include <ctype.h> | |
19c1ef65 | 330 | #include "gdb_string.h" |
14f9c5c9 AS |
331 | |
332 | /* Initialize the lexer for processing new expression */ | |
333 | void | |
4c4b4cd2 | 334 | lexer_init (FILE *inp) |
14f9c5c9 AS |
335 | { |
336 | BEGIN INITIAL; | |
337 | yyrestart (inp); | |
338 | } | |
339 | ||
340 | ||
4c4b4cd2 | 341 | /* Make sure that tempbuf points at an array at least N characters long. */ |
14f9c5c9 AS |
342 | |
343 | static void | |
4c4b4cd2 | 344 | resize_tempbuf (unsigned int n) |
14f9c5c9 AS |
345 | { |
346 | if (tempbufsize < n) | |
347 | { | |
348 | tempbufsize = (n+63) & ~63; | |
34a17005 | 349 | tempbuf = xrealloc (tempbuf, tempbufsize); |
14f9c5c9 AS |
350 | } |
351 | } | |
4c4b4cd2 PH |
352 | |
353 | /* Copy S2 to S1, removing all underscores, and downcasing all letters. */ | |
14f9c5c9 AS |
354 | |
355 | static void | |
4c4b4cd2 | 356 | canonicalizeNumeral (char *s1, const char *s2) |
14f9c5c9 | 357 | { |
4c4b4cd2 | 358 | for (; *s2 != '\000'; s2 += 1) |
14f9c5c9 AS |
359 | { |
360 | if (*s2 != '_') | |
361 | { | |
362 | *s1 = tolower(*s2); | |
363 | s1 += 1; | |
364 | } | |
365 | } | |
366 | s1[0] = '\000'; | |
367 | } | |
368 | ||
369 | #define HIGH_BYTE_POSN ((sizeof (ULONGEST) - 1) * HOST_CHAR_BIT) | |
370 | ||
4c4b4cd2 | 371 | /* True (non-zero) iff DIGIT is a valid digit in radix BASE, |
14f9c5c9 AS |
372 | where 2 <= BASE <= 16. */ |
373 | ||
374 | static int | |
4c4b4cd2 | 375 | is_digit_in_base (unsigned char digit, int base) |
14f9c5c9 AS |
376 | { |
377 | if (!isxdigit (digit)) | |
378 | return 0; | |
379 | if (base <= 10) | |
380 | return (isdigit (digit) && digit < base + '0'); | |
4c4b4cd2 | 381 | else |
14f9c5c9 AS |
382 | return (isdigit (digit) || tolower (digit) < base - 10 + 'a'); |
383 | } | |
384 | ||
385 | static int | |
4c4b4cd2 | 386 | digit_to_int (unsigned char c) |
14f9c5c9 AS |
387 | { |
388 | if (isdigit (c)) | |
389 | return c - '0'; | |
390 | else | |
391 | return tolower (c) - 'a' + 10; | |
392 | } | |
393 | ||
4c4b4cd2 | 394 | /* As for strtoul, but for ULONGEST results. */ |
14f9c5c9 | 395 | ULONGEST |
4c4b4cd2 | 396 | strtoulst (const char *num, const char **trailer, int base) |
14f9c5c9 AS |
397 | { |
398 | unsigned int high_part; | |
399 | ULONGEST result; | |
400 | int i; | |
401 | unsigned char lim; | |
402 | ||
403 | if (base < 2 || base > 16) | |
404 | { | |
405 | errno = EINVAL; | |
406 | return 0; | |
407 | } | |
408 | lim = base - 1 + '0'; | |
409 | ||
410 | result = high_part = 0; | |
411 | for (i = 0; is_digit_in_base (num[i], base); i += 1) | |
412 | { | |
413 | result = result*base + digit_to_int (num[i]); | |
414 | high_part = high_part*base + (unsigned int) (result >> HIGH_BYTE_POSN); | |
415 | result &= ((ULONGEST) 1 << HIGH_BYTE_POSN) - 1; | |
4c4b4cd2 | 416 | if (high_part > 0xff) |
14f9c5c9 AS |
417 | { |
418 | errno = ERANGE; | |
419 | result = high_part = 0; | |
420 | break; | |
421 | } | |
422 | } | |
423 | ||
424 | if (trailer != NULL) | |
425 | *trailer = &num[i]; | |
426 | ||
427 | return result + ((ULONGEST) high_part << HIGH_BYTE_POSN); | |
428 | } | |
429 | ||
430 | ||
431 | ||
432 | /* Interprets the prefix of NUM that consists of digits of the given BASE | |
433 | as an integer of that BASE, with the string EXP as an exponent. | |
434 | Puts value in yylval, and returns INT, if the string is valid. Causes | |
4c4b4cd2 PH |
435 | an error if the number is improperly formated. BASE, if NULL, defaults |
436 | to "10", and EXP to "1". The EXP does not contain a leading 'e' or 'E'. */ | |
14f9c5c9 AS |
437 | |
438 | static int | |
4c4b4cd2 | 439 | processInt (const char *base0, const char *num0, const char *exp0) |
14f9c5c9 AS |
440 | { |
441 | ULONGEST result; | |
442 | long exp; | |
443 | int base; | |
444 | ||
4c4b4cd2 | 445 | char *trailer; |
14f9c5c9 AS |
446 | |
447 | if (base0 == NULL) | |
448 | base = 10; | |
449 | else | |
4c4b4cd2 PH |
450 | { |
451 | base = strtol (base0, (char **) NULL, 10); | |
14f9c5c9 AS |
452 | if (base < 2 || base > 16) |
453 | error ("Invalid base: %d.", base); | |
454 | } | |
455 | ||
456 | if (exp0 == NULL) | |
457 | exp = 0; | |
458 | else | |
4c4b4cd2 | 459 | exp = strtol(exp0, (char **) NULL, 10); |
14f9c5c9 AS |
460 | |
461 | errno = 0; | |
4c4b4cd2 | 462 | result = strtoulst (num0, (const char **) &trailer, base); |
14f9c5c9 AS |
463 | if (errno == ERANGE) |
464 | error ("Integer literal out of range"); | |
465 | if (isxdigit(*trailer)) | |
466 | error ("Invalid digit `%c' in based literal", *trailer); | |
467 | ||
4c4b4cd2 | 468 | while (exp > 0) |
14f9c5c9 AS |
469 | { |
470 | if (result > (ULONG_MAX / base)) | |
471 | error ("Integer literal out of range"); | |
472 | result *= base; | |
473 | exp -= 1; | |
474 | } | |
4c4b4cd2 | 475 | |
14f9c5c9 | 476 | if ((result >> (TARGET_INT_BIT-1)) == 0) |
72d5681a | 477 | yylval.typed_val.type = type_int (); |
14f9c5c9 | 478 | else if ((result >> (TARGET_LONG_BIT-1)) == 0) |
72d5681a | 479 | yylval.typed_val.type = type_long (); |
14f9c5c9 AS |
480 | else if (((result >> (TARGET_LONG_BIT-1)) >> 1) == 0) |
481 | { | |
482 | /* We have a number representable as an unsigned integer quantity. | |
4c4b4cd2 | 483 | For consistency with the C treatment, we will treat it as an |
14f9c5c9 | 484 | anonymous modular (unsigned) quantity. Alas, the types are such |
4c4b4cd2 | 485 | that we need to store .val as a signed quantity. Sorry |
14f9c5c9 AS |
486 | for the mess, but C doesn't officially guarantee that a simple |
487 | assignment does the trick (no, it doesn't; read the reference manual). | |
488 | */ | |
489 | yylval.typed_val.type = builtin_type_unsigned_long; | |
490 | if (result & LONGEST_SIGN) | |
4c4b4cd2 PH |
491 | yylval.typed_val.val = |
492 | (LONGEST) (result & ~LONGEST_SIGN) | |
14f9c5c9 AS |
493 | - (LONGEST_SIGN>>1) - (LONGEST_SIGN>>1); |
494 | else | |
495 | yylval.typed_val.val = (LONGEST) result; | |
496 | return INT; | |
497 | } | |
4c4b4cd2 | 498 | else |
72d5681a | 499 | yylval.typed_val.type = type_long_long (); |
14f9c5c9 AS |
500 | |
501 | yylval.typed_val.val = (LONGEST) result; | |
502 | return INT; | |
503 | } | |
504 | ||
4c4b4cd2 PH |
505 | #if defined (PRINTF_HAS_LONG_DOUBLE) |
506 | # undef PRINTF_HAS_LONG_DOUBLE | |
507 | # define PRINTF_HAS_LONG_DOUBLE 1 | |
508 | #else | |
509 | # define PRINTF_HAS_LONG_DOUBLE 0 | |
510 | #endif | |
511 | ||
14f9c5c9 | 512 | static int |
4c4b4cd2 | 513 | processReal (const char *num0) |
14f9c5c9 | 514 | { |
4c4b4cd2 PH |
515 | #if defined (PRINTF_HAS_LONG_DOUBLE) |
516 | if (sizeof (DOUBLEST) > sizeof (double)) | |
517 | sscanf (num0, "%Lg", &yylval.typed_val_float.dval); | |
14f9c5c9 | 518 | else |
4c4b4cd2 | 519 | #endif |
14f9c5c9 | 520 | { |
14f9c5c9 AS |
521 | double temp; |
522 | sscanf (num0, "%lg", &temp); | |
523 | yylval.typed_val_float.dval = temp; | |
14f9c5c9 AS |
524 | } |
525 | ||
72d5681a | 526 | yylval.typed_val_float.type = type_float (); |
14f9c5c9 | 527 | if (sizeof(DOUBLEST) >= TARGET_DOUBLE_BIT / TARGET_CHAR_BIT) |
72d5681a | 528 | yylval.typed_val_float.type = type_double (); |
14f9c5c9 | 529 | if (sizeof(DOUBLEST) >= TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT) |
72d5681a | 530 | yylval.typed_val_float.type = type_long_double (); |
14f9c5c9 AS |
531 | |
532 | return FLOAT; | |
533 | } | |
534 | ||
535 | static int | |
4c4b4cd2 | 536 | processId (const char *name0, int len) |
14f9c5c9 | 537 | { |
4c4b4cd2 | 538 | char *name = obstack_alloc (&temp_parse_space, len + 11); |
14f9c5c9 | 539 | int i0, i; |
4c4b4cd2 | 540 | |
14f9c5c9 AS |
541 | while (len > 0 && isspace (name0[len-1])) |
542 | len -= 1; | |
543 | i = i0 = 0; | |
4c4b4cd2 | 544 | while (i0 < len) |
14f9c5c9 AS |
545 | { |
546 | if (isalnum (name0[i0])) | |
547 | { | |
548 | name[i] = tolower (name0[i0]); | |
549 | i += 1; i0 += 1; | |
550 | } | |
4c4b4cd2 | 551 | else switch (name0[i0]) |
14f9c5c9 AS |
552 | { |
553 | default: | |
554 | name[i] = name0[i0]; | |
555 | i += 1; i0 += 1; | |
556 | break; | |
557 | case ' ': case '\t': | |
558 | i0 += 1; | |
559 | break; | |
560 | case '\'': | |
561 | i0 += 1; | |
562 | while (i0 < len && name0[i0] != '\'') | |
563 | { | |
564 | name[i] = name0[i0]; | |
565 | i += 1; i0 += 1; | |
566 | } | |
567 | i0 += 1; | |
568 | break; | |
569 | case '<': | |
570 | i0 += 1; | |
571 | while (i0 < len && name0[i0] != '>') | |
572 | { | |
573 | name[i] = name0[i0]; | |
574 | i += 1; i0 += 1; | |
575 | } | |
576 | i0 += 1; | |
577 | break; | |
578 | } | |
579 | } | |
580 | name[i] = '\000'; | |
581 | ||
582 | yylval.ssym.sym = NULL; | |
583 | yylval.ssym.stoken.ptr = name; | |
584 | yylval.ssym.stoken.length = i; | |
585 | return NAME; | |
586 | } | |
587 | ||
4c4b4cd2 PH |
588 | static void |
589 | block_lookup (char *name, char *err_name) | |
14f9c5c9 | 590 | { |
4c4b4cd2 | 591 | struct ada_symbol_info *syms; |
14f9c5c9 AS |
592 | int nsyms; |
593 | struct symtab *symtab; | |
594 | nsyms = ada_lookup_symbol_list (name, left_block_context, | |
4c4b4cd2 | 595 | VAR_DOMAIN, &syms); |
14f9c5c9 | 596 | if (left_block_context == NULL && |
4c4b4cd2 | 597 | (nsyms == 0 || SYMBOL_CLASS (syms[0].sym) != LOC_BLOCK)) |
14f9c5c9 AS |
598 | symtab = lookup_symtab (name); |
599 | else | |
600 | symtab = NULL; | |
601 | ||
602 | if (symtab != NULL) | |
603 | left_block_context = yylval.bval = | |
604 | BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK); | |
4c4b4cd2 | 605 | else if (nsyms == 0 || SYMBOL_CLASS (syms[0].sym) != LOC_BLOCK) |
14f9c5c9 AS |
606 | { |
607 | if (left_block_context == NULL) | |
608 | error ("No file or function \"%s\".", err_name); | |
609 | else | |
610 | error ("No function \"%s\" in specified context.", err_name); | |
611 | } | |
4c4b4cd2 | 612 | else |
14f9c5c9 | 613 | { |
4c4b4cd2 | 614 | left_block_context = yylval.bval = SYMBOL_BLOCK_VALUE (syms[0].sym); |
14f9c5c9 AS |
615 | if (nsyms > 1) |
616 | warning ("Function name \"%s\" ambiguous here", err_name); | |
617 | } | |
618 | } | |
619 | ||
4c4b4cd2 | 620 | /* Look up NAME0 (assumed to be encoded) as a name in VAR_DOMAIN, |
14f9c5c9 | 621 | setting *TOKEN_TYPE to NAME or TYPENAME, depending on what is |
4c4b4cd2 | 622 | found. Try first the entire name, then the name without the last |
14f9c5c9 | 623 | segment (i.e., after the last .id), etc., and return the number of |
4c4b4cd2 PH |
624 | segments that had to be removed to get a match. Try only the full |
625 | name if it starts with "standard__". Calls error if no | |
14f9c5c9 | 626 | matches are found, using ERR_NAME in any error message. When |
4c4b4cd2 PH |
627 | exactly one symbol match is found, it is placed in yylval. When |
628 | the symbol is a renaming, follow at most DEPTH steps to find the | |
629 | ultimate definition; cause error if depth exceeded. */ | |
630 | ||
14f9c5c9 | 631 | static int |
4c4b4cd2 | 632 | name_lookup (char *name0, char *err_name, int *token_type, int depth) |
14f9c5c9 | 633 | { |
4c4b4cd2 PH |
634 | struct ada_symbol_info *syms; |
635 | struct type *type; | |
14f9c5c9 | 636 | int len0 = strlen (name0); |
4c4b4cd2 | 637 | char *name = obsavestring (name0, len0, &temp_parse_space); |
14f9c5c9 AS |
638 | int nsyms; |
639 | int segments; | |
4c4b4cd2 PH |
640 | |
641 | if (depth <= 0) | |
642 | error ("Could not find renamed symbol \"%s\"", err_name); | |
643 | ||
14f9c5c9 AS |
644 | yylval.ssym.stoken.ptr = name; |
645 | yylval.ssym.stoken.length = strlen (name); | |
646 | for (segments = 0; ; segments += 1) | |
647 | { | |
4c4b4cd2 | 648 | struct type *preferred_type; |
14f9c5c9 AS |
649 | int i, preferred_index; |
650 | ||
4c4b4cd2 PH |
651 | if (left_block_context == NULL) |
652 | nsyms = ada_lookup_symbol_list (name, expression_context_block, | |
653 | VAR_DOMAIN, &syms); | |
14f9c5c9 | 654 | else |
4c4b4cd2 PH |
655 | nsyms = ada_lookup_symbol_list (name, left_block_context, |
656 | VAR_DOMAIN, &syms); | |
657 | ||
658 | ||
659 | /* Check for a type renaming. */ | |
14f9c5c9 | 660 | |
4c4b4cd2 PH |
661 | if (nsyms == 1 && !ada_is_object_renaming (syms[0].sym)) |
662 | { | |
663 | struct symbol *renaming_sym = | |
664 | ada_find_renaming_symbol (SYMBOL_LINKAGE_NAME (syms[0].sym), | |
665 | syms[0].block); | |
666 | ||
667 | if (renaming_sym != NULL) | |
668 | syms[0].sym = renaming_sym; | |
669 | } | |
670 | ||
671 | /* Check for a type definition. */ | |
14f9c5c9 AS |
672 | |
673 | /* Look for a symbol that doesn't denote void. This is (I think) a */ | |
4c4b4cd2 | 674 | /* temporary kludge to get around problems in GNAT output. */ |
14f9c5c9 AS |
675 | preferred_index = -1; preferred_type = NULL; |
676 | for (i = 0; i < nsyms; i += 1) | |
4c4b4cd2 | 677 | switch (SYMBOL_CLASS (syms[i].sym)) |
14f9c5c9 AS |
678 | { |
679 | case LOC_TYPEDEF: | |
4c4b4cd2 | 680 | if (ada_prefer_type (SYMBOL_TYPE (syms[i].sym), preferred_type)) |
14f9c5c9 AS |
681 | { |
682 | preferred_index = i; | |
4c4b4cd2 | 683 | preferred_type = SYMBOL_TYPE (syms[i].sym); |
14f9c5c9 AS |
684 | } |
685 | break; | |
686 | case LOC_REGISTER: | |
687 | case LOC_ARG: | |
688 | case LOC_REF_ARG: | |
689 | case LOC_REGPARM: | |
690 | case LOC_REGPARM_ADDR: | |
691 | case LOC_LOCAL: | |
692 | case LOC_LOCAL_ARG: | |
693 | case LOC_BASEREG: | |
694 | case LOC_BASEREG_ARG: | |
4c4b4cd2 PH |
695 | case LOC_COMPUTED: |
696 | case LOC_COMPUTED_ARG: | |
14f9c5c9 AS |
697 | goto NotType; |
698 | default: | |
699 | break; | |
700 | } | |
701 | if (preferred_type != NULL) | |
702 | { | |
4c4b4cd2 PH |
703 | if (TYPE_CODE (preferred_type) == TYPE_CODE_VOID) |
704 | error ("`%s' matches only void type name(s)", | |
705 | ada_decode (name)); | |
706 | else if (ada_is_object_renaming (syms[preferred_index].sym)) | |
14f9c5c9 | 707 | { |
4c4b4cd2 | 708 | yylval.ssym.sym = syms[preferred_index].sym; |
14f9c5c9 AS |
709 | *token_type = OBJECT_RENAMING; |
710 | return segments; | |
4c4b4cd2 PH |
711 | } |
712 | else if (ada_renaming_type (SYMBOL_TYPE (syms[preferred_index].sym)) | |
14f9c5c9 AS |
713 | != NULL) |
714 | { | |
715 | int result; | |
4c4b4cd2 PH |
716 | char *renaming |
717 | = ada_simple_renamed_entity (syms[preferred_index].sym); | |
718 | char *new_name | |
719 | = (char *) obstack_alloc (&temp_parse_space, | |
720 | strlen (renaming) + len0 | |
721 | - yylval.ssym.stoken.length + 1); | |
14f9c5c9 | 722 | strcpy (new_name, renaming); |
19c1ef65 | 723 | xfree (renaming); |
14f9c5c9 | 724 | strcat (new_name, name0 + yylval.ssym.stoken.length); |
4c4b4cd2 PH |
725 | result = name_lookup (new_name, err_name, token_type, depth - 1); |
726 | if (result > segments) | |
14f9c5c9 AS |
727 | error ("Confused by renamed symbol."); |
728 | return result; | |
729 | } | |
730 | else if (segments == 0) | |
731 | { | |
732 | yylval.tval = preferred_type; | |
733 | *token_type = TYPENAME; | |
734 | return 0; | |
4c4b4cd2 | 735 | } |
14f9c5c9 AS |
736 | } |
737 | ||
738 | if (segments == 0) | |
739 | { | |
54a5b07d AC |
740 | type = language_lookup_primitive_type_by_name (current_language, |
741 | current_gdbarch, | |
742 | name); | |
4c4b4cd2 | 743 | if (type == NULL && strcmp ("system__address", name) == 0) |
72d5681a | 744 | type = type_system_address (); |
14f9c5c9 AS |
745 | if (type != NULL) |
746 | { | |
4c4b4cd2 PH |
747 | /* First check to see if we have a regular definition of this |
748 | type that just didn't happen to have been read yet. */ | |
749 | int ntypes; | |
750 | struct symbol *sym; | |
751 | char *expanded_name = | |
752 | (char *) alloca (strlen (name) + sizeof ("standard__")); | |
753 | strcpy (expanded_name, "standard__"); | |
754 | strcat (expanded_name, name); | |
755 | sym = ada_lookup_symbol (expanded_name, NULL, | |
756 | VAR_DOMAIN, NULL, NULL); | |
757 | if (sym != NULL && SYMBOL_CLASS (sym) == LOC_TYPEDEF) | |
758 | type = SYMBOL_TYPE (sym); | |
759 | ||
14f9c5c9 AS |
760 | yylval.tval = type; |
761 | *token_type = TYPENAME; | |
762 | return 0; | |
763 | } | |
764 | } | |
765 | ||
766 | NotType: | |
4c4b4cd2 | 767 | if (nsyms == 1) |
14f9c5c9 AS |
768 | { |
769 | *token_type = NAME; | |
4c4b4cd2 | 770 | yylval.ssym.sym = syms[0].sym; |
14f9c5c9 | 771 | yylval.ssym.msym = NULL; |
4c4b4cd2 | 772 | yylval.ssym.block = syms[0].block; |
14f9c5c9 AS |
773 | return segments; |
774 | } | |
775 | else if (nsyms == 0) { | |
776 | int i; | |
4c4b4cd2 | 777 | yylval.ssym.msym = ada_lookup_simple_minsym (name); |
14f9c5c9 AS |
778 | if (yylval.ssym.msym != NULL) |
779 | { | |
780 | yylval.ssym.sym = NULL; | |
781 | yylval.ssym.block = NULL; | |
782 | *token_type = NAME; | |
783 | return segments; | |
784 | } | |
785 | ||
4c4b4cd2 PH |
786 | if (segments == 0 |
787 | && strncmp (name, "standard__", sizeof ("standard__") - 1) == 0) | |
788 | error ("No definition of \"%s\" found.", err_name); | |
789 | ||
14f9c5c9 AS |
790 | for (i = yylval.ssym.stoken.length - 1; i > 0; i -= 1) |
791 | { | |
792 | if (name[i] == '.') | |
4c4b4cd2 | 793 | { |
14f9c5c9 AS |
794 | name[i] = '\0'; |
795 | yylval.ssym.stoken.length = i; | |
796 | break; | |
797 | } | |
798 | else if (name[i] == '_' && name[i-1] == '_') | |
799 | { | |
800 | i -= 1; | |
801 | name[i] = '\0'; | |
802 | yylval.ssym.stoken.length = i; | |
803 | break; | |
804 | } | |
805 | } | |
4c4b4cd2 | 806 | if (i <= 0) |
14f9c5c9 AS |
807 | { |
808 | if (!have_full_symbols () && !have_partial_symbols () | |
809 | && left_block_context == NULL) | |
810 | error ("No symbol table is loaded. Use the \"file\" command."); | |
811 | if (left_block_context == NULL) | |
4c4b4cd2 | 812 | error ("No definition of \"%s\" in current context.", |
14f9c5c9 AS |
813 | err_name); |
814 | else | |
4c4b4cd2 | 815 | error ("No definition of \"%s\" in specified context.", |
14f9c5c9 AS |
816 | err_name); |
817 | } | |
818 | } | |
4c4b4cd2 | 819 | else |
14f9c5c9 AS |
820 | { |
821 | *token_type = NAME; | |
822 | yylval.ssym.sym = NULL; | |
823 | yylval.ssym.msym = NULL; | |
824 | if (left_block_context == NULL) | |
825 | yylval.ssym.block = expression_context_block; | |
826 | else | |
827 | yylval.ssym.block = left_block_context; | |
828 | return segments; | |
829 | } | |
830 | } | |
831 | } | |
832 | ||
833 | /* Returns the position within STR of the '.' in a | |
4c4b4cd2 | 834 | '.{WHITE}*all' component of a dotted name, or -1 if there is none. */ |
14f9c5c9 | 835 | static int |
4c4b4cd2 | 836 | find_dot_all (const char *str) |
14f9c5c9 AS |
837 | { |
838 | int i; | |
839 | for (i = 0; str[i] != '\000'; i += 1) | |
840 | { | |
841 | if (str[i] == '.') | |
842 | { | |
843 | int i0 = i; | |
4c4b4cd2 | 844 | do |
14f9c5c9 AS |
845 | i += 1; |
846 | while (isspace (str[i])); | |
847 | if (strcmp (str+i, "all") == 0 | |
848 | && ! isalnum (str[i+3]) && str[i+3] != '_') | |
849 | return i0; | |
850 | } | |
851 | } | |
852 | return -1; | |
4c4b4cd2 | 853 | } |
14f9c5c9 AS |
854 | |
855 | /* Returns non-zero iff string SUBSEQ matches a subsequence of STR, ignoring | |
4c4b4cd2 | 856 | case. */ |
14f9c5c9 AS |
857 | |
858 | static int | |
4c4b4cd2 | 859 | subseqMatch (const char *subseq, const char *str) |
14f9c5c9 AS |
860 | { |
861 | if (subseq[0] == '\0') | |
862 | return 1; | |
863 | else if (str[0] == '\0') | |
864 | return 0; | |
865 | else if (tolower (subseq[0]) == tolower (str[0])) | |
866 | return subseqMatch (subseq+1, str+1) || subseqMatch (subseq, str+1); | |
867 | else | |
868 | return subseqMatch (subseq, str+1); | |
869 | } | |
14f9c5c9 | 870 | |
4c4b4cd2 PH |
871 | |
872 | static struct { const char *name; int code; } | |
14f9c5c9 AS |
873 | attributes[] = { |
874 | { "address", TICK_ADDRESS }, | |
875 | { "unchecked_access", TICK_ACCESS }, | |
876 | { "unrestricted_access", TICK_ACCESS }, | |
877 | { "access", TICK_ACCESS }, | |
878 | { "first", TICK_FIRST }, | |
879 | { "last", TICK_LAST }, | |
880 | { "length", TICK_LENGTH }, | |
881 | { "max", TICK_MAX }, | |
882 | { "min", TICK_MIN }, | |
883 | { "modulus", TICK_MODULUS }, | |
884 | { "pos", TICK_POS }, | |
885 | { "range", TICK_RANGE }, | |
886 | { "size", TICK_SIZE }, | |
887 | { "tag", TICK_TAG }, | |
888 | { "val", TICK_VAL }, | |
889 | { NULL, -1 } | |
890 | }; | |
891 | ||
892 | /* Return the syntactic code corresponding to the attribute name or | |
893 | abbreviation STR. */ | |
894 | ||
895 | static int | |
4c4b4cd2 | 896 | processAttribute (const char *str) |
14f9c5c9 AS |
897 | { |
898 | int i, k; | |
899 | ||
900 | for (i = 0; attributes[i].code != -1; i += 1) | |
901 | if (strcasecmp (str, attributes[i].name) == 0) | |
902 | return attributes[i].code; | |
903 | ||
904 | for (i = 0, k = -1; attributes[i].code != -1; i += 1) | |
4c4b4cd2 | 905 | if (subseqMatch (str, attributes[i].name)) |
14f9c5c9 AS |
906 | { |
907 | if (k == -1) | |
908 | k = i; | |
4c4b4cd2 | 909 | else |
14f9c5c9 AS |
910 | error ("ambiguous attribute name: `%s'", str); |
911 | } | |
912 | if (k == -1) | |
913 | error ("unrecognized attribute: `%s'", str); | |
914 | ||
915 | return attributes[k].code; | |
916 | } | |
917 | ||
918 | int | |
4c4b4cd2 | 919 | yywrap(void) |
14f9c5c9 AS |
920 | { |
921 | return 1; | |
922 | } | |
23485554 PH |
923 | |
924 | /* Dummy definition to suppress warnings about unused static definitions. */ | |
925 | typedef void (*dummy_function) (); | |
926 | dummy_function ada_flex_use[] = | |
927 | { | |
375c0479 | 928 | (dummy_function) yyunput |
23485554 | 929 | }; |