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