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