]>
Commit | Line | Data |
---|---|---|
14f9c5c9 AS |
1 | /* FLEX lexer for Ada expressions, for GDB. |
2 | Copyright (C) 1994, 1997, 2000 | |
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 | %{ | |
48 | #define NUMERAL_WIDTH 256 | |
49 | #define LONGEST_SIGN ((ULONGEST) 1 << (sizeof(LONGEST) * HOST_CHAR_BIT - 1)) | |
50 | ||
51 | /* Temporary staging for numeric literals. */ | |
52 | static char numbuf[NUMERAL_WIDTH]; | |
53 | static void canonicalizeNumeral (char* s1, const char*); | |
54 | static int processInt (const char*, const char*, const char*); | |
55 | static int processReal (const char*); | |
56 | static int processId (const char*, int); | |
57 | static int processAttribute (const char*); | |
58 | static int find_dot_all (const char*); | |
59 | ||
60 | #undef YY_DECL | |
61 | #define YY_DECL static int yylex ( void ) | |
62 | ||
63 | #undef YY_INPUT | |
64 | #define YY_INPUT(BUF, RESULT, MAX_SIZE) \ | |
65 | if ( *lexptr == '\000' ) \ | |
66 | (RESULT) = YY_NULL; \ | |
67 | else \ | |
68 | { \ | |
69 | *(BUF) = *lexptr; \ | |
70 | (RESULT) = 1; \ | |
71 | lexptr += 1; \ | |
72 | } | |
73 | ||
74 | static char *tempbuf = NULL; | |
75 | static int tempbufsize = 0; | |
76 | static int tempbuf_len; | |
77 | static struct block* left_block_context; | |
78 | ||
79 | static void resize_tempbuf (unsigned int); | |
80 | ||
81 | static void block_lookup (char*, char*); | |
82 | ||
83 | static int name_lookup (char*, char*, int*); | |
84 | ||
85 | static int find_dot_all (const char*); | |
86 | ||
87 | %} | |
88 | ||
89 | %s IN_STRING BEFORE_QUAL_QUOTE | |
90 | ||
91 | %% | |
92 | ||
93 | {WHITE} { } | |
94 | ||
95 | "--".* { yyterminate(); } | |
96 | ||
97 | {NUM10}{POSEXP} { | |
98 | canonicalizeNumeral (numbuf, yytext); | |
99 | return processInt (NULL, numbuf, strrchr(numbuf, 'e')+1); | |
100 | } | |
101 | ||
102 | {NUM10} { | |
103 | canonicalizeNumeral (numbuf, yytext); | |
104 | return processInt (NULL, numbuf, NULL); | |
105 | } | |
106 | ||
107 | {NUM10}"#"{HEXDIG}({HEXDIG}|_)*"#"{POSEXP} { | |
108 | canonicalizeNumeral (numbuf, yytext); | |
109 | return processInt (numbuf, | |
110 | strchr (numbuf, '#') + 1, | |
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} { | |
126 | canonicalizeNumeral (numbuf, yytext); | |
127 | return processReal (numbuf); | |
128 | } | |
129 | ||
130 | {NUM10}"."{NUM10} { | |
131 | canonicalizeNumeral (numbuf, yytext); | |
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}|\")"'" { | |
144 | yylval.typed_val.type = builtin_type_ada_char; | |
145 | yylval.typed_val.val = yytext[1]; | |
146 | return CHARLIT; | |
147 | } | |
148 | ||
149 | <INITIAL>"'[\""{HEXDIG}{2}"\"]'" { | |
150 | int v; | |
151 | yylval.typed_val.type = builtin_type_ada_char; | |
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 | ||
159 | <INITIAL>\" { | |
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 | ||
191 | if { | |
192 | while (*lexptr != 'i' && *lexptr != 'I') | |
193 | lexptr -= 1; | |
194 | yyrestart(NULL); | |
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 | } | |
237 | else | |
238 | return ','; | |
239 | } | |
240 | ||
241 | "(" { paren_depth += 1; return '('; } | |
242 | ")" { if (paren_depth == 0) | |
243 | { | |
244 | lexptr -= 1; | |
245 | yyrestart(NULL); | |
246 | return 0; | |
247 | } | |
248 | else | |
249 | { | |
250 | paren_depth -= 1; | |
251 | return ')'; | |
252 | } | |
253 | } | |
254 | ||
255 | "."{WHITE}*all { return DOT_ALL; } | |
256 | ||
257 | "."{WHITE}*{ID} { | |
258 | processId (yytext+1, yyleng-1); | |
259 | return DOT_ID; | |
260 | } | |
261 | ||
262 | {ID}({WHITE}*"."{WHITE}*({ID}|\"{OPER}\"))*(" "*"'")? { | |
263 | int all_posn = find_dot_all (yytext); | |
264 | int token_type, segments, k; | |
265 | int quote_follows; | |
266 | ||
267 | if (all_posn == -1 && yytext[yyleng-1] == '\'') | |
268 | { | |
269 | quote_follows = 1; | |
270 | do { | |
271 | yyless (yyleng-1); | |
272 | } while (yytext[yyleng-1] == ' '); | |
273 | } | |
274 | else | |
275 | quote_follows = 0; | |
276 | ||
277 | if (all_posn >= 0) | |
278 | yyless (all_posn); | |
279 | processId(yytext, yyleng); | |
280 | segments = name_lookup (ada_mangle (yylval.ssym.stoken.ptr), | |
281 | yylval.ssym.stoken.ptr, &token_type); | |
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); | |
292 | if (quote_follows) | |
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 | ||
306 | {ID}({WHITE}*"."{WHITE}*({ID}|\"{OPER}\"))*{WHITE}*:: { | |
307 | processId(yytext, yyleng-2); | |
308 | block_lookup (ada_mangle (yylval.ssym.stoken.ptr), | |
309 | yylval.ssym.stoken.ptr); | |
310 | return BLOCKNAME; | |
311 | } | |
312 | ||
313 | [{}@] { return yytext[0]; } | |
314 | ||
315 | "$$" { yylval.lval = -1; return LAST; } | |
316 | "$$"{DIG}+ { yylval.lval = -atoi(yytext+2); return LAST; } | |
317 | "$" { yylval.lval = 0; return LAST; } | |
318 | "$"{DIG}+ { yylval.lval = atoi(yytext+1); return LAST; } | |
319 | ||
320 | ||
321 | /* REGISTERS AND GDB CONVENIENCE VARIABLES */ | |
322 | ||
323 | "$"({LETTER}|{DIG}|"$")+ { | |
324 | int c; | |
325 | for (c = 0; c < NUM_REGS; c++) | |
326 | if (REGISTER_NAME (c) && | |
327 | strcmp (yytext + 1, REGISTER_NAME (c)) == 0) | |
328 | { | |
329 | yylval.lval = c; | |
330 | return REGNAME; | |
331 | } | |
332 | yylval.sval.ptr = yytext; | |
333 | yylval.sval.length = yyleng; | |
334 | yylval.ivar = | |
335 | lookup_internalvar (copy_name (yylval.sval) + 1); | |
336 | return INTERNAL_VARIABLE; | |
337 | } | |
338 | ||
339 | /* CATCH-ALL ERROR CASE */ | |
340 | ||
341 | . { error ("Invalid character '%s' in expression.", yytext); } | |
342 | %% | |
343 | ||
344 | #include <ctype.h> | |
345 | #include <string.h> | |
346 | ||
347 | /* Initialize the lexer for processing new expression */ | |
348 | void | |
349 | lexer_init (FILE* inp) | |
350 | { | |
351 | BEGIN INITIAL; | |
352 | yyrestart (inp); | |
353 | } | |
354 | ||
355 | ||
356 | /* Make sure that tempbuf points at an array at least N characters long. */ | |
357 | ||
358 | static void | |
359 | resize_tempbuf (n) | |
360 | unsigned int n; | |
361 | { | |
362 | if (tempbufsize < n) | |
363 | { | |
364 | tempbufsize = (n+63) & ~63; | |
365 | tempbuf = (char*) xrealloc (tempbuf, tempbufsize); | |
366 | } | |
367 | } | |
368 | ||
369 | /* Copy S2 to S1, removing all underscores, and downcasing all letters. */ | |
370 | ||
371 | static void | |
372 | canonicalizeNumeral (s1,s2) | |
373 | char* s1; | |
374 | const char* s2; | |
375 | { | |
376 | for (; *s2 != '\000'; s2 += 1) | |
377 | { | |
378 | if (*s2 != '_') | |
379 | { | |
380 | *s1 = tolower(*s2); | |
381 | s1 += 1; | |
382 | } | |
383 | } | |
384 | s1[0] = '\000'; | |
385 | } | |
386 | ||
387 | #define HIGH_BYTE_POSN ((sizeof (ULONGEST) - 1) * HOST_CHAR_BIT) | |
388 | ||
389 | /* True (non-zero) iff DIGIT is a valid digit in radix BASE, | |
390 | where 2 <= BASE <= 16. */ | |
391 | ||
392 | static int | |
393 | is_digit_in_base (digit, base) | |
394 | unsigned char digit; | |
395 | int base; | |
396 | { | |
397 | if (!isxdigit (digit)) | |
398 | return 0; | |
399 | if (base <= 10) | |
400 | return (isdigit (digit) && digit < base + '0'); | |
401 | else | |
402 | return (isdigit (digit) || tolower (digit) < base - 10 + 'a'); | |
403 | } | |
404 | ||
405 | static int | |
406 | digit_to_int (c) | |
407 | unsigned char c; | |
408 | { | |
409 | if (isdigit (c)) | |
410 | return c - '0'; | |
411 | else | |
412 | return tolower (c) - 'a' + 10; | |
413 | } | |
414 | ||
415 | /* As for strtoul, but for ULONGEST results. */ | |
416 | ULONGEST | |
417 | strtoulst (num, trailer, base) | |
418 | const char *num; | |
419 | const char **trailer; | |
420 | int base; | |
421 | { | |
422 | unsigned int high_part; | |
423 | ULONGEST result; | |
424 | int i; | |
425 | unsigned char lim; | |
426 | ||
427 | if (base < 2 || base > 16) | |
428 | { | |
429 | errno = EINVAL; | |
430 | return 0; | |
431 | } | |
432 | lim = base - 1 + '0'; | |
433 | ||
434 | result = high_part = 0; | |
435 | for (i = 0; is_digit_in_base (num[i], base); i += 1) | |
436 | { | |
437 | result = result*base + digit_to_int (num[i]); | |
438 | high_part = high_part*base + (unsigned int) (result >> HIGH_BYTE_POSN); | |
439 | result &= ((ULONGEST) 1 << HIGH_BYTE_POSN) - 1; | |
440 | if (high_part > 0xff) | |
441 | { | |
442 | errno = ERANGE; | |
443 | result = high_part = 0; | |
444 | break; | |
445 | } | |
446 | } | |
447 | ||
448 | if (trailer != NULL) | |
449 | *trailer = &num[i]; | |
450 | ||
451 | return result + ((ULONGEST) high_part << HIGH_BYTE_POSN); | |
452 | } | |
453 | ||
454 | ||
455 | ||
456 | /* Interprets the prefix of NUM that consists of digits of the given BASE | |
457 | as an integer of that BASE, with the string EXP as an exponent. | |
458 | Puts value in yylval, and returns INT, if the string is valid. Causes | |
459 | an error if the number is improperly formated. BASE, if NULL, defaults | |
460 | to "10", and EXP to "1". The EXP does not contain a leading 'e' or 'E'. */ | |
461 | ||
462 | static int | |
463 | processInt (base0, num0, exp0) | |
464 | const char* num0; | |
465 | const char* base0; | |
466 | const char* exp0; | |
467 | { | |
468 | ULONGEST result; | |
469 | long exp; | |
470 | int base; | |
471 | ||
472 | char* trailer; | |
473 | ||
474 | if (base0 == NULL) | |
475 | base = 10; | |
476 | else | |
477 | { | |
478 | base = strtol (base0, (char**) NULL, 10); | |
479 | if (base < 2 || base > 16) | |
480 | error ("Invalid base: %d.", base); | |
481 | } | |
482 | ||
483 | if (exp0 == NULL) | |
484 | exp = 0; | |
485 | else | |
486 | exp = strtol(exp0, (char**) NULL, 10); | |
487 | ||
488 | errno = 0; | |
489 | result = strtoulst (num0, &trailer, base); | |
490 | if (errno == ERANGE) | |
491 | error ("Integer literal out of range"); | |
492 | if (isxdigit(*trailer)) | |
493 | error ("Invalid digit `%c' in based literal", *trailer); | |
494 | ||
495 | while (exp > 0) | |
496 | { | |
497 | if (result > (ULONG_MAX / base)) | |
498 | error ("Integer literal out of range"); | |
499 | result *= base; | |
500 | exp -= 1; | |
501 | } | |
502 | ||
503 | if ((result >> (TARGET_INT_BIT-1)) == 0) | |
504 | yylval.typed_val.type = builtin_type_ada_int; | |
505 | else if ((result >> (TARGET_LONG_BIT-1)) == 0) | |
506 | yylval.typed_val.type = builtin_type_ada_long; | |
507 | else if (((result >> (TARGET_LONG_BIT-1)) >> 1) == 0) | |
508 | { | |
509 | /* We have a number representable as an unsigned integer quantity. | |
510 | For consistency with the C treatment, we will treat it as an | |
511 | anonymous modular (unsigned) quantity. Alas, the types are such | |
512 | that we need to store .val as a signed quantity. Sorry | |
513 | for the mess, but C doesn't officially guarantee that a simple | |
514 | assignment does the trick (no, it doesn't; read the reference manual). | |
515 | */ | |
516 | yylval.typed_val.type = builtin_type_unsigned_long; | |
517 | if (result & LONGEST_SIGN) | |
518 | yylval.typed_val.val = | |
519 | (LONGEST) (result & ~LONGEST_SIGN) | |
520 | - (LONGEST_SIGN>>1) - (LONGEST_SIGN>>1); | |
521 | else | |
522 | yylval.typed_val.val = (LONGEST) result; | |
523 | return INT; | |
524 | } | |
525 | else | |
526 | yylval.typed_val.type = builtin_type_ada_long_long; | |
527 | ||
528 | yylval.typed_val.val = (LONGEST) result; | |
529 | return INT; | |
530 | } | |
531 | ||
532 | static int | |
533 | processReal (num0) | |
534 | const char* num0; | |
535 | { | |
536 | if (sizeof (DOUBLEST) <= sizeof (float)) | |
537 | sscanf (num0, "%g", &yylval.typed_val_float.dval); | |
538 | else if (sizeof (DOUBLEST) <= sizeof (double)) | |
539 | sscanf (num0, "%lg", &yylval.typed_val_float.dval); | |
540 | else | |
541 | { | |
542 | #ifdef PRINTF_HAS_LONG_DOUBLE | |
543 | sscanf (num0, "%Lg", &yylval.typed_val_float.dval); | |
544 | #else | |
545 | /* Scan it into a double, then convert and assign it to the | |
546 | long double. This at least wins with values representable | |
547 | in the range of doubles. */ | |
548 | double temp; | |
549 | sscanf (num0, "%lg", &temp); | |
550 | yylval.typed_val_float.dval = temp; | |
551 | #endif | |
552 | } | |
553 | ||
554 | yylval.typed_val_float.type = builtin_type_ada_float; | |
555 | if (sizeof(DOUBLEST) >= TARGET_DOUBLE_BIT / TARGET_CHAR_BIT) | |
556 | yylval.typed_val_float.type = builtin_type_ada_double; | |
557 | if (sizeof(DOUBLEST) >= TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT) | |
558 | yylval.typed_val_float.type = builtin_type_ada_long_double; | |
559 | ||
560 | return FLOAT; | |
561 | } | |
562 | ||
563 | static int | |
564 | processId (name0, len) | |
565 | const char *name0; | |
566 | int len; | |
567 | { | |
568 | char* name = xmalloc (len + 11); | |
569 | int i0, i; | |
570 | ||
571 | /* add_name_string_cleanup (name); */ | |
572 | /* FIXME: add_name_string_cleanup should be defined in parse.c */ | |
573 | while (len > 0 && isspace (name0[len-1])) | |
574 | len -= 1; | |
575 | i = i0 = 0; | |
576 | while (i0 < len) | |
577 | { | |
578 | if (isalnum (name0[i0])) | |
579 | { | |
580 | name[i] = tolower (name0[i0]); | |
581 | i += 1; i0 += 1; | |
582 | } | |
583 | else switch (name0[i0]) | |
584 | { | |
585 | default: | |
586 | name[i] = name0[i0]; | |
587 | i += 1; i0 += 1; | |
588 | break; | |
589 | case ' ': case '\t': | |
590 | i0 += 1; | |
591 | break; | |
592 | case '\'': | |
593 | i0 += 1; | |
594 | while (i0 < len && name0[i0] != '\'') | |
595 | { | |
596 | name[i] = name0[i0]; | |
597 | i += 1; i0 += 1; | |
598 | } | |
599 | i0 += 1; | |
600 | break; | |
601 | case '<': | |
602 | i0 += 1; | |
603 | while (i0 < len && name0[i0] != '>') | |
604 | { | |
605 | name[i] = name0[i0]; | |
606 | i += 1; i0 += 1; | |
607 | } | |
608 | i0 += 1; | |
609 | break; | |
610 | } | |
611 | } | |
612 | name[i] = '\000'; | |
613 | ||
614 | yylval.ssym.sym = NULL; | |
615 | yylval.ssym.stoken.ptr = name; | |
616 | yylval.ssym.stoken.length = i; | |
617 | return NAME; | |
618 | } | |
619 | ||
620 | static void | |
621 | block_lookup (name, err_name) | |
622 | char* name; | |
623 | char* err_name; | |
624 | { | |
625 | struct symbol** syms; | |
626 | struct block** blocks; | |
627 | int nsyms; | |
628 | struct symtab *symtab; | |
629 | nsyms = ada_lookup_symbol_list (name, left_block_context, | |
630 | VAR_NAMESPACE, &syms, &blocks); | |
631 | if (left_block_context == NULL && | |
632 | (nsyms == 0 || SYMBOL_CLASS (syms[0]) != LOC_BLOCK)) | |
633 | symtab = lookup_symtab (name); | |
634 | else | |
635 | symtab = NULL; | |
636 | ||
637 | if (symtab != NULL) | |
638 | left_block_context = yylval.bval = | |
639 | BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK); | |
640 | else if (nsyms == 0 || SYMBOL_CLASS (syms[0]) != LOC_BLOCK) | |
641 | { | |
642 | if (left_block_context == NULL) | |
643 | error ("No file or function \"%s\".", err_name); | |
644 | else | |
645 | error ("No function \"%s\" in specified context.", err_name); | |
646 | } | |
647 | else | |
648 | { | |
649 | left_block_context = yylval.bval = SYMBOL_BLOCK_VALUE (syms[0]); | |
650 | if (nsyms > 1) | |
651 | warning ("Function name \"%s\" ambiguous here", err_name); | |
652 | } | |
653 | } | |
654 | ||
655 | /* Look up NAME0 (assumed to be mangled) as a name in VAR_NAMESPACE, | |
656 | setting *TOKEN_TYPE to NAME or TYPENAME, depending on what is | |
657 | found. Try first the entire name, then the name without the last | |
658 | segment (i.e., after the last .id), etc., and return the number of | |
659 | segments that had to be removed to get a match. Calls error if no | |
660 | matches are found, using ERR_NAME in any error message. When | |
661 | exactly one symbol match is found, it is placed in yylval. */ | |
662 | ||
663 | static int | |
664 | name_lookup (name0, err_name, token_type) | |
665 | char* name0; | |
666 | char* err_name; | |
667 | int* token_type; | |
668 | { | |
669 | struct symbol** syms; | |
670 | struct block** blocks; | |
671 | struct type* type; | |
672 | int len0 = strlen (name0); | |
673 | char* name = savestring (name0, len0); | |
674 | int nsyms; | |
675 | int segments; | |
676 | ||
677 | /* add_name_string_cleanup (name);*/ | |
678 | /* FIXME: add_name_string_cleanup should be defined in parse.c */ | |
679 | yylval.ssym.stoken.ptr = name; | |
680 | yylval.ssym.stoken.length = strlen (name); | |
681 | for (segments = 0; ; segments += 1) | |
682 | { | |
683 | struct type* preferred_type; | |
684 | int i, preferred_index; | |
685 | ||
686 | if (left_block_context == NULL) | |
687 | nsyms = ada_lookup_symbol_list (name, expression_context_block, | |
688 | VAR_NAMESPACE, &syms, &blocks); | |
689 | else | |
690 | nsyms = ada_lookup_symbol_list (name, left_block_context, | |
691 | VAR_NAMESPACE, &syms, &blocks); | |
692 | ||
693 | /* Check for a type definition. */ | |
694 | ||
695 | /* Look for a symbol that doesn't denote void. This is (I think) a */ | |
696 | /* temporary kludge to get around problems in GNAT output. */ | |
697 | preferred_index = -1; preferred_type = NULL; | |
698 | for (i = 0; i < nsyms; i += 1) | |
699 | switch (SYMBOL_CLASS (syms[i])) | |
700 | { | |
701 | case LOC_TYPEDEF: | |
702 | if (ada_prefer_type (SYMBOL_TYPE (syms[i]), preferred_type)) | |
703 | { | |
704 | preferred_index = i; | |
705 | preferred_type = SYMBOL_TYPE (syms[i]); | |
706 | } | |
707 | break; | |
708 | case LOC_REGISTER: | |
709 | case LOC_ARG: | |
710 | case LOC_REF_ARG: | |
711 | case LOC_REGPARM: | |
712 | case LOC_REGPARM_ADDR: | |
713 | case LOC_LOCAL: | |
714 | case LOC_LOCAL_ARG: | |
715 | case LOC_BASEREG: | |
716 | case LOC_BASEREG_ARG: | |
717 | goto NotType; | |
718 | default: | |
719 | break; | |
720 | } | |
721 | if (preferred_type != NULL) | |
722 | { | |
723 | /* if (TYPE_CODE (preferred_type) == TYPE_CODE_VOID) | |
724 | error ("`%s' matches only void type name(s)", | |
725 | ada_demangle (name)); | |
726 | */ | |
727 | /* FIXME: ada_demangle should be defined in defs.h, and is located in ada-lang.c */ | |
728 | /* else*/ if (ada_is_object_renaming (syms[preferred_index])) | |
729 | { | |
730 | yylval.ssym.sym = syms[preferred_index]; | |
731 | *token_type = OBJECT_RENAMING; | |
732 | return segments; | |
733 | } | |
734 | else if (ada_renaming_type (SYMBOL_TYPE (syms[preferred_index])) | |
735 | != NULL) | |
736 | { | |
737 | int result; | |
738 | const char* renaming = | |
739 | ada_simple_renamed_entity (syms[preferred_index]); | |
740 | char* new_name = xmalloc (strlen (renaming) + len0 | |
741 | - yylval.ssym.stoken.length + 1); | |
742 | /* add_name_string_cleanup (new_name);*/ | |
743 | /* FIXME: add_name_string_cleanup should be defined in parse.c */ | |
744 | strcpy (new_name, renaming); | |
745 | strcat (new_name, name0 + yylval.ssym.stoken.length); | |
746 | result = name_lookup (new_name, err_name, token_type); | |
747 | if (result > segments) | |
748 | error ("Confused by renamed symbol."); | |
749 | return result; | |
750 | } | |
751 | else if (segments == 0) | |
752 | { | |
753 | yylval.tval = preferred_type; | |
754 | *token_type = TYPENAME; | |
755 | return 0; | |
756 | } | |
757 | } | |
758 | ||
759 | if (segments == 0) | |
760 | { | |
761 | type = lookup_primitive_typename (name); | |
762 | if (type == NULL && STREQ ("system__address", name)) | |
763 | type = builtin_type_ada_system_address; | |
764 | if (type != NULL) | |
765 | { | |
766 | yylval.tval = type; | |
767 | *token_type = TYPENAME; | |
768 | return 0; | |
769 | } | |
770 | } | |
771 | ||
772 | NotType: | |
773 | if (nsyms == 1) | |
774 | { | |
775 | *token_type = NAME; | |
776 | yylval.ssym.sym = syms[0]; | |
777 | yylval.ssym.msym = NULL; | |
778 | yylval.ssym.block = blocks[0]; | |
779 | return segments; | |
780 | } | |
781 | else if (nsyms == 0) { | |
782 | int i; | |
783 | yylval.ssym.msym = ada_lookup_minimal_symbol (name); | |
784 | if (yylval.ssym.msym != NULL) | |
785 | { | |
786 | yylval.ssym.sym = NULL; | |
787 | yylval.ssym.block = NULL; | |
788 | *token_type = NAME; | |
789 | return segments; | |
790 | } | |
791 | ||
792 | for (i = yylval.ssym.stoken.length - 1; i > 0; i -= 1) | |
793 | { | |
794 | if (name[i] == '.') | |
795 | { | |
796 | name[i] = '\0'; | |
797 | yylval.ssym.stoken.length = i; | |
798 | break; | |
799 | } | |
800 | else if (name[i] == '_' && name[i-1] == '_') | |
801 | { | |
802 | i -= 1; | |
803 | name[i] = '\0'; | |
804 | yylval.ssym.stoken.length = i; | |
805 | break; | |
806 | } | |
807 | } | |
808 | if (i <= 0) | |
809 | { | |
810 | if (!have_full_symbols () && !have_partial_symbols () | |
811 | && left_block_context == NULL) | |
812 | error ("No symbol table is loaded. Use the \"file\" command."); | |
813 | if (left_block_context == NULL) | |
814 | error ("No definition of \"%s\" in current context.", | |
815 | err_name); | |
816 | else | |
817 | error ("No definition of \"%s\" in specified context.", | |
818 | err_name); | |
819 | } | |
820 | } | |
821 | else | |
822 | { | |
823 | *token_type = NAME; | |
824 | yylval.ssym.sym = NULL; | |
825 | yylval.ssym.msym = NULL; | |
826 | if (left_block_context == NULL) | |
827 | yylval.ssym.block = expression_context_block; | |
828 | else | |
829 | yylval.ssym.block = left_block_context; | |
830 | return segments; | |
831 | } | |
832 | } | |
833 | } | |
834 | ||
835 | /* Returns the position within STR of the '.' in a | |
836 | '.{WHITE}*all' component of a dotted name, or -1 if there is none. */ | |
837 | static int | |
838 | find_dot_all (str) | |
839 | const char* str; | |
840 | { | |
841 | int i; | |
842 | for (i = 0; str[i] != '\000'; i += 1) | |
843 | { | |
844 | if (str[i] == '.') | |
845 | { | |
846 | int i0 = i; | |
847 | do | |
848 | i += 1; | |
849 | while (isspace (str[i])); | |
850 | if (strcmp (str+i, "all") == 0 | |
851 | && ! isalnum (str[i+3]) && str[i+3] != '_') | |
852 | return i0; | |
853 | } | |
854 | } | |
855 | return -1; | |
856 | } | |
857 | ||
858 | /* Returns non-zero iff string SUBSEQ matches a subsequence of STR, ignoring | |
859 | case. */ | |
860 | ||
861 | static int | |
862 | subseqMatch (subseq, str) | |
863 | const char* subseq; | |
864 | const char* str; | |
865 | { | |
866 | if (subseq[0] == '\0') | |
867 | return 1; | |
868 | else if (str[0] == '\0') | |
869 | return 0; | |
870 | else if (tolower (subseq[0]) == tolower (str[0])) | |
871 | return subseqMatch (subseq+1, str+1) || subseqMatch (subseq, str+1); | |
872 | else | |
873 | return subseqMatch (subseq, str+1); | |
874 | } | |
875 | ||
876 | ||
877 | static struct { const char* name; int code; } | |
878 | attributes[] = { | |
879 | { "address", TICK_ADDRESS }, | |
880 | { "unchecked_access", TICK_ACCESS }, | |
881 | { "unrestricted_access", TICK_ACCESS }, | |
882 | { "access", TICK_ACCESS }, | |
883 | { "first", TICK_FIRST }, | |
884 | { "last", TICK_LAST }, | |
885 | { "length", TICK_LENGTH }, | |
886 | { "max", TICK_MAX }, | |
887 | { "min", TICK_MIN }, | |
888 | { "modulus", TICK_MODULUS }, | |
889 | { "pos", TICK_POS }, | |
890 | { "range", TICK_RANGE }, | |
891 | { "size", TICK_SIZE }, | |
892 | { "tag", TICK_TAG }, | |
893 | { "val", TICK_VAL }, | |
894 | { NULL, -1 } | |
895 | }; | |
896 | ||
897 | /* Return the syntactic code corresponding to the attribute name or | |
898 | abbreviation STR. */ | |
899 | ||
900 | static int | |
901 | processAttribute (str) | |
902 | const char* str; | |
903 | { | |
904 | int i, k; | |
905 | ||
906 | for (i = 0; attributes[i].code != -1; i += 1) | |
907 | if (strcasecmp (str, attributes[i].name) == 0) | |
908 | return attributes[i].code; | |
909 | ||
910 | for (i = 0, k = -1; attributes[i].code != -1; i += 1) | |
911 | if (subseqMatch (str, attributes[i].name)) | |
912 | { | |
913 | if (k == -1) | |
914 | k = i; | |
915 | else | |
916 | error ("ambiguous attribute name: `%s'", str); | |
917 | } | |
918 | if (k == -1) | |
919 | error ("unrecognized attribute: `%s'", str); | |
920 | ||
921 | return attributes[k].code; | |
922 | } | |
923 | ||
924 | int | |
925 | yywrap() | |
926 | { | |
927 | return 1; | |
928 | } |