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