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