]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/gdb/gdb/ada-lex.l
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / gdb / gdb / ada-lex.l
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_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  
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_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. */
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 }