1/* FLEX lexer for Ada expressions, for GDB. 2 Copyright (C) 1994, 1997, 2000 3 Free Software Foundation, Inc. 4 5This file is part of GDB. 6 7This program is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 2 of the License, or 10(at your option) any later version. 11 12This program is distributed in the hope that it will be useful, 13but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15GNU General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with this program; if not, write to the Free Software 19Foundation, 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 32DIG [0-9] 33NUM10 ({DIG}({DIG}|_)*) 34HEXDIG [0-9a-f] 35NUM16 ({HEXDIG}({HEXDIG}|_)*) 36OCTDIG [0-7] 37LETTER [a-z_] 38ID ({LETTER}({LETTER}|{DIG})*|"<"{LETTER}({LETTER}|{DIG})*">") 39WHITE [ \t\n] 40TICK ("'"{WHITE}*) 41GRAPHIC [a-z0-9 #&'()*+,-./:;<>=_|!$%?@\[\]\\^`{}~] 42OPER ([-+*/=<>&]|"<="|">="|"**"|"/="|"and"|"or"|"xor"|"not"|"mod"|"rem"|"abs") 43 44EXP (e[+-]{NUM10}) 45POSEXP (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. */ 52static char numbuf[NUMERAL_WIDTH]; 53 static void canonicalizeNumeral (char* s1, const char*); 54static int processInt (const char*, const char*, const char*); 55static int processReal (const char*); 56static int processId (const char*, int); 57static int processAttribute (const char*); 58static 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 74static char *tempbuf = NULL; 75static int tempbufsize = 0; 76static int tempbuf_len; 77static struct block* left_block_context; 78 79static void resize_tempbuf (unsigned int); 80 81static void block_lookup (char*, char*); 82 83static int name_lookup (char*, char*, int*); 84 85static 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 191if { 192 while (*lexptr != 'i' && *lexptr != 'I') 193 lexptr -= 1; 194 yyrestart(NULL); 195 return 0; 196 } 197 198 /* ADA KEYWORDS */ 199 200abs { return ABS; } 201and { return _AND_; } 202else { return ELSE; } 203in { return IN; } 204mod { return MOD; } 205new { return NEW; } 206not { return NOT; } 207null { return NULL_PTR; } 208or { return OR; } 209rem { return REM; } 210then { return THEN; } 211xor { 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 */ 348void 349lexer_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 358static void 359resize_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 371static void 372canonicalizeNumeral (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 392static int 393is_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 405static int 406digit_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. */ 416ULONGEST 417strtoulst (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 462static int 463processInt (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 532static int 533processReal (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 563static int 564processId (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 620static void 621block_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_DOMAIN, &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_DOMAIN, 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 663static int 664name_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_DOMAIN, &syms, &blocks); 689 else 690 nsyms = ada_lookup_symbol_list (name, left_block_context, 691 VAR_DOMAIN, &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 && DEPRECATED_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. */ 837static int 838find_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 861static int 862subseqMatch (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 877static struct { const char* name; int code; } 878attributes[] = { 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 900static int 901processAttribute (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 924int 925yywrap() 926{ 927 return 1; 928} 929