Add base ada language files
authorAidan Skinner <aidan@velvet.net>
Tue, 4 Jun 2002 15:28:49 +0000 (15:28 +0000)
committerAidan Skinner <aidan@velvet.net>
Tue, 4 Jun 2002 15:28:49 +0000 (15:28 +0000)
gdb/ada-exp.tab.c [new file with mode: 0644]
gdb/ada-exp.y [new file with mode: 0644]
gdb/ada-lang.c [new file with mode: 0644]
gdb/ada-lang.h [new file with mode: 0644]
gdb/ada-lex.c [new file with mode: 0644]
gdb/ada-lex.l [new file with mode: 0644]
gdb/ada-tasks.c [new file with mode: 0644]
gdb/ada-typeprint.c [new file with mode: 0644]
gdb/ada-valprint.c [new file with mode: 0644]

diff --git a/gdb/ada-exp.tab.c b/gdb/ada-exp.tab.c
new file mode 100644 (file)
index 0000000..bb6d29b
--- /dev/null
@@ -0,0 +1,2389 @@
+/* A Bison parser, made from ./ada-exp.y
+   by GNU bison 1.35.  */
+
+#define YYBISON 1  /* Identify Bison output.  */
+
+# define       INT     257
+# define       NULL_PTR        258
+# define       CHARLIT 259
+# define       FLOAT   260
+# define       TYPENAME        261
+# define       BLOCKNAME       262
+# define       STRING  263
+# define       NAME    264
+# define       DOT_ID  265
+# define       OBJECT_RENAMING 266
+# define       DOT_ALL 267
+# define       LAST    268
+# define       REGNAME 269
+# define       INTERNAL_VARIABLE       270
+# define       ASSIGN  271
+# define       _AND_   272
+# define       OR      273
+# define       XOR     274
+# define       THEN    275
+# define       ELSE    276
+# define       NOTEQUAL        277
+# define       LEQ     278
+# define       GEQ     279
+# define       IN      280
+# define       DOTDOT  281
+# define       UNARY   282
+# define       MOD     283
+# define       REM     284
+# define       STARSTAR        285
+# define       ABS     286
+# define       NOT     287
+# define       TICK_ACCESS     288
+# define       TICK_ADDRESS    289
+# define       TICK_FIRST      290
+# define       TICK_LAST       291
+# define       TICK_LENGTH     292
+# define       TICK_MAX        293
+# define       TICK_MIN        294
+# define       TICK_MODULUS    295
+# define       TICK_POS        296
+# define       TICK_RANGE      297
+# define       TICK_SIZE       298
+# define       TICK_TAG        299
+# define       TICK_VAL        300
+# define       ARROW   301
+# define       NEW     302
+
+#line 38 "./ada-exp.y"
+
+
+#include "defs.h"
+#include <string.h>
+#include <ctype.h>
+#include "expression.h"
+#include "value.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "ada-lang.h"
+#include "bfd.h" /* Required by objfiles.h.  */
+#include "symfile.h" /* Required by objfiles.h.  */
+#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
+#include "frame.h"
+
+/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
+   as well as gratuitiously global symbol names, so we can have multiple
+   yacc generated parsers in gdb.  These are only the variables
+   produced by yacc.  If other parser generators (bison, byacc, etc) produce
+   additional global names that conflict at link time, then those parser
+   generators need to be fixed instead of adding those names to this list. */
+
+/* NOTE: This is clumsy, especially since BISON and FLEX provide --prefix  
+   options.  I presume we are maintaining it to accommodate systems
+   without BISON?  (PNH) */
+
+#define        yymaxdepth ada_maxdepth
+#define        yyparse _ada_parse      /* ada_parse calls this after  initialization */
+#define        yylex   ada_lex
+#define        yyerror ada_error
+#define        yylval  ada_lval
+#define        yychar  ada_char
+#define        yydebug ada_debug
+#define        yypact  ada_pact        
+#define        yyr1    ada_r1                  
+#define        yyr2    ada_r2                  
+#define        yydef   ada_def         
+#define        yychk   ada_chk         
+#define        yypgo   ada_pgo         
+#define        yyact   ada_act         
+#define        yyexca  ada_exca
+#define yyerrflag ada_errflag
+#define yynerrs        ada_nerrs
+#define        yyps    ada_ps
+#define        yypv    ada_pv
+#define        yys     ada_s
+#define        yy_yys  ada_yys
+#define        yystate ada_state
+#define        yytmp   ada_tmp
+#define        yyv     ada_v
+#define        yy_yyv  ada_yyv
+#define        yyval   ada_val
+#define        yylloc  ada_lloc
+#define yyreds ada_reds                /* With YYDEBUG defined */
+#define yytoks ada_toks                /* With YYDEBUG defined */
+
+#ifndef YYDEBUG
+#define        YYDEBUG 0               /* Default to no yydebug support */
+#endif
+
+struct name_info {
+  struct symbol* sym;
+  struct minimal_symbol* msym;
+  struct block* block;
+  struct stoken stoken;
+};
+
+/* If expression is in the context of TYPE'(...), then TYPE, else
+ * NULL. */
+static struct type* type_qualifier;
+
+int yyparse (void);
+
+static int yylex (void);
+
+void yyerror (char *);
+
+static struct stoken string_to_operator (struct stoken);
+
+static void write_attribute_call0 (enum ada_attribute);
+
+static void write_attribute_call1 (enum ada_attribute, LONGEST);
+
+static void write_attribute_calln (enum ada_attribute, int);
+
+static void write_object_renaming (struct block*, struct symbol*);
+
+static void write_var_from_name (struct block*, struct name_info);
+
+static LONGEST
+convert_char_literal (struct type*, LONGEST);
+
+#line 131 "./ada-exp.y"
+#ifndef YYSTYPE
+typedef union
+  {
+    LONGEST lval;
+    struct {
+      LONGEST val;
+      struct type *type;
+    } typed_val;
+    struct {
+      DOUBLEST dval;
+      struct type *type;
+    } typed_val_float;
+    struct type *tval;
+    struct stoken sval;
+    struct name_info ssym;
+    int voidval;
+    struct block *bval;
+    struct internalvar *ivar;
+
+  } yystype;
+# define YYSTYPE yystype
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+
+
+#define        YYFINAL         184
+#define        YYFLAG          -32768
+#define        YYNTBASE        68
+
+/* YYTRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */
+#define YYTRANSLATE(x) ((unsigned)(x) <= 302 ? yytranslate[x] : 82)
+
+/* YYTRANSLATE[YYLEX] -- Bison token number corresponding to YYLEX. */
+static const char yytranslate[] =
+{
+       0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,    34,    63,
+      57,    62,    36,    32,    64,    33,    56,    37,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,    61,
+      25,    23,    26,     2,    31,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,    58,     2,    67,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,    65,     2,    66,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,     2,     2,     1,     3,     4,     5,
+       6,     7,     8,     9,    10,    11,    12,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,    24,    27,    28,
+      29,    30,    35,    38,    39,    40,    41,    42,    43,    44,
+      45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
+      55,    59,    60
+};
+
+#if YYDEBUG
+static const short yyprhs[] =
+{
+       0,     0,     2,     4,     6,    10,    13,    16,    21,    26,
+      27,    35,    36,    43,    47,    49,    51,    53,    55,    57,
+      61,    64,    67,    70,    73,    74,    76,    80,    84,    90,
+      95,    99,   103,   107,   111,   115,   119,   123,   127,   131,
+     135,   139,   143,   149,   155,   159,   166,   173,   178,   182,
+     186,   190,   194,   199,   203,   208,   212,   215,   218,   222,
+     226,   230,   233,   236,   244,   252,   258,   262,   266,   270,
+     276,   279,   280,   284,   286,   288,   289,   291,   293,   295,
+     297,   299,   302,   304,   307,   309,   312,   314,   316,   318,
+     320,   323,   325,   328,   331,   335,   338,   341
+};
+static const short yyrhs[] =
+{
+      69,     0,    81,     0,    73,     0,    69,    61,    73,     0,
+      70,    13,     0,    70,    11,     0,    70,    57,    74,    62,
+       0,    81,    57,    73,    62,     0,     0,    81,    63,    72,
+      71,    57,    73,    62,     0,     0,    70,    57,    73,    30,
+      73,    62,     0,    57,    69,    62,     0,    78,     0,    15,
+       0,    16,     0,    70,     0,    14,     0,    73,    17,    73,
+       0,    33,    73,     0,    32,    73,     0,    42,    73,     0,
+      41,    73,     0,     0,    73,     0,    79,    59,    73,     0,
+      74,    64,    73,     0,    74,    64,    79,    59,    73,     0,
+      65,    81,    66,    73,     0,    73,    40,    73,     0,    73,
+      36,    73,     0,    73,    37,    73,     0,    73,    39,    73,
+       0,    73,    38,    73,     0,    73,    31,    73,     0,    73,
+      32,    73,     0,    73,    34,    73,     0,    73,    33,    73,
+       0,    73,    23,    73,     0,    73,    24,    73,     0,    73,
+      27,    73,     0,    73,    29,    73,    30,    73,     0,    73,
+      29,    73,    52,    75,     0,    73,    29,     7,     0,    73,
+      42,    29,    73,    30,    73,     0,    73,    42,    29,    73,
+      52,    75,     0,    73,    42,    29,     7,     0,    73,    28,
+      73,     0,    73,    25,    73,     0,    73,    26,    73,     0,
+      73,    18,    73,     0,    73,    18,    21,    73,     0,    73,
+      19,    73,     0,    73,    19,    22,    73,     0,    73,    20,
+      73,     0,    70,    43,     0,    70,    44,     0,    70,    45,
+      75,     0,    70,    46,    75,     0,    70,    47,    75,     0,
+      70,    53,     0,    70,    54,     0,    77,    49,    57,    73,
+      64,    73,    62,     0,    77,    48,    57,    73,    64,    73,
+      62,     0,    77,    51,    57,    73,    62,     0,    76,    45,
+      75,     0,    76,    46,    75,     0,    76,    47,    75,     0,
+      76,    55,    57,    73,    62,     0,    76,    50,     0,     0,
+      57,     3,    62,     0,     7,     0,    76,     0,     0,     3,
+       0,     5,     0,     6,     0,     4,     0,     9,     0,    60,
+       7,     0,    10,     0,    80,    10,     0,    12,     0,    80,
+      12,     0,    10,     0,     7,     0,    12,     0,     8,     0,
+      80,     8,     0,     7,     0,    80,     7,     0,     7,    43,
+       0,    80,     7,    43,     0,    36,    73,     0,    34,    73,
+       0,    73,    58,    73,    67,     0
+};
+
+#endif
+
+#if YYDEBUG
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const short yyrline[] =
+{
+       0,   203,   204,   210,   211,   216,   220,   227,   235,   243,
+     243,   254,   256,   261,   264,   267,   274,   282,   285,   292,
+     296,   300,   304,   308,   312,   315,   317,   319,   321,   325,
+     335,   339,   343,   347,   351,   355,   359,   363,   367,   371,
+     375,   379,   383,   387,   393,   400,   405,   413,   423,   427,
+     431,   435,   439,   443,   447,   451,   455,   457,   463,   465,
+     467,   469,   471,   473,   475,   477,   479,   481,   483,   485,
+     487,   491,   493,   497,   504,   506,   513,   521,   533,   541,
+     548,   575,   579,   580,   582,   583,   587,   588,   589,   592,
+     594,   599,   600,   601,   603,   610,   612,   614
+};
+#endif
+
+
+#if (YYDEBUG) || defined YYERROR_VERBOSE
+
+/* YYTNAME[TOKEN_NUM] -- String name of the token TOKEN_NUM. */
+static const char *const yytname[] =
+{
+  "$", "error", "$undefined.", "INT", "NULL_PTR", "CHARLIT", "FLOAT", 
+  "TYPENAME", "BLOCKNAME", "STRING", "NAME", "DOT_ID", "OBJECT_RENAMING", 
+  "DOT_ALL", "LAST", "REGNAME", "INTERNAL_VARIABLE", "ASSIGN", "_AND_", 
+  "OR", "XOR", "THEN", "ELSE", "'='", "NOTEQUAL", "'<'", "'>'", "LEQ", 
+  "GEQ", "IN", "DOTDOT", "'@'", "'+'", "'-'", "'&'", "UNARY", "'*'", 
+  "'/'", "MOD", "REM", "STARSTAR", "ABS", "NOT", "TICK_ACCESS", 
+  "TICK_ADDRESS", "TICK_FIRST", "TICK_LAST", "TICK_LENGTH", "TICK_MAX", 
+  "TICK_MIN", "TICK_MODULUS", "TICK_POS", "TICK_RANGE", "TICK_SIZE", 
+  "TICK_TAG", "TICK_VAL", "'.'", "'('", "'['", "ARROW", "NEW", "';'", 
+  "')'", "'\\''", "','", "'{'", "'}'", "']'", "start", "exp1", 
+  "simple_exp", "@1", "save_qualifier", "exp", "arglist", "tick_arglist", 
+  "type_prefix", "opt_type_prefix", "variable", "any_name", "block", 
+  "type", 0
+};
+#endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const short yyr1[] =
+{
+       0,    68,    68,    69,    69,    70,    70,    70,    70,    71,
+      70,    72,    70,    70,    70,    70,    70,    73,    70,    73,
+      73,    73,    73,    73,    74,    74,    74,    74,    74,    73,
+      73,    73,    73,    73,    73,    73,    73,    73,    73,    73,
+      73,    73,    73,    73,    73,    73,    73,    73,    73,    73,
+      73,    73,    73,    73,    73,    73,    70,    70,    70,    70,
+      70,    70,    70,    70,    70,    70,    70,    70,    70,    70,
+      70,    75,    75,    76,    77,    77,    73,    73,    73,    73,
+      73,    73,    78,    78,    78,    78,    79,    79,    79,    80,
+      80,    81,    81,    81,    81,    73,    73,    73
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const short yyr2[] =
+{
+       0,     1,     1,     1,     3,     2,     2,     4,     4,     0,
+       7,     0,     6,     3,     1,     1,     1,     1,     1,     3,
+       2,     2,     2,     2,     0,     1,     3,     3,     5,     4,
+       3,     3,     3,     3,     3,     3,     3,     3,     3,     3,
+       3,     3,     5,     5,     3,     6,     6,     4,     3,     3,
+       3,     3,     4,     3,     4,     3,     2,     2,     3,     3,
+       3,     2,     2,     7,     7,     5,     3,     3,     3,     5,
+       2,     0,     3,     1,     1,     0,     1,     1,     1,     1,
+       1,     2,     1,     2,     1,     2,     1,     1,     1,     1,
+       2,     1,     2,     2,     3,     2,     2,     4
+};
+
+/* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE
+   doesn't specify something else to do.  Zero means the default is an
+   error. */
+static const short yydefact[] =
+{
+      75,    76,    79,    77,    78,    73,    89,    80,    82,    84,
+      18,    15,    16,    75,    75,    75,    75,    75,    75,    75,
+       0,     0,     1,    17,     3,    74,     0,    14,     0,     2,
+      93,    21,     0,    20,    96,    95,    23,    22,     0,    81,
+      91,     0,     0,    75,     6,     5,    56,    57,    71,    71,
+      71,    61,    62,    75,    75,    75,    75,    75,    75,    75,
+      75,    75,    75,    75,    75,    75,    75,    75,    75,    75,
+      75,    75,    75,    75,     0,    75,    71,    71,    71,    70,
+       0,     0,     0,     0,    92,    90,    83,    85,    75,    11,
+      13,    75,     4,     0,    58,    59,    60,    73,    82,    84,
+      25,     0,     0,    19,    75,    51,    75,    53,    55,    39,
+      40,    49,    50,    41,    48,    44,     0,    35,    36,    38,
+      37,    31,    32,    34,    33,    30,    75,     0,    66,    67,
+      68,    75,    75,    75,    75,    94,     0,     9,    29,     0,
+      75,     7,    75,    75,    52,    54,    75,    71,    47,     0,
+      97,     0,     0,     0,     0,     8,     0,    72,     0,    27,
+       0,    26,    42,    43,    75,    71,    69,    75,    75,    65,
+      75,    12,    75,    45,    46,     0,     0,     0,    28,    64,
+      63,    10,     0,     0,     0
+};
+
+static const short yydefgoto[] =
+{
+     182,    22,    23,   156,   137,    24,   101,    94,    25,    26,
+      27,   102,    28,    32
+};
+
+static const short yypact[] =
+{
+     251,-32768,-32768,-32768,-32768,    20,-32768,-32768,-32768,-32768,
+  -32768,-32768,-32768,   251,   251,   251,   251,   251,   251,   251,
+       2,    79,   -47,    53,   958,   -23,    54,-32768,   104,   -32,
+  -32768,    31,   -32,    31,   -22,   -22,    31,    31,    33,-32768,
+      -5,   101,   -27,   251,-32768,-32768,-32768,-32768,     4,     4,
+       4,-32768,-32768,   131,   251,   171,   211,   251,   251,   251,
+     251,   251,   251,   251,   291,   251,   251,   251,   251,   251,
+     251,   251,   251,   251,    47,   251,     4,     4,     4,-32768,
+      23,    25,    27,    35,    45,-32768,-32768,-32768,   251,-32768,
+  -32768,   251,   958,    98,-32768,-32768,-32768,    22,    56,    58,
+     930,   -36,    64,   986,   251,  1009,   251,  1009,  1009,   -21,
+     -21,   -21,   -21,   -21,   -21,   534,   858,   387,    31,    31,
+      31,    32,    32,    32,    32,    32,   331,   415,-32768,-32768,
+  -32768,   251,   251,   251,   251,-32768,   536,-32768,   -22,    62,
+     251,-32768,   371,   251,  1009,  1009,   251,     4,   534,   894,
+  -32768,   582,   452,   494,   628,-32768,    68,-32768,   674,   958,
+      67,   958,   -21,-32768,   251,     4,-32768,   251,   251,-32768,
+     251,-32768,   251,   -21,-32768,   720,   766,   812,   958,-32768,
+  -32768,-32768,   128,   132,-32768
+};
+
+static const short yypgoto[] =
+{
+  -32768,   112,-32768,-32768,-32768,   -13,-32768,   -43,-32768,-32768,
+  -32768,     0,   123,     8
+};
+
+
+#define        YYLAST          1067
+
+
+static const short yytable[] =
+{
+      31,    33,    34,    35,    36,    37,    95,    96,    29,    39,
+      65,    66,    67,    68,    43,    69,    70,    71,    72,    73,
+     -91,    74,    76,    77,    78,    88,   141,    79,   142,    42,
+      92,    89,    80,   128,   129,   130,    75,    75,    30,    91,
+     100,   103,   105,   107,   108,   109,   110,   111,   112,   113,
+     114,   116,   117,   118,   119,   120,   121,   122,   123,   124,
+     125,    93,   127,    30,    44,    30,    45,    69,    70,    71,
+      72,    73,    73,    74,    74,   136,   126,   -91,   138,   -91,
+     131,   -87,   132,   -91,   133,   -91,    40,     6,   135,    75,
+      75,   144,   134,   145,    43,    90,    46,    47,    48,    49,
+      50,   139,    81,    82,   163,    83,    51,    52,    84,    85,
+      53,    84,    85,   149,    86,   -86,    87,   -88,   151,   152,
+     153,   154,   174,   143,   157,   170,   172,   158,   183,   159,
+     161,    38,   184,   162,     1,     2,     3,     4,    97,     6,
+       7,    98,   160,    99,    41,    10,    11,    12,     0,     0,
+       0,   173,     0,     0,   175,   176,     0,   177,     0,   178,
+       0,     0,     0,    13,    14,    15,     0,    16,     0,     0,
+       0,     0,    17,    18,     1,     2,     3,     4,     5,     6,
+       7,     8,     0,     9,     0,    10,    11,    12,    19,     0,
+       0,    20,   104,   -24,     0,   -24,    21,     0,     0,     0,
+       0,     0,     0,    13,    14,    15,     0,    16,     0,     0,
+       0,     0,    17,    18,     1,     2,     3,     4,     5,     6,
+       7,     8,     0,     9,     0,    10,    11,    12,    19,     0,
+       0,    20,     0,   106,     0,     0,    21,     0,     0,     0,
+       0,     0,     0,    13,    14,    15,     0,    16,     0,     0,
+       0,     0,    17,    18,     1,     2,     3,     4,     5,     6,
+       7,     8,     0,     9,     0,    10,    11,    12,    19,     0,
+       0,    20,     0,     0,     0,     0,    21,     0,     0,     0,
+       0,     0,     0,    13,    14,    15,     0,    16,     0,     0,
+       0,     0,    17,    18,     1,     2,     3,     4,   115,     6,
+       7,     8,     0,     9,     0,    10,    11,    12,    19,     0,
+       0,    20,     0,     0,     0,     0,    21,     0,     0,     0,
+       0,     0,     0,    13,    14,    15,     0,    16,     0,     0,
+       0,     0,    17,    18,     1,     2,     3,     4,   148,     6,
+       7,     8,     0,     9,     0,    10,    11,    12,    19,     0,
+       0,    20,     0,     0,     0,     0,    21,     0,     0,     0,
+       0,     0,     0,    13,    14,    15,     0,    16,     0,     0,
+       0,     0,    17,    18,     1,     2,     3,     4,    97,     6,
+       7,    98,     0,    99,     0,    10,    11,    12,    19,     0,
+       0,    20,     0,     0,     0,     0,    21,     0,     0,     0,
+       0,     0,     0,    13,    14,    15,     0,    16,     0,     0,
+       0,     0,    17,    18,     0,     0,     0,     0,     0,    66,
+      67,    68,     0,    69,    70,    71,    72,    73,    19,    74,
+       0,    20,    54,    55,    56,    57,    21,     0,    58,    59,
+      60,    61,    62,    63,    64,    75,    65,    66,    67,    68,
+       0,    69,    70,    71,    72,    73,     0,    74,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,    54,
+      55,    56,    57,    75,     0,    58,    59,    60,    61,    62,
+      63,    64,   150,    65,    66,    67,    68,     0,    69,    70,
+      71,    72,    73,     0,    74,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      75,    54,    55,    56,    57,     0,   167,    58,    59,    60,
+      61,    62,    63,    64,     0,    65,    66,    67,    68,     0,
+      69,    70,    71,    72,    73,     0,    74,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    75,    54,    55,    56,    57,     0,   168,    58,
+      59,    60,    61,    62,    63,    64,     0,    65,    66,    67,
+      68,     0,    69,    70,    71,    72,    73,    30,    74,   -73,
+     -73,   -73,   -73,   -73,   -73,   -73,     0,     0,     0,   -73,
+       0,   -91,     0,     0,    75,     0,     0,   -91,   155,    54,
+      55,    56,    57,     0,     0,    58,    59,    60,    61,    62,
+      63,    64,     0,    65,    66,    67,    68,     0,    69,    70,
+      71,    72,    73,     0,    74,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      75,     0,     0,     0,   166,    54,    55,    56,    57,     0,
+       0,    58,    59,    60,    61,    62,    63,    64,     0,    65,
+      66,    67,    68,     0,    69,    70,    71,    72,    73,     0,
+      74,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,    75,     0,     0,     0,
+     169,    54,    55,    56,    57,     0,     0,    58,    59,    60,
+      61,    62,    63,    64,     0,    65,    66,    67,    68,     0,
+      69,    70,    71,    72,    73,     0,    74,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    75,     0,     0,     0,   171,    54,    55,    56,
+      57,     0,     0,    58,    59,    60,    61,    62,    63,    64,
+       0,    65,    66,    67,    68,     0,    69,    70,    71,    72,
+      73,     0,    74,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,    75,     0,
+       0,     0,   179,    54,    55,    56,    57,     0,     0,    58,
+      59,    60,    61,    62,    63,    64,     0,    65,    66,    67,
+      68,     0,    69,    70,    71,    72,    73,     0,    74,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,    75,     0,     0,     0,   180,    54,
+      55,    56,    57,     0,     0,    58,    59,    60,    61,    62,
+      63,    64,     0,    65,    66,    67,    68,     0,    69,    70,
+      71,    72,    73,     0,    74,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+      75,     0,     0,     0,   181,    54,    55,    56,    57,     0,
+       0,    58,    59,    60,    61,    62,    63,    64,   146,    65,
+      66,    67,    68,     0,    69,    70,    71,    72,    73,     0,
+      74,     0,     0,     0,     0,     0,     0,     0,     0,     0,
+     147,    54,    55,    56,    57,     0,    75,    58,    59,    60,
+      61,    62,    63,    64,   164,    65,    66,    67,    68,     0,
+      69,    70,    71,    72,    73,     0,    74,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,   165,    54,    55,    56,
+      57,     0,    75,    58,    59,    60,    61,    62,    63,    64,
+     140,    65,    66,    67,    68,     0,    69,    70,    71,    72,
+      73,     0,    74,     0,     0,    54,    55,    56,    57,     0,
+       0,    58,    59,    60,    61,    62,    63,    64,    75,    65,
+      66,    67,    68,     0,    69,    70,    71,    72,    73,     0,
+      74,     0,     0,-32768,    55,    56,    57,     0,     0,    58,
+      59,    60,    61,    62,    63,    64,    75,    65,    66,    67,
+      68,     0,    69,    70,    71,    72,    73,     0,    74,     0,
+       0,     0,    58,    59,    60,    61,    62,    63,    64,     0,
+      65,    66,    67,    68,    75,    69,    70,    71,    72,    73,
+       0,    74,     0,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,     0,     0,     0,     0,     0,    75
+};
+
+static const short yycheck[] =
+{
+      13,    14,    15,    16,    17,    18,    49,    50,     0,     7,
+      31,    32,    33,    34,    61,    36,    37,    38,    39,    40,
+       0,    42,    45,    46,    47,    57,    62,    50,    64,    21,
+      43,    63,    55,    76,    77,    78,    58,    58,    43,    66,
+      53,    54,    55,    56,    57,    58,    59,    60,    61,    62,
+      63,    64,    65,    66,    67,    68,    69,    70,    71,    72,
+      73,    57,    75,    43,    11,    43,    13,    36,    37,    38,
+      39,    40,    40,    42,    42,    88,    29,    57,    91,    57,
+      57,    59,    57,    63,    57,    63,     7,     8,    43,    58,
+      58,   104,    57,   106,    61,    62,    43,    44,    45,    46,
+      47,     3,    48,    49,   147,    51,    53,    54,     7,     8,
+      57,     7,     8,   126,    10,    59,    12,    59,   131,   132,
+     133,   134,   165,    59,    62,    57,    59,   140,     0,   142,
+     143,    19,     0,   146,     3,     4,     5,     6,     7,     8,
+       9,    10,   142,    12,    21,    14,    15,    16,    -1,    -1,
+      -1,   164,    -1,    -1,   167,   168,    -1,   170,    -1,   172,
+      -1,    -1,    -1,    32,    33,    34,    -1,    36,    -1,    -1,
+      -1,    -1,    41,    42,     3,     4,     5,     6,     7,     8,
+       9,    10,    -1,    12,    -1,    14,    15,    16,    57,    -1,
+      -1,    60,    21,    62,    -1,    64,    65,    -1,    -1,    -1,
+      -1,    -1,    -1,    32,    33,    34,    -1,    36,    -1,    -1,
+      -1,    -1,    41,    42,     3,     4,     5,     6,     7,     8,
+       9,    10,    -1,    12,    -1,    14,    15,    16,    57,    -1,
+      -1,    60,    -1,    22,    -1,    -1,    65,    -1,    -1,    -1,
+      -1,    -1,    -1,    32,    33,    34,    -1,    36,    -1,    -1,
+      -1,    -1,    41,    42,     3,     4,     5,     6,     7,     8,
+       9,    10,    -1,    12,    -1,    14,    15,    16,    57,    -1,
+      -1,    60,    -1,    -1,    -1,    -1,    65,    -1,    -1,    -1,
+      -1,    -1,    -1,    32,    33,    34,    -1,    36,    -1,    -1,
+      -1,    -1,    41,    42,     3,     4,     5,     6,     7,     8,
+       9,    10,    -1,    12,    -1,    14,    15,    16,    57,    -1,
+      -1,    60,    -1,    -1,    -1,    -1,    65,    -1,    -1,    -1,
+      -1,    -1,    -1,    32,    33,    34,    -1,    36,    -1,    -1,
+      -1,    -1,    41,    42,     3,     4,     5,     6,     7,     8,
+       9,    10,    -1,    12,    -1,    14,    15,    16,    57,    -1,
+      -1,    60,    -1,    -1,    -1,    -1,    65,    -1,    -1,    -1,
+      -1,    -1,    -1,    32,    33,    34,    -1,    36,    -1,    -1,
+      -1,    -1,    41,    42,     3,     4,     5,     6,     7,     8,
+       9,    10,    -1,    12,    -1,    14,    15,    16,    57,    -1,
+      -1,    60,    -1,    -1,    -1,    -1,    65,    -1,    -1,    -1,
+      -1,    -1,    -1,    32,    33,    34,    -1,    36,    -1,    -1,
+      -1,    -1,    41,    42,    -1,    -1,    -1,    -1,    -1,    32,
+      33,    34,    -1,    36,    37,    38,    39,    40,    57,    42,
+      -1,    60,    17,    18,    19,    20,    65,    -1,    23,    24,
+      25,    26,    27,    28,    29,    58,    31,    32,    33,    34,
+      -1,    36,    37,    38,    39,    40,    -1,    42,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    17,
+      18,    19,    20,    58,    -1,    23,    24,    25,    26,    27,
+      28,    29,    67,    31,    32,    33,    34,    -1,    36,    37,
+      38,    39,    40,    -1,    42,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      58,    17,    18,    19,    20,    -1,    64,    23,    24,    25,
+      26,    27,    28,    29,    -1,    31,    32,    33,    34,    -1,
+      36,    37,    38,    39,    40,    -1,    42,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    58,    17,    18,    19,    20,    -1,    64,    23,
+      24,    25,    26,    27,    28,    29,    -1,    31,    32,    33,
+      34,    -1,    36,    37,    38,    39,    40,    43,    42,    45,
+      46,    47,    48,    49,    50,    51,    -1,    -1,    -1,    55,
+      -1,    57,    -1,    -1,    58,    -1,    -1,    63,    62,    17,
+      18,    19,    20,    -1,    -1,    23,    24,    25,    26,    27,
+      28,    29,    -1,    31,    32,    33,    34,    -1,    36,    37,
+      38,    39,    40,    -1,    42,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      58,    -1,    -1,    -1,    62,    17,    18,    19,    20,    -1,
+      -1,    23,    24,    25,    26,    27,    28,    29,    -1,    31,
+      32,    33,    34,    -1,    36,    37,    38,    39,    40,    -1,
+      42,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    58,    -1,    -1,    -1,
+      62,    17,    18,    19,    20,    -1,    -1,    23,    24,    25,
+      26,    27,    28,    29,    -1,    31,    32,    33,    34,    -1,
+      36,    37,    38,    39,    40,    -1,    42,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    58,    -1,    -1,    -1,    62,    17,    18,    19,
+      20,    -1,    -1,    23,    24,    25,    26,    27,    28,    29,
+      -1,    31,    32,    33,    34,    -1,    36,    37,    38,    39,
+      40,    -1,    42,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    58,    -1,
+      -1,    -1,    62,    17,    18,    19,    20,    -1,    -1,    23,
+      24,    25,    26,    27,    28,    29,    -1,    31,    32,    33,
+      34,    -1,    36,    37,    38,    39,    40,    -1,    42,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    58,    -1,    -1,    -1,    62,    17,
+      18,    19,    20,    -1,    -1,    23,    24,    25,    26,    27,
+      28,    29,    -1,    31,    32,    33,    34,    -1,    36,    37,
+      38,    39,    40,    -1,    42,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      58,    -1,    -1,    -1,    62,    17,    18,    19,    20,    -1,
+      -1,    23,    24,    25,    26,    27,    28,    29,    30,    31,
+      32,    33,    34,    -1,    36,    37,    38,    39,    40,    -1,
+      42,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      52,    17,    18,    19,    20,    -1,    58,    23,    24,    25,
+      26,    27,    28,    29,    30,    31,    32,    33,    34,    -1,
+      36,    37,    38,    39,    40,    -1,    42,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    52,    17,    18,    19,
+      20,    -1,    58,    23,    24,    25,    26,    27,    28,    29,
+      30,    31,    32,    33,    34,    -1,    36,    37,    38,    39,
+      40,    -1,    42,    -1,    -1,    17,    18,    19,    20,    -1,
+      -1,    23,    24,    25,    26,    27,    28,    29,    58,    31,
+      32,    33,    34,    -1,    36,    37,    38,    39,    40,    -1,
+      42,    -1,    -1,    17,    18,    19,    20,    -1,    -1,    23,
+      24,    25,    26,    27,    28,    29,    58,    31,    32,    33,
+      34,    -1,    36,    37,    38,    39,    40,    -1,    42,    -1,
+      -1,    -1,    23,    24,    25,    26,    27,    28,    29,    -1,
+      31,    32,    33,    34,    58,    36,    37,    38,    39,    40,
+      -1,    42,    -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    -1,    -1,    -1,    -1,    58
+};
+/* -*-C-*-  Note some compilers choke on comments on `#line' lines.  */
+#line 3 "/usr/local/share/bison/bison.simple"
+
+/* Skeleton output parser for bison,
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software
+   Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, when this file is copied by Bison into a
+   Bison output file, you may use that output file without restriction.
+   This special exception was added by the Free Software Foundation
+   in version 1.24 of Bison.  */
+
+/* This is the parser code that is written into each bison parser when
+   the %semantic_parser declaration is not specified in the grammar.
+   It was written by Richard Stallman by simplifying the hairy parser
+   used when %semantic_parser is specified.  */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+   infringing on user name space.  This should be done even for local
+   variables, as they might otherwise be expanded by user macros.
+   There are some unavoidable exceptions within include files to
+   define necessary library symbols; they are noted "INFRINGES ON
+   USER NAME SPACE" below.  */
+
+#if ! defined (yyoverflow) || defined (YYERROR_VERBOSE)
+
+/* The parser invokes alloca or xmalloc; define the necessary symbols.  */
+
+# if YYSTACK_USE_ALLOCA
+#  define YYSTACK_ALLOC alloca
+# else
+#  ifndef YYSTACK_USE_ALLOCA
+#   if defined (alloca) || defined (_ALLOCA_H)
+#    define YYSTACK_ALLOC alloca
+#   else
+#    ifdef __GNUC__
+#     define YYSTACK_ALLOC __builtin_alloca
+#    endif
+#   endif
+#  endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+   /* Pacify GCC's `empty if-body' warning. */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
+# else
+#  if defined (__STDC__) || defined (__cplusplus)
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   define YYSIZE_T size_t
+#  endif
+#  define YYSTACK_ALLOC xmalloc
+#  define YYSTACK_FREE free
+# endif
+#endif /* ! defined (yyoverflow) || defined (YYERROR_VERBOSE) */
+
+
+#if (! defined (yyoverflow) \
+     && (! defined (__cplusplus) \
+        || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member.  */
+union yyalloc
+{
+  short yyss;
+  YYSTYPE yyvs;
+# if YYLSP_NEEDED
+  YYLTYPE yyls;
+# endif
+};
+
+/* The size of the maximum gap between one aligned stack and the next.  */
+# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+   N elements.  */
+# if YYLSP_NEEDED
+#  define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short) + sizeof (YYSTYPE) + sizeof (YYLTYPE))     \
+      + 2 * YYSTACK_GAP_MAX)
+# else
+#  define YYSTACK_BYTES(N) \
+     ((N) * (sizeof (short) + sizeof (YYSTYPE))                                \
+      + YYSTACK_GAP_MAX)
+# endif
+
+/* Copy COUNT objects from FROM to TO.  The source and destination do
+   not overlap.  */
+# ifndef YYCOPY
+#  if 1 < __GNUC__
+#   define YYCOPY(To, From, Count) \
+      __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+#  else
+#   define YYCOPY(To, From, Count)             \
+      do                                       \
+       {                                       \
+         register YYSIZE_T yyi;                \
+         for (yyi = 0; yyi < (Count); yyi++)   \
+           (To)[yyi] = (From)[yyi];            \
+       }                                       \
+      while (0)
+#  endif
+# endif
+
+/* Relocate STACK from its old location to the new one.  The
+   local variables YYSIZE and YYSTACKSIZE give the old and new number of
+   elements in the stack, and YYPTR gives the new location of the
+   stack.  Advance YYPTR to a properly aligned location for the next
+   stack.  */
+# define YYSTACK_RELOCATE(Stack)                                       \
+    do                                                                 \
+      {                                                                        \
+       YYSIZE_T yynewbytes;                                            \
+       YYCOPY (&yyptr->Stack, Stack, yysize);                          \
+       Stack = &yyptr->Stack;                                          \
+       yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX;   \
+       yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                        \
+    while (0)
+
+#endif
+
+
+#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__)
+# define YYSIZE_T __SIZE_TYPE__
+#endif
+#if ! defined (YYSIZE_T) && defined (size_t)
+# define YYSIZE_T size_t
+#endif
+#if ! defined (YYSIZE_T)
+# if defined (__STDC__) || defined (__cplusplus)
+#  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYSIZE_T size_t
+# endif
+#endif
+#if ! defined (YYSIZE_T)
+# define YYSIZE_T unsigned int
+#endif
+
+#define yyerrok                (yyerrstatus = 0)
+#define yyclearin      (yychar = YYEMPTY)
+#define YYEMPTY                -2
+#define YYEOF          0
+#define YYACCEPT       goto yyacceptlab
+#define YYABORT        goto yyabortlab
+#define YYERROR                goto yyerrlab1
+/* Like YYERROR except do call yyerror.  This remains here temporarily
+   to ease the transition to the new meaning of YYERROR, for GCC.
+   Once GCC version 2 has supplanted version 1, this can go.  */
+#define YYFAIL         goto yyerrlab
+#define YYRECOVERING()  (!!yyerrstatus)
+#define YYBACKUP(Token, Value)                                 \
+do                                                             \
+  if (yychar == YYEMPTY && yylen == 1)                         \
+    {                                                          \
+      yychar = (Token);                                                \
+      yylval = (Value);                                                \
+      yychar1 = YYTRANSLATE (yychar);                          \
+      YYPOPSTACK;                                              \
+      goto yybackup;                                           \
+    }                                                          \
+  else                                                         \
+    {                                                          \
+      yyerror ("syntax error: cannot back up");                        \
+      YYERROR;                                                 \
+    }                                                          \
+while (0)
+
+#define YYTERROR       1
+#define YYERRCODE      256
+
+
+/* YYLLOC_DEFAULT -- Compute the default location (before the actions
+   are run).
+
+   When YYLLOC_DEFAULT is run, CURRENT is set the location of the
+   first token.  By default, to implement support for ranges, extend
+   its range to the last symbol.  */
+
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N)               \
+   Current.last_line   = Rhs[N].last_line;     \
+   Current.last_column = Rhs[N].last_column;
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments.  */
+
+#if YYPURE
+# if YYLSP_NEEDED
+#  ifdef YYLEX_PARAM
+#   define YYLEX               yylex (&yylval, &yylloc, YYLEX_PARAM)
+#  else
+#   define YYLEX               yylex (&yylval, &yylloc)
+#  endif
+# else /* !YYLSP_NEEDED */
+#  ifdef YYLEX_PARAM
+#   define YYLEX               yylex (&yylval, YYLEX_PARAM)
+#  else
+#   define YYLEX               yylex (&yylval)
+#  endif
+# endif /* !YYLSP_NEEDED */
+#else /* !YYPURE */
+# define YYLEX                 yylex ()
+#endif /* !YYPURE */
+
+
+/* Enable debugging if requested.  */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+#  include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+#  define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args)                       \
+do {                                           \
+  if (yydebug)                                 \
+    YYFPRINTF Args;                            \
+} while (0)
+/* Nonzero means print parse trace.  It is left uninitialized so that
+   multiple parsers can coexist.  */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+#endif /* !YYDEBUG */
+
+/* YYINITDEPTH -- initial size of the parser's stacks.  */
+#ifndef        YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+   if the built-in stack extension method is used).
+
+   Do not make this value too large; the results are undefined if
+   SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH)
+   evaluated with infinite-precision integer arithmetic.  */
+
+#if YYMAXDEPTH == 0
+# undef YYMAXDEPTH
+#endif
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+\f
+#ifdef YYERROR_VERBOSE
+
+# ifndef yystrlen
+#  if defined (__GLIBC__) && defined (_STRING_H)
+#   define yystrlen strlen
+#  else
+/* Return the length of YYSTR.  */
+static YYSIZE_T
+#   if defined (__STDC__) || defined (__cplusplus)
+yystrlen (const char *yystr)
+#   else
+yystrlen (yystr)
+     const char *yystr;
+#   endif
+{
+  register const char *yys = yystr;
+
+  while (*yys++ != '\0')
+    continue;
+
+  return yys - yystr - 1;
+}
+#  endif
+# endif
+
+# ifndef yystpcpy
+#  if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE)
+#   define yystpcpy stpcpy
+#  else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+   YYDEST.  */
+static char *
+#   if defined (__STDC__) || defined (__cplusplus)
+yystpcpy (char *yydest, const char *yysrc)
+#   else
+yystpcpy (yydest, yysrc)
+     char *yydest;
+     const char *yysrc;
+#   endif
+{
+  register char *yyd = yydest;
+  register const char *yys = yysrc;
+
+  while ((*yyd++ = *yys++) != '\0')
+    continue;
+
+  return yyd - 1;
+}
+#  endif
+# endif
+#endif
+\f
+#line 315 "/usr/local/share/bison/bison.simple"
+
+
+/* The user can define YYPARSE_PARAM as the name of an argument to be passed
+   into yyparse.  The argument should have type void *.
+   It should actually point to an object.
+   Grammar actions can access the variable by casting it
+   to the proper pointer type.  */
+
+#ifdef YYPARSE_PARAM
+# if defined (__STDC__) || defined (__cplusplus)
+#  define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
+#  define YYPARSE_PARAM_DECL
+# else
+#  define YYPARSE_PARAM_ARG YYPARSE_PARAM
+#  define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
+# endif
+#else /* !YYPARSE_PARAM */
+# define YYPARSE_PARAM_ARG
+# define YYPARSE_PARAM_DECL
+#endif /* !YYPARSE_PARAM */
+
+/* Prevent warning if -Wstrict-prototypes.  */
+#ifdef __GNUC__
+# ifdef YYPARSE_PARAM
+int yyparse (void *);
+# else
+int yyparse (void);
+# endif
+#endif
+
+/* YY_DECL_VARIABLES -- depending whether we use a pure parser,
+   variables are global, or local to YYPARSE.  */
+
+#define YY_DECL_NON_LSP_VARIABLES                      \
+/* The lookahead symbol.  */                           \
+int yychar;                                            \
+                                                       \
+/* The semantic value of the lookahead symbol. */      \
+YYSTYPE yylval;                                                \
+                                                       \
+/* Number of parse errors so far.  */                  \
+int yynerrs;
+
+#if YYLSP_NEEDED
+# define YY_DECL_VARIABLES                     \
+YY_DECL_NON_LSP_VARIABLES                      \
+                                               \
+/* Location data for the lookahead symbol.  */ \
+YYLTYPE yylloc;
+#else
+# define YY_DECL_VARIABLES                     \
+YY_DECL_NON_LSP_VARIABLES
+#endif
+
+
+/* If nonreentrant, generate the variables here. */
+
+#if !YYPURE
+YY_DECL_VARIABLES
+#endif  /* !YYPURE */
+
+int
+yyparse (YYPARSE_PARAM_ARG)
+     YYPARSE_PARAM_DECL
+{
+  /* If reentrant, generate the variables here. */
+#if YYPURE
+  YY_DECL_VARIABLES
+#endif  /* !YYPURE */
+
+  register int yystate;
+  register int yyn;
+  int yyresult;
+  /* Number of tokens to shift before error messages enabled.  */
+  int yyerrstatus;
+  /* Lookahead token as an internal (translated) token number.  */
+  int yychar1 = 0;
+
+  /* Three stacks and their tools:
+     `yyss': related to states,
+     `yyvs': related to semantic values,
+     `yyls': related to locations.
+
+     Refer to the stacks thru separate pointers, to allow yyoverflow
+     to xreallocate them elsewhere.  */
+
+  /* The state stack. */
+  short        yyssa[YYINITDEPTH];
+  short *yyss = yyssa;
+  register short *yyssp;
+
+  /* The semantic value stack.  */
+  YYSTYPE yyvsa[YYINITDEPTH];
+  YYSTYPE *yyvs = yyvsa;
+  register YYSTYPE *yyvsp;
+
+#if YYLSP_NEEDED
+  /* The location stack.  */
+  YYLTYPE yylsa[YYINITDEPTH];
+  YYLTYPE *yyls = yylsa;
+  YYLTYPE *yylsp;
+#endif
+
+#if YYLSP_NEEDED
+# define YYPOPSTACK   (yyvsp--, yyssp--, yylsp--)
+#else
+# define YYPOPSTACK   (yyvsp--, yyssp--)
+#endif
+
+  YYSIZE_T yystacksize = YYINITDEPTH;
+
+
+  /* The variables used to return semantic value and location from the
+     action routines.  */
+  YYSTYPE yyval;
+#if YYLSP_NEEDED
+  YYLTYPE yyloc;
+#endif
+
+  /* When reducing, the number of symbols on the RHS of the reduced
+     rule. */
+  int yylen;
+
+  YYDPRINTF ((stderr, "Starting parse\n"));
+
+  yystate = 0;
+  yyerrstatus = 0;
+  yynerrs = 0;
+  yychar = YYEMPTY;            /* Cause a token to be read.  */
+
+  /* Initialize stack pointers.
+     Waste one element of value and location stack
+     so that they stay on the same level as the state stack.
+     The wasted elements are never initialized.  */
+
+  yyssp = yyss;
+  yyvsp = yyvs;
+#if YYLSP_NEEDED
+  yylsp = yyls;
+#endif
+  goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate.  |
+`------------------------------------------------------------*/
+ yynewstate:
+  /* In all cases, when you get here, the value and location stacks
+     have just been pushed. so pushing a state here evens the stacks.
+     */
+  yyssp++;
+
+ yysetstate:
+  *yyssp = yystate;
+
+  if (yyssp >= yyss + yystacksize - 1)
+    {
+      /* Get the current used size of the three stacks, in elements.  */
+      YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+      {
+       /* Give user a chance to xreallocate the stack. Use copies of
+          these so that the &'s don't force the real ones into
+          memory.  */
+       YYSTYPE *yyvs1 = yyvs;
+       short *yyss1 = yyss;
+
+       /* Each stack pointer address is followed by the size of the
+          data in use in that stack, in bytes.  */
+# if YYLSP_NEEDED
+       YYLTYPE *yyls1 = yyls;
+       /* This used to be a conditional around just the two extra args,
+          but that might be undefined if yyoverflow is a macro.  */
+       yyoverflow ("parser stack overflow",
+                   &yyss1, yysize * sizeof (*yyssp),
+                   &yyvs1, yysize * sizeof (*yyvsp),
+                   &yyls1, yysize * sizeof (*yylsp),
+                   &yystacksize);
+       yyls = yyls1;
+# else
+       yyoverflow ("parser stack overflow",
+                   &yyss1, yysize * sizeof (*yyssp),
+                   &yyvs1, yysize * sizeof (*yyvsp),
+                   &yystacksize);
+# endif
+       yyss = yyss1;
+       yyvs = yyvs1;
+      }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+      goto yyoverflowlab;
+# else
+      /* Extend the stack our own way.  */
+      if (yystacksize >= YYMAXDEPTH)
+       goto yyoverflowlab;
+      yystacksize *= 2;
+      if (yystacksize > YYMAXDEPTH)
+       yystacksize = YYMAXDEPTH;
+
+      {
+       short *yyss1 = yyss;
+       union yyalloc *yyptr =
+         (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+       if (! yyptr)
+         goto yyoverflowlab;
+       YYSTACK_RELOCATE (yyss);
+       YYSTACK_RELOCATE (yyvs);
+# if YYLSP_NEEDED
+       YYSTACK_RELOCATE (yyls);
+# endif
+# undef YYSTACK_RELOCATE
+       if (yyss1 != yyssa)
+         YYSTACK_FREE (yyss1);
+      }
+# endif
+#endif /* no yyoverflow */
+
+      yyssp = yyss + yysize - 1;
+      yyvsp = yyvs + yysize - 1;
+#if YYLSP_NEEDED
+      yylsp = yyls + yysize - 1;
+#endif
+
+      YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+                 (unsigned long int) yystacksize));
+
+      if (yyssp >= yyss + yystacksize - 1)
+       YYABORT;
+    }
+
+  YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+  goto yybackup;
+
+
+/*-----------.
+| yybackup.  |
+`-----------*/
+yybackup:
+
+/* Do appropriate processing given the current state.  */
+/* Read a lookahead token if we need one and don't already have one.  */
+/* yyresume: */
+
+  /* First try to decide what to do without reference to lookahead token.  */
+
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yydefault;
+
+  /* Not known => get a lookahead token if don't already have one.  */
+
+  /* yychar is either YYEMPTY or YYEOF
+     or a valid token in external form.  */
+
+  if (yychar == YYEMPTY)
+    {
+      YYDPRINTF ((stderr, "Reading a token: "));
+      yychar = YYLEX;
+    }
+
+  /* Convert token to internal form (in yychar1) for indexing tables with */
+
+  if (yychar <= 0)             /* This means end of input. */
+    {
+      yychar1 = 0;
+      yychar = YYEOF;          /* Don't call YYLEX any more */
+
+      YYDPRINTF ((stderr, "Now at end of input.\n"));
+    }
+  else
+    {
+      yychar1 = YYTRANSLATE (yychar);
+
+#if YYDEBUG
+     /* We have to keep this `#if YYDEBUG', since we use variables
+       which are defined only if `YYDEBUG' is set.  */
+      if (yydebug)
+       {
+         YYFPRINTF (stderr, "Next token is %d (%s",
+                    yychar, yytname[yychar1]);
+         /* Give the individual parser a way to print the precise
+            meaning of a token, for further debugging info.  */
+# ifdef YYPRINT
+         YYPRINT (stderr, yychar, yylval);
+# endif
+         YYFPRINTF (stderr, ")\n");
+       }
+#endif
+    }
+
+  yyn += yychar1;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
+    goto yydefault;
+
+  yyn = yytable[yyn];
+
+  /* yyn is what to do for this token type in this state.
+     Negative => reduce, -yyn is rule number.
+     Positive => shift, yyn is new state.
+       New state is final state => don't bother to shift,
+       just return success.
+     0, or most negative number => error.  */
+
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+       goto yyerrlab;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrlab;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  /* Shift the lookahead token.  */
+  YYDPRINTF ((stderr, "Shifting token %d (%s), ",
+             yychar, yytname[yychar1]));
+
+  /* Discard the token being shifted unless it is eof.  */
+  if (yychar != YYEOF)
+    yychar = YYEMPTY;
+
+  *++yyvsp = yylval;
+#if YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  /* Count tokens shifted since error; after three, turn off error
+     status.  */
+  if (yyerrstatus)
+    yyerrstatus--;
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state.  |
+`-----------------------------------------------------------*/
+yydefault:
+  yyn = yydefact[yystate];
+  if (yyn == 0)
+    goto yyerrlab;
+  goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction.  |
+`-----------------------------*/
+yyreduce:
+  /* yyn is the number of a rule to reduce with.  */
+  yylen = yyr2[yyn];
+
+  /* If YYLEN is nonzero, implement the default value of the action:
+     `$$ = $1'.
+
+     Otherwise, the following line sets YYVAL to the semantic value of
+     the lookahead token.  This behavior is undocumented and Bison
+     users should not rely upon it.  Assigning to YYVAL
+     unconditionally makes the parser a bit smaller, and it avoids a
+     GCC warning that YYVAL may be used uninitialized.  */
+  yyval = yyvsp[1-yylen];
+
+#if YYLSP_NEEDED
+  /* Similarly for the default location.  Let the user run additional
+     commands if for instance locations are ranges.  */
+  yyloc = yylsp[1-yylen];
+  YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+#endif
+
+#if YYDEBUG
+  /* We have to keep this `#if YYDEBUG', since we use variables which
+     are defined only if `YYDEBUG' is set.  */
+  if (yydebug)
+    {
+      int yyi;
+
+      YYFPRINTF (stderr, "Reducing via rule %d (line %d), ",
+                yyn, yyrline[yyn]);
+
+      /* Print the symbols being reduced, and their result.  */
+      for (yyi = yyprhs[yyn]; yyrhs[yyi] > 0; yyi++)
+       YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]);
+      YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]);
+    }
+#endif
+
+  switch (yyn) {
+
+case 2:
+#line 204 "./ada-exp.y"
+{ write_exp_elt_opcode (OP_TYPE);
+                         write_exp_elt_type (yyvsp[0].tval);
+                         write_exp_elt_opcode (OP_TYPE); }
+    break;
+case 4:
+#line 212 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_COMMA); }
+    break;
+case 5:
+#line 217 "./ada-exp.y"
+{ write_exp_elt_opcode (UNOP_IND); }
+    break;
+case 6:
+#line 221 "./ada-exp.y"
+{ write_exp_elt_opcode (STRUCTOP_STRUCT);
+                         write_exp_string (yyvsp[0].ssym.stoken);
+                         write_exp_elt_opcode (STRUCTOP_STRUCT); 
+                         }
+    break;
+case 7:
+#line 228 "./ada-exp.y"
+{
+                         write_exp_elt_opcode (OP_FUNCALL);
+                         write_exp_elt_longcst (yyvsp[-1].lval);
+                         write_exp_elt_opcode (OP_FUNCALL);
+                       }
+    break;
+case 8:
+#line 236 "./ada-exp.y"
+{
+                         write_exp_elt_opcode (UNOP_CAST);
+                         write_exp_elt_type (yyvsp[-3].tval);
+                         write_exp_elt_opcode (UNOP_CAST); 
+                       }
+    break;
+case 9:
+#line 243 "./ada-exp.y"
+{ type_qualifier = yyvsp[-2].tval; }
+    break;
+case 10:
+#line 244 "./ada-exp.y"
+{
+                         /*                      write_exp_elt_opcode (UNOP_QUAL); */
+                         /* FIXME: UNOP_QUAL should be defined in expression.h */
+                         write_exp_elt_type (yyvsp[-6].tval);
+                         /* write_exp_elt_opcode (UNOP_QUAL); */
+                         /* FIXME: UNOP_QUAL should be defined in expression.h */
+                         type_qualifier = yyvsp[-4].tval;
+                       }
+    break;
+case 11:
+#line 254 "./ada-exp.y"
+{ yyval.tval = type_qualifier; }
+    break;
+case 12:
+#line 258 "./ada-exp.y"
+{ write_exp_elt_opcode (TERNOP_SLICE); }
+    break;
+case 13:
+#line 261 "./ada-exp.y"
+{ }
+    break;
+case 15:
+#line 268 "./ada-exp.y"
+{ write_exp_elt_opcode (OP_REGISTER);
+                         write_exp_elt_longcst ((LONGEST) yyvsp[0].lval);
+                         write_exp_elt_opcode (OP_REGISTER); 
+                       }
+    break;
+case 16:
+#line 275 "./ada-exp.y"
+{ write_exp_elt_opcode (OP_INTERNALVAR);
+                         write_exp_elt_intern (yyvsp[0].ivar);
+                         write_exp_elt_opcode (OP_INTERNALVAR); 
+                       }
+    break;
+case 18:
+#line 286 "./ada-exp.y"
+{ write_exp_elt_opcode (OP_LAST);
+                         write_exp_elt_longcst ((LONGEST) yyvsp[0].lval);
+                         write_exp_elt_opcode (OP_LAST); 
+                        }
+    break;
+case 19:
+#line 293 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_ASSIGN); }
+    break;
+case 20:
+#line 297 "./ada-exp.y"
+{ write_exp_elt_opcode (UNOP_NEG); }
+    break;
+case 21:
+#line 301 "./ada-exp.y"
+{ write_exp_elt_opcode (UNOP_PLUS); }
+    break;
+case 22:
+#line 305 "./ada-exp.y"
+{ write_exp_elt_opcode (UNOP_LOGICAL_NOT); }
+    break;
+case 23:
+#line 309 "./ada-exp.y"
+{ write_exp_elt_opcode (UNOP_ABS); }
+    break;
+case 24:
+#line 312 "./ada-exp.y"
+{ yyval.lval = 0; }
+    break;
+case 25:
+#line 316 "./ada-exp.y"
+{ yyval.lval = 1; }
+    break;
+case 26:
+#line 318 "./ada-exp.y"
+{ yyval.lval = 1; }
+    break;
+case 27:
+#line 320 "./ada-exp.y"
+{ yyval.lval = yyvsp[-2].lval + 1; }
+    break;
+case 28:
+#line 322 "./ada-exp.y"
+{ yyval.lval = yyvsp[-4].lval + 1; }
+    break;
+case 29:
+#line 327 "./ada-exp.y"
+{ write_exp_elt_opcode (UNOP_MEMVAL);
+                         write_exp_elt_type (yyvsp[-2].tval);
+                         write_exp_elt_opcode (UNOP_MEMVAL); 
+                       }
+    break;
+case 30:
+#line 336 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_EXP); }
+    break;
+case 31:
+#line 340 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_MUL); }
+    break;
+case 32:
+#line 344 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_DIV); }
+    break;
+case 33:
+#line 348 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_REM); }
+    break;
+case 34:
+#line 352 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_MOD); }
+    break;
+case 35:
+#line 356 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_REPEAT); }
+    break;
+case 36:
+#line 360 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_ADD); }
+    break;
+case 37:
+#line 364 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_CONCAT); }
+    break;
+case 38:
+#line 368 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_SUB); }
+    break;
+case 39:
+#line 372 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_EQUAL); }
+    break;
+case 40:
+#line 376 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_NOTEQUAL); }
+    break;
+case 41:
+#line 380 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_LEQ); }
+    break;
+case 42:
+#line 384 "./ada-exp.y"
+{ /*write_exp_elt_opcode (TERNOP_MBR); */ }
+    break;
+case 43:
+#line 388 "./ada-exp.y"
+{ /*write_exp_elt_opcode (BINOP_MBR); */
+                         /* FIXME: BINOP_MBR should be defined in expression.h */
+                         write_exp_elt_longcst ((LONGEST) yyvsp[0].lval);
+                         /*write_exp_elt_opcode (BINOP_MBR); */
+                       }
+    break;
+case 44:
+#line 394 "./ada-exp.y"
+{ /*write_exp_elt_opcode (UNOP_MBR); */
+                         /* FIXME: UNOP_QUAL should be defined in expression.h */                        
+                         write_exp_elt_type (yyvsp[0].tval);
+                         /*                      write_exp_elt_opcode (UNOP_MBR); */
+                         /* FIXME: UNOP_MBR should be defined in expression.h */                         
+                       }
+    break;
+case 45:
+#line 401 "./ada-exp.y"
+{ /*write_exp_elt_opcode (TERNOP_MBR); */
+                         /* FIXME: TERNOP_MBR should be defined in expression.h */                                               
+                         write_exp_elt_opcode (UNOP_LOGICAL_NOT); 
+                       }
+    break;
+case 46:
+#line 406 "./ada-exp.y"
+{ /* write_exp_elt_opcode (BINOP_MBR); */
+                         /* FIXME: BINOP_MBR should be defined in expression.h */
+                         write_exp_elt_longcst ((LONGEST) yyvsp[0].lval);
+                         /*write_exp_elt_opcode (BINOP_MBR);*/
+                         /* FIXME: BINOP_MBR should be defined in expression.h */                        
+                         write_exp_elt_opcode (UNOP_LOGICAL_NOT); 
+                       }
+    break;
+case 47:
+#line 414 "./ada-exp.y"
+{ /*write_exp_elt_opcode (UNOP_MBR);*/
+                         /* FIXME: UNOP_MBR should be defined in expression.h */                         
+                         write_exp_elt_type (yyvsp[0].tval);
+                         /*                      write_exp_elt_opcode (UNOP_MBR);*/
+                         /* FIXME: UNOP_MBR should be defined in expression.h */                                                 
+                         write_exp_elt_opcode (UNOP_LOGICAL_NOT); 
+                       }
+    break;
+case 48:
+#line 424 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_GEQ); }
+    break;
+case 49:
+#line 428 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_LESS); }
+    break;
+case 50:
+#line 432 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_GTR); }
+    break;
+case 51:
+#line 436 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_BITWISE_AND); }
+    break;
+case 52:
+#line 440 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_LOGICAL_AND); }
+    break;
+case 53:
+#line 444 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_BITWISE_IOR); }
+    break;
+case 54:
+#line 448 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_LOGICAL_OR); }
+    break;
+case 55:
+#line 452 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_BITWISE_XOR); }
+    break;
+case 56:
+#line 456 "./ada-exp.y"
+{ write_exp_elt_opcode (UNOP_ADDR); }
+    break;
+case 57:
+#line 458 "./ada-exp.y"
+{ write_exp_elt_opcode (UNOP_ADDR);
+                         write_exp_elt_opcode (UNOP_CAST);
+                         write_exp_elt_type (builtin_type_ada_system_address);
+                         write_exp_elt_opcode (UNOP_CAST);
+                       }
+    break;
+case 58:
+#line 464 "./ada-exp.y"
+{ write_attribute_call1 (ATR_FIRST, yyvsp[0].lval); }
+    break;
+case 59:
+#line 466 "./ada-exp.y"
+{ write_attribute_call1 (ATR_LAST, yyvsp[0].lval); }
+    break;
+case 60:
+#line 468 "./ada-exp.y"
+{ write_attribute_call1 (ATR_LENGTH, yyvsp[0].lval); }
+    break;
+case 61:
+#line 470 "./ada-exp.y"
+{ write_attribute_call0 (ATR_SIZE); }
+    break;
+case 62:
+#line 472 "./ada-exp.y"
+{ write_attribute_call0 (ATR_TAG); }
+    break;
+case 63:
+#line 474 "./ada-exp.y"
+{ write_attribute_calln (ATR_MIN, 2); }
+    break;
+case 64:
+#line 476 "./ada-exp.y"
+{ write_attribute_calln (ATR_MAX, 2); }
+    break;
+case 65:
+#line 478 "./ada-exp.y"
+{ write_attribute_calln (ATR_POS, 1); }
+    break;
+case 66:
+#line 480 "./ada-exp.y"
+{ write_attribute_call1 (ATR_FIRST, yyvsp[0].lval); }
+    break;
+case 67:
+#line 482 "./ada-exp.y"
+{ write_attribute_call1 (ATR_LAST, yyvsp[0].lval); }
+    break;
+case 68:
+#line 484 "./ada-exp.y"
+{ write_attribute_call1 (ATR_LENGTH, yyvsp[0].lval); }
+    break;
+case 69:
+#line 486 "./ada-exp.y"
+{ write_attribute_calln (ATR_VAL, 1); }
+    break;
+case 70:
+#line 488 "./ada-exp.y"
+{ write_attribute_call0 (ATR_MODULUS); }
+    break;
+case 71:
+#line 492 "./ada-exp.y"
+{ yyval.lval = 1; }
+    break;
+case 72:
+#line 494 "./ada-exp.y"
+{ yyval.lval = yyvsp[-1].typed_val.val; }
+    break;
+case 73:
+#line 499 "./ada-exp.y"
+{ write_exp_elt_opcode (OP_TYPE);
+                         write_exp_elt_type (yyvsp[0].tval);
+                         write_exp_elt_opcode (OP_TYPE); }
+    break;
+case 75:
+#line 507 "./ada-exp.y"
+{ write_exp_elt_opcode (OP_TYPE);
+                         write_exp_elt_type (builtin_type_void);
+                         write_exp_elt_opcode (OP_TYPE); }
+    break;
+case 76:
+#line 514 "./ada-exp.y"
+{ write_exp_elt_opcode (OP_LONG);
+                         write_exp_elt_type (yyvsp[0].typed_val.type);
+                         write_exp_elt_longcst ((LONGEST)(yyvsp[0].typed_val.val));
+                         write_exp_elt_opcode (OP_LONG); 
+                       }
+    break;
+case 77:
+#line 522 "./ada-exp.y"
+{ write_exp_elt_opcode (OP_LONG);
+                         if (type_qualifier == NULL) 
+                           write_exp_elt_type (yyvsp[0].typed_val.type);
+                         else
+                           write_exp_elt_type (type_qualifier);
+                         write_exp_elt_longcst 
+                           (convert_char_literal (type_qualifier, yyvsp[0].typed_val.val));
+                         write_exp_elt_opcode (OP_LONG); 
+                       }
+    break;
+case 78:
+#line 534 "./ada-exp.y"
+{ write_exp_elt_opcode (OP_DOUBLE);
+                         write_exp_elt_type (yyvsp[0].typed_val_float.type);
+                         write_exp_elt_dblcst (yyvsp[0].typed_val_float.dval);
+                         write_exp_elt_opcode (OP_DOUBLE); 
+                       }
+    break;
+case 79:
+#line 542 "./ada-exp.y"
+{ write_exp_elt_opcode (OP_LONG);
+                         write_exp_elt_type (builtin_type_int);
+                         write_exp_elt_longcst ((LONGEST)(0));
+                         write_exp_elt_opcode (OP_LONG); 
+                        }
+    break;
+case 80:
+#line 549 "./ada-exp.y"
+{ /* Ada strings are converted into array constants 
+                            a lower bound of 1.  Thus, the array upper bound 
+                            is the string length. */
+                         char *sp = yyvsp[0].sval.ptr; int count;
+                         if (yyvsp[0].sval.length == 0) 
+                           { /* One dummy character for the type */
+                             write_exp_elt_opcode (OP_LONG);
+                             write_exp_elt_type (builtin_type_ada_char);
+                             write_exp_elt_longcst ((LONGEST)(0));
+                             write_exp_elt_opcode (OP_LONG);
+                           }
+                         for (count = yyvsp[0].sval.length; count > 0; count -= 1)
+                           {
+                             write_exp_elt_opcode (OP_LONG);
+                             write_exp_elt_type (builtin_type_ada_char);
+                             write_exp_elt_longcst ((LONGEST)(*sp));
+                             sp += 1;
+                             write_exp_elt_opcode (OP_LONG);
+                           }
+                         write_exp_elt_opcode (OP_ARRAY);
+                         write_exp_elt_longcst ((LONGEST) 1);
+                         write_exp_elt_longcst ((LONGEST) (yyvsp[0].sval.length));
+                         write_exp_elt_opcode (OP_ARRAY); 
+                        }
+    break;
+case 81:
+#line 576 "./ada-exp.y"
+{ error ("NEW not implemented."); }
+    break;
+case 82:
+#line 579 "./ada-exp.y"
+{ write_var_from_name (NULL, yyvsp[0].ssym); }
+    break;
+case 83:
+#line 581 "./ada-exp.y"
+{ write_var_from_name (yyvsp[-1].bval, yyvsp[0].ssym); }
+    break;
+case 84:
+#line 582 "./ada-exp.y"
+{ write_object_renaming (NULL, yyvsp[0].ssym.sym); }
+    break;
+case 85:
+#line 584 "./ada-exp.y"
+{ write_object_renaming (yyvsp[-1].bval, yyvsp[0].ssym.sym); }
+    break;
+case 86:
+#line 587 "./ada-exp.y"
+{ }
+    break;
+case 87:
+#line 588 "./ada-exp.y"
+{ }
+    break;
+case 88:
+#line 589 "./ada-exp.y"
+{ }
+    break;
+case 89:
+#line 593 "./ada-exp.y"
+{ yyval.bval = yyvsp[0].bval; }
+    break;
+case 90:
+#line 595 "./ada-exp.y"
+{ yyval.bval = yyvsp[0].bval; }
+    break;
+case 91:
+#line 599 "./ada-exp.y"
+{ yyval.tval = yyvsp[0].tval; }
+    break;
+case 92:
+#line 600 "./ada-exp.y"
+{ yyval.tval = yyvsp[0].tval; }
+    break;
+case 93:
+#line 602 "./ada-exp.y"
+{ yyval.tval = lookup_pointer_type (yyvsp[-1].tval); }
+    break;
+case 94:
+#line 604 "./ada-exp.y"
+{ yyval.tval = lookup_pointer_type (yyvsp[-1].tval); }
+    break;
+case 95:
+#line 611 "./ada-exp.y"
+{ write_exp_elt_opcode (UNOP_IND); }
+    break;
+case 96:
+#line 613 "./ada-exp.y"
+{ write_exp_elt_opcode (UNOP_ADDR); }
+    break;
+case 97:
+#line 615 "./ada-exp.y"
+{ write_exp_elt_opcode (BINOP_SUBSCRIPT); }
+    break;
+}
+
+#line 705 "/usr/local/share/bison/bison.simple"
+
+\f
+  yyvsp -= yylen;
+  yyssp -= yylen;
+#if YYLSP_NEEDED
+  yylsp -= yylen;
+#endif
+
+#if YYDEBUG
+  if (yydebug)
+    {
+      short *yyssp1 = yyss - 1;
+      YYFPRINTF (stderr, "state stack now");
+      while (yyssp1 != yyssp)
+       YYFPRINTF (stderr, " %d", *++yyssp1);
+      YYFPRINTF (stderr, "\n");
+    }
+#endif
+
+  *++yyvsp = yyval;
+#if YYLSP_NEEDED
+  *++yylsp = yyloc;
+#endif
+
+  /* Now `shift' the result of the reduction.  Determine what state
+     that goes to, based on the state we popped back to and the rule
+     number reduced by.  */
+
+  yyn = yyr1[yyn];
+
+  yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
+  if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+    yystate = yytable[yystate];
+  else
+    yystate = yydefgoto[yyn - YYNTBASE];
+
+  goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+  /* If not already recovering from an error, report this error.  */
+  if (!yyerrstatus)
+    {
+      ++yynerrs;
+
+#ifdef YYERROR_VERBOSE
+      yyn = yypact[yystate];
+
+      if (yyn > YYFLAG && yyn < YYLAST)
+       {
+         YYSIZE_T yysize = 0;
+         char *yymsg;
+         int yyx, yycount;
+
+         yycount = 0;
+         /* Start YYX at -YYN if negative to avoid negative indexes in
+            YYCHECK.  */
+         for (yyx = yyn < 0 ? -yyn : 0;
+              yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++)
+           if (yycheck[yyx + yyn] == yyx)
+             yysize += yystrlen (yytname[yyx]) + 15, yycount++;
+         yysize += yystrlen ("parse error, unexpected ") + 1;
+         yysize += yystrlen (yytname[YYTRANSLATE (yychar)]);
+         yymsg = (char *) YYSTACK_ALLOC (yysize);
+         if (yymsg != 0)
+           {
+             char *yyp = yystpcpy (yymsg, "parse error, unexpected ");
+             yyp = yystpcpy (yyp, yytname[YYTRANSLATE (yychar)]);
+
+             if (yycount < 5)
+               {
+                 yycount = 0;
+                 for (yyx = yyn < 0 ? -yyn : 0;
+                      yyx < (int) (sizeof (yytname) / sizeof (char *));
+                      yyx++)
+                   if (yycheck[yyx + yyn] == yyx)
+                     {
+                       const char *yyq = ! yycount ? ", expecting " : " or ";
+                       yyp = yystpcpy (yyp, yyq);
+                       yyp = yystpcpy (yyp, yytname[yyx]);
+                       yycount++;
+                     }
+               }
+             yyerror (yymsg);
+             YYSTACK_FREE (yymsg);
+           }
+         else
+           yyerror ("parse error; also virtual memory exhausted");
+       }
+      else
+#endif /* defined (YYERROR_VERBOSE) */
+       yyerror ("parse error");
+    }
+  goto yyerrlab1;
+
+
+/*--------------------------------------------------.
+| yyerrlab1 -- error raised explicitly by an action |
+`--------------------------------------------------*/
+yyerrlab1:
+  if (yyerrstatus == 3)
+    {
+      /* If just tried and failed to reuse lookahead token after an
+        error, discard it.  */
+
+      /* return failure if at end of input */
+      if (yychar == YYEOF)
+       YYABORT;
+      YYDPRINTF ((stderr, "Discarding token %d (%s).\n",
+                 yychar, yytname[yychar1]));
+      yychar = YYEMPTY;
+    }
+
+  /* Else will try to reuse lookahead token after shifting the error
+     token.  */
+
+  yyerrstatus = 3;             /* Each real token shifted decrements this */
+
+  goto yyerrhandle;
+
+
+/*-------------------------------------------------------------------.
+| yyerrdefault -- current state does not do anything special for the |
+| error token.                                                       |
+`-------------------------------------------------------------------*/
+yyerrdefault:
+#if 0
+  /* This is wrong; only states that explicitly want error tokens
+     should shift them.  */
+
+  /* If its default is to accept any token, ok.  Otherwise pop it.  */
+  yyn = yydefact[yystate];
+  if (yyn)
+    goto yydefault;
+#endif
+
+
+/*---------------------------------------------------------------.
+| yyerrpop -- pop the current state because it cannot handle the |
+| error token                                                    |
+`---------------------------------------------------------------*/
+yyerrpop:
+  if (yyssp == yyss)
+    YYABORT;
+  yyvsp--;
+  yystate = *--yyssp;
+#if YYLSP_NEEDED
+  yylsp--;
+#endif
+
+#if YYDEBUG
+  if (yydebug)
+    {
+      short *yyssp1 = yyss - 1;
+      YYFPRINTF (stderr, "Error: state stack now");
+      while (yyssp1 != yyssp)
+       YYFPRINTF (stderr, " %d", *++yyssp1);
+      YYFPRINTF (stderr, "\n");
+    }
+#endif
+
+/*--------------.
+| yyerrhandle.  |
+`--------------*/
+yyerrhandle:
+  yyn = yypact[yystate];
+  if (yyn == YYFLAG)
+    goto yyerrdefault;
+
+  yyn += YYTERROR;
+  if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
+    goto yyerrdefault;
+
+  yyn = yytable[yyn];
+  if (yyn < 0)
+    {
+      if (yyn == YYFLAG)
+       goto yyerrpop;
+      yyn = -yyn;
+      goto yyreduce;
+    }
+  else if (yyn == 0)
+    goto yyerrpop;
+
+  if (yyn == YYFINAL)
+    YYACCEPT;
+
+  YYDPRINTF ((stderr, "Shifting error token, "));
+
+  *++yyvsp = yylval;
+#if YYLSP_NEEDED
+  *++yylsp = yylloc;
+#endif
+
+  yystate = yyn;
+  goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here.  |
+`-------------------------------------*/
+yyacceptlab:
+  yyresult = 0;
+  goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here.  |
+`-----------------------------------*/
+yyabortlab:
+  yyresult = 1;
+  goto yyreturn;
+
+/*---------------------------------------------.
+| yyoverflowab -- parser overflow comes here.  |
+`---------------------------------------------*/
+yyoverflowlab:
+  yyerror ("parser stack overflow");
+  yyresult = 2;
+  /* Fall through.  */
+
+yyreturn:
+#ifndef yyoverflow
+  if (yyss != yyssa)
+    YYSTACK_FREE (yyss);
+#endif
+  return yyresult;
+}
+#line 618 "./ada-exp.y"
+
+
+/* yylex defined in ada-lex.c: Reads one token, getting characters */
+/* through lexptr.  */
+
+/* Remap normal flex interface names (yylex) as well as gratuitiously */
+/* global symbol names, so we can have multiple flex-generated parsers */
+/* in gdb.  */
+
+/* (See note above on previous definitions for YACC.) */
+
+#define yy_create_buffer ada_yy_create_buffer
+#define yy_delete_buffer ada_yy_delete_buffer
+#define yy_init_buffer ada_yy_init_buffer
+#define yy_load_buffer_state ada_yy_load_buffer_state
+#define yy_switch_to_buffer ada_yy_switch_to_buffer
+#define yyrestart ada_yyrestart
+#define yytext ada_yytext
+#define yywrap ada_yywrap
+
+/* The following kludge was found necessary to prevent conflicts between */
+/* defs.h and non-standard stdlib.h files.  */
+#define qsort __qsort__dummy
+#include "ada-lex.c"
+
+int
+ada_parse ()
+{
+  lexer_init (yyin);           /* (Re-)initialize lexer. */
+  left_block_context = NULL;
+  type_qualifier = NULL;
+  
+  return _ada_parse ();
+}
+
+void
+yyerror (msg)
+     char *msg;
+{
+  error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
+}
+
+/* The operator name corresponding to operator symbol STRING (adds 
+   quotes and maps to lower-case).  Destroys the previous contents of
+   the array pointed to by STRING.ptr.  Error if STRING does not match
+   a valid Ada operator.  Assumes that STRING.ptr points to a
+   null-terminated string and that, if STRING is a valid operator
+   symbol, the array pointed to by STRING.ptr contains at least
+   STRING.length+3 characters. */ 
+
+static struct stoken
+string_to_operator (string)
+     struct stoken string;
+{
+  int i;
+
+  for (i = 0; ada_opname_table[i].mangled != NULL; i += 1)
+    {
+      if (string.length == strlen (ada_opname_table[i].demangled)-2
+         && strncasecmp (string.ptr, ada_opname_table[i].demangled+1,
+                         string.length) == 0)
+       {
+         strncpy (string.ptr, ada_opname_table[i].demangled,
+                  string.length+2);
+         string.length += 2;
+         return string;
+       }
+    }
+  error ("Invalid operator symbol `%s'", string.ptr);
+}
+
+/* Emit expression to access an instance of SYM, in block BLOCK (if
+ * non-NULL), and with :: qualification ORIG_LEFT_CONTEXT. */
+static void
+write_var_from_sym (orig_left_context, block, sym)
+     struct block* orig_left_context;
+     struct block* block;
+     struct symbol* sym;
+{
+  if (orig_left_context == NULL && symbol_read_needs_frame (sym))
+    {
+      if (innermost_block == 0 ||
+         contained_in (block, innermost_block))
+       innermost_block = block;
+    }
+
+  write_exp_elt_opcode (OP_VAR_VALUE);
+  /* We want to use the selected frame, not another more inner frame
+     which happens to be in the same block */
+  write_exp_elt_block (NULL);
+  write_exp_elt_sym (sym);
+  write_exp_elt_opcode (OP_VAR_VALUE);
+}
+
+/* Emit expression to access an instance of NAME. */
+static void
+write_var_from_name (orig_left_context, name)
+     struct block* orig_left_context;
+     struct name_info name;
+{
+  if (name.msym != NULL)
+    {
+      write_exp_msymbol (name.msym, 
+                        lookup_function_type (builtin_type_int),
+                        builtin_type_int);
+    }
+  else if (name.sym == NULL) 
+    {
+      /* Multiple matches: record name and starting block for later 
+         resolution by ada_resolve. */
+      /*      write_exp_elt_opcode (OP_UNRESOLVED_VALUE); */
+      /* FIXME: OP_UNRESOLVED_VALUE should be defined in expression.h */      
+      write_exp_elt_block (name.block);
+      /*      write_exp_elt_name (name.stoken.ptr); */
+      /* FIXME: write_exp_elt_name should be defined in defs.h, located in parse.c */      
+      /*      write_exp_elt_opcode (OP_UNRESOLVED_VALUE); */
+      /* FIXME: OP_UNRESOLVED_VALUE should be defined in expression.h */      
+    }
+  else
+    write_var_from_sym (orig_left_context, name.block, name.sym);
+}
+
+/* Write a call on parameterless attribute ATR.  */
+
+static void
+write_attribute_call0 (atr)
+     enum ada_attribute atr;
+{
+  /*  write_exp_elt_opcode (OP_ATTRIBUTE); */
+  /* FIXME: OP_ATTRIBUTE should be defined in expression.h */      
+  write_exp_elt_longcst ((LONGEST) 0);
+  write_exp_elt_longcst ((LONGEST) atr);
+  /*  write_exp_elt_opcode (OP_ATTRIBUTE); */
+  /* FIXME: OP_ATTRIBUTE should be defined in expression.h */      
+}
+
+/* Write a call on an attribute ATR with one constant integer
+ * parameter. */
+
+static void
+write_attribute_call1 (atr, arg)
+     enum ada_attribute atr;
+     LONGEST arg;
+{
+  write_exp_elt_opcode (OP_LONG);
+  write_exp_elt_type (builtin_type_int);
+  write_exp_elt_longcst (arg);
+  write_exp_elt_opcode (OP_LONG);
+  /*write_exp_elt_opcode (OP_ATTRIBUTE);*/
+  /* FIXME: OP_ATTRIBUTE should be defined in expression.h */
+  write_exp_elt_longcst ((LONGEST) 1);
+  write_exp_elt_longcst ((LONGEST) atr);
+  /*write_exp_elt_opcode (OP_ATTRIBUTE);*/
+  /* FIXME: OP_ATTRIBUTE should be defined in expression.h */        
+}  
+
+/* Write a call on an attribute ATR with N parameters, whose code must have
+ * been generated previously. */
+
+static void
+write_attribute_calln (atr, n)
+     enum ada_attribute atr;
+     int n;
+{
+  /*write_exp_elt_opcode (OP_ATTRIBUTE);*/
+  /* FIXME: OP_ATTRIBUTE should be defined in expression.h */      
+  write_exp_elt_longcst ((LONGEST) n);
+  write_exp_elt_longcst ((LONGEST) atr);
+  /*  write_exp_elt_opcode (OP_ATTRIBUTE);*/
+  /* FIXME: OP_ATTRIBUTE should be defined in expression.h */        
+}  
+
+/* Emit expression corresponding to the renamed object designated by 
+ * the type RENAMING, which must be the referent of an object renaming
+ * type, in the context of ORIG_LEFT_CONTEXT (?). */
+static void
+write_object_renaming (orig_left_context, renaming)
+     struct block* orig_left_context;
+     struct symbol* renaming;
+{
+  const char* qualification = SYMBOL_NAME (renaming);
+  const char* simple_tail;
+  const char* expr = TYPE_FIELD_NAME (SYMBOL_TYPE (renaming), 0);
+  const char* suffix;
+  char* name;
+  struct symbol* sym;
+  enum { SIMPLE_INDEX, LOWER_BOUND, UPPER_BOUND } slice_state;
+
+  /* if orig_left_context is null, then use the currently selected
+     block, otherwise we might fail our symbol lookup below */
+  if (orig_left_context == NULL)
+    orig_left_context = get_selected_block (NULL);
+
+  for (simple_tail = qualification + strlen (qualification); 
+       simple_tail != qualification; simple_tail -= 1)
+    {
+      if (*simple_tail == '.')
+       {
+         simple_tail += 1;
+         break;
+       } 
+      else if (STREQN (simple_tail, "__", 2))
+       {
+         simple_tail += 2;
+         break;
+       }
+    }
+
+  suffix = strstr (expr, "___XE");
+  if (suffix == NULL)
+    goto BadEncoding;
+
+  name = (char*) xmalloc (suffix - expr + 1);
+  /*  add_name_string_cleanup (name); */
+  /* FIXME: add_name_string_cleanup should be defined in
+     parser-defs.h, implemented in parse.c */    
+  strncpy (name, expr, suffix-expr);
+  name[suffix-expr] = '\000';
+  sym = lookup_symbol (name, orig_left_context, VAR_NAMESPACE, 0, NULL);
+  /*  if (sym == NULL) 
+    error ("Could not find renamed variable: %s", ada_demangle (name));
+  */
+  /* FIXME: ada_demangle should be defined in defs.h, implemented in ada-lang.c */  
+  write_var_from_sym (orig_left_context, block_found, sym);
+
+  suffix += 5;
+  slice_state = SIMPLE_INDEX;
+  while (*suffix == 'X') 
+    {
+      suffix += 1;
+
+      switch (*suffix) {
+      case 'L':
+       slice_state = LOWER_BOUND;
+      case 'S':
+       suffix += 1;
+       if (isdigit (*suffix)) 
+         {
+           char* next;
+           long val = strtol (suffix, &next, 10);
+           if (next == suffix) 
+             goto BadEncoding;
+           suffix = next;
+           write_exp_elt_opcode (OP_LONG);
+           write_exp_elt_type (builtin_type_ada_int);
+           write_exp_elt_longcst ((LONGEST) val);
+           write_exp_elt_opcode (OP_LONG);
+         } 
+       else
+         {
+           const char* end;
+           char* index_name;
+           int index_len;
+           struct symbol* index_sym;
+
+           end = strchr (suffix, 'X');
+           if (end == NULL) 
+             end = suffix + strlen (suffix);
+           
+           index_len = simple_tail - qualification + 2 + (suffix - end) + 1;
+           index_name = (char*) xmalloc (index_len);
+           memset (index_name, '\000', index_len);
+           /*      add_name_string_cleanup (index_name);*/
+           /* FIXME: add_name_string_cleanup should be defined in
+              parser-defs.h, implemented in parse.c */             
+           strncpy (index_name, qualification, simple_tail - qualification);
+           index_name[simple_tail - qualification] = '\000';
+           strncat (index_name, suffix, suffix-end);
+           suffix = end;
+
+           index_sym = 
+             lookup_symbol (index_name, NULL, VAR_NAMESPACE, 0, NULL);
+           if (index_sym == NULL)
+             error ("Could not find %s", index_name);
+           write_var_from_sym (NULL, block_found, sym);
+         }
+       if (slice_state == SIMPLE_INDEX)
+         { 
+           write_exp_elt_opcode (OP_FUNCALL);
+           write_exp_elt_longcst ((LONGEST) 1);
+           write_exp_elt_opcode (OP_FUNCALL);
+         }
+       else if (slice_state == LOWER_BOUND)
+         slice_state = UPPER_BOUND;
+       else if (slice_state == UPPER_BOUND)
+         {
+           write_exp_elt_opcode (TERNOP_SLICE);
+           slice_state = SIMPLE_INDEX;
+         }
+       break;
+
+      case 'R':
+       {
+         struct stoken field_name;
+         const char* end;
+         suffix += 1;
+         
+         if (slice_state != SIMPLE_INDEX)
+           goto BadEncoding;
+         end = strchr (suffix, 'X');
+         if (end == NULL) 
+           end = suffix + strlen (suffix);
+         field_name.length = end - suffix;
+         field_name.ptr = (char*) xmalloc (end - suffix + 1);
+         strncpy (field_name.ptr, suffix, end - suffix);
+         field_name.ptr[end - suffix] = '\000';
+         suffix = end;
+         write_exp_elt_opcode (STRUCTOP_STRUCT);
+         write_exp_string (field_name);
+         write_exp_elt_opcode (STRUCTOP_STRUCT);         
+         break;
+       }
+         
+      default:
+       goto BadEncoding;
+      }
+    }
+  if (slice_state == SIMPLE_INDEX)
+    return;
+
+ BadEncoding:
+  error ("Internal error in encoding of renaming declaration: %s",
+        SYMBOL_NAME (renaming));
+}
+
+/* Convert the character literal whose ASCII value would be VAL to the
+   appropriate value of type TYPE, if there is a translation.
+   Otherwise return VAL.  Hence, in an enumeration type ('A', 'B'), 
+   the literal 'A' (VAL == 65), returns 0. */
+static LONGEST
+convert_char_literal (struct type* type, LONGEST val)
+{
+  char name[7];
+  int f;
+
+  if (type == NULL || TYPE_CODE (type) != TYPE_CODE_ENUM)
+    return val;
+  sprintf (name, "QU%02x", (int) val);
+  for (f = 0; f < TYPE_NFIELDS (type); f += 1) 
+    {
+      if (STREQ (name, TYPE_FIELD_NAME (type, f)))
+       return TYPE_FIELD_BITPOS (type, f);
+    }
+  return val;
+}
diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
new file mode 100644 (file)
index 0000000..7d46dd2
--- /dev/null
@@ -0,0 +1,962 @@
+/* YACC parser for Ada expressions, for GDB.
+   Copyright (C) 1986, 1989, 1990, 1991, 1993, 1994, 1997, 2000
+   Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* Parse an Ada expression from text in a string,
+   and return the result as a  struct expression  pointer.
+   That structure contains arithmetic operations in reverse polish,
+   with constants represented by operations that are followed by special data.
+   See expression.h for the details of the format.
+   What is important here is that it can be built up sequentially
+   during the process of parsing; the lower levels of the tree always
+   come first in the result.
+
+   malloc's and realloc's in this file are transformed to
+   xmalloc and xrealloc respectively by the same sed command in the
+   makefile that remaps any other malloc/realloc inserted by the parser
+   generator.  Doing this with #defines and trying to control the interaction
+   with include files (<malloc.h> and <stdlib.h> for example) just became
+   too messy, particularly when such includes can be inserted at random
+   times by the parser generator.  */
+   
+%{
+
+#include "defs.h"
+#include <string.h>
+#include <ctype.h>
+#include "expression.h"
+#include "value.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "ada-lang.h"
+#include "bfd.h" /* Required by objfiles.h.  */
+#include "symfile.h" /* Required by objfiles.h.  */
+#include "objfiles.h" /* For have_full_symbols and have_partial_symbols */
+#include "frame.h"
+
+/* Remap normal yacc parser interface names (yyparse, yylex, yyerror, etc),
+   as well as gratuitiously global symbol names, so we can have multiple
+   yacc generated parsers in gdb.  These are only the variables
+   produced by yacc.  If other parser generators (bison, byacc, etc) produce
+   additional global names that conflict at link time, then those parser
+   generators need to be fixed instead of adding those names to this list. */
+
+/* NOTE: This is clumsy, especially since BISON and FLEX provide --prefix  
+   options.  I presume we are maintaining it to accommodate systems
+   without BISON?  (PNH) */
+
+#define        yymaxdepth ada_maxdepth
+#define        yyparse _ada_parse      /* ada_parse calls this after  initialization */
+#define        yylex   ada_lex
+#define        yyerror ada_error
+#define        yylval  ada_lval
+#define        yychar  ada_char
+#define        yydebug ada_debug
+#define        yypact  ada_pact        
+#define        yyr1    ada_r1                  
+#define        yyr2    ada_r2                  
+#define        yydef   ada_def         
+#define        yychk   ada_chk         
+#define        yypgo   ada_pgo         
+#define        yyact   ada_act         
+#define        yyexca  ada_exca
+#define yyerrflag ada_errflag
+#define yynerrs        ada_nerrs
+#define        yyps    ada_ps
+#define        yypv    ada_pv
+#define        yys     ada_s
+#define        yy_yys  ada_yys
+#define        yystate ada_state
+#define        yytmp   ada_tmp
+#define        yyv     ada_v
+#define        yy_yyv  ada_yyv
+#define        yyval   ada_val
+#define        yylloc  ada_lloc
+#define yyreds ada_reds                /* With YYDEBUG defined */
+#define yytoks ada_toks                /* With YYDEBUG defined */
+
+#ifndef YYDEBUG
+#define        YYDEBUG 0               /* Default to no yydebug support */
+#endif
+
+struct name_info {
+  struct symbol* sym;
+  struct minimal_symbol* msym;
+  struct block* block;
+  struct stoken stoken;
+};
+
+/* If expression is in the context of TYPE'(...), then TYPE, else
+ * NULL. */
+static struct type* type_qualifier;
+
+int yyparse (void);
+
+static int yylex (void);
+
+void yyerror (char *);
+
+static struct stoken string_to_operator (struct stoken);
+
+static void write_attribute_call0 (enum ada_attribute);
+
+static void write_attribute_call1 (enum ada_attribute, LONGEST);
+
+static void write_attribute_calln (enum ada_attribute, int);
+
+static void write_object_renaming (struct block*, struct symbol*);
+
+static void write_var_from_name (struct block*, struct name_info);
+
+static LONGEST
+convert_char_literal (struct type*, LONGEST);
+%} 
+
+%union
+  {
+    LONGEST lval;
+    struct {
+      LONGEST val;
+      struct type *type;
+    } typed_val;
+    struct {
+      DOUBLEST dval;
+      struct type *type;
+    } typed_val_float;
+    struct type *tval;
+    struct stoken sval;
+    struct name_info ssym;
+    int voidval;
+    struct block *bval;
+    struct internalvar *ivar;
+
+  }
+
+%type <voidval> exp exp1 simple_exp start variable
+%type <tval> type
+
+%token <typed_val> INT NULL_PTR CHARLIT
+%token <typed_val_float> FLOAT
+%token <tval> TYPENAME
+%token <bval> BLOCKNAME
+
+/* Both NAME and TYPENAME tokens represent symbols in the input,
+   and both convey their data as strings.
+   But a TYPENAME is a string that happens to be defined as a typedef
+   or builtin type name (such as int or char)
+   and a NAME is any other symbol.
+   Contexts where this distinction is not important can use the
+   nonterminal "name", which matches either NAME or TYPENAME.  */
+
+%token <sval> STRING 
+%token <ssym> NAME DOT_ID OBJECT_RENAMING
+%type <bval> block 
+%type <lval> arglist tick_arglist
+
+%type <tval> save_qualifier
+
+%token DOT_ALL
+
+/* Special type cases, put in to allow the parser to distinguish different
+   legal basetypes.  */
+%token <lval> LAST REGNAME
+
+%token <ivar> INTERNAL_VARIABLE
+
+%nonassoc ASSIGN
+%left _AND_ OR XOR THEN ELSE
+%left '=' NOTEQUAL '<' '>' LEQ GEQ IN DOTDOT
+%left '@'
+%left '+' '-' '&'
+%left UNARY
+%left '*' '/' MOD REM
+%right STARSTAR ABS NOT
+ /* The following are right-associative only so that reductions at this 
+    precedence have lower precedence than '.' and '('. The syntax still 
+    forces a.b.c, e.g., to be LEFT-associated. */
+%right TICK_ACCESS TICK_ADDRESS TICK_FIRST TICK_LAST TICK_LENGTH
+%right TICK_MAX TICK_MIN TICK_MODULUS
+%right TICK_POS TICK_RANGE TICK_SIZE TICK_TAG TICK_VAL
+%right '.' '(' '[' DOT_ID DOT_ALL
+
+%token ARROW NEW
+
+\f
+%%
+
+start   :      exp1
+       |       type    { write_exp_elt_opcode (OP_TYPE);
+                         write_exp_elt_type ($1);
+                         write_exp_elt_opcode (OP_TYPE); }
+       ;
+
+/* Expressions, including the sequencing operator.  */
+exp1   :       exp
+       |       exp1 ';' exp
+                       { write_exp_elt_opcode (BINOP_COMMA); }
+       ;
+
+/* Expressions, not including the sequencing operator.  */
+simple_exp :   simple_exp DOT_ALL
+                       { write_exp_elt_opcode (UNOP_IND); }
+       ;
+
+simple_exp :   simple_exp DOT_ID
+                       { write_exp_elt_opcode (STRUCTOP_STRUCT);
+                         write_exp_string ($2.stoken);
+                         write_exp_elt_opcode (STRUCTOP_STRUCT); 
+                         }
+       ;
+
+simple_exp :   simple_exp '(' arglist ')'
+                       {
+                         write_exp_elt_opcode (OP_FUNCALL);
+                         write_exp_elt_longcst ($3);
+                         write_exp_elt_opcode (OP_FUNCALL);
+                       }
+       ;
+
+simple_exp :   type '(' exp ')'
+                       {
+                         write_exp_elt_opcode (UNOP_CAST);
+                         write_exp_elt_type ($1);
+                         write_exp_elt_opcode (UNOP_CAST); 
+                       }
+       ;
+
+simple_exp :   type '\'' save_qualifier { type_qualifier = $1; } '(' exp ')'
+                       {
+                         /*                      write_exp_elt_opcode (UNOP_QUAL); */
+                         /* FIXME: UNOP_QUAL should be defined in expression.h */
+                         write_exp_elt_type ($1);
+                         /* write_exp_elt_opcode (UNOP_QUAL); */
+                         /* FIXME: UNOP_QUAL should be defined in expression.h */
+                         type_qualifier = $3;
+                       }
+       ;
+
+save_qualifier :       { $$ = type_qualifier; }
+
+simple_exp :
+               simple_exp '(' exp DOTDOT exp ')'
+                       { write_exp_elt_opcode (TERNOP_SLICE); }
+       ;
+
+simple_exp :   '(' exp1 ')'    { }
+       ;
+
+simple_exp :   variable        
+       ;
+
+simple_exp:    REGNAME /* GDB extension */
+                       { write_exp_elt_opcode (OP_REGISTER);
+                         write_exp_elt_longcst ((LONGEST) $1);
+                         write_exp_elt_opcode (OP_REGISTER); 
+                       }
+       ;
+
+simple_exp:    INTERNAL_VARIABLE /* GDB extension */
+                       { write_exp_elt_opcode (OP_INTERNALVAR);
+                         write_exp_elt_intern ($1);
+                         write_exp_elt_opcode (OP_INTERNALVAR); 
+                       }
+       ;
+
+
+exp    :       simple_exp
+       ;
+
+simple_exp:    LAST
+                       { write_exp_elt_opcode (OP_LAST);
+                         write_exp_elt_longcst ((LONGEST) $1);
+                         write_exp_elt_opcode (OP_LAST); 
+                        }
+       ;
+
+exp    :       exp ASSIGN exp   /* Extension for convenience */
+                       { write_exp_elt_opcode (BINOP_ASSIGN); }
+       ;
+
+exp    :       '-' exp    %prec UNARY
+                       { write_exp_elt_opcode (UNOP_NEG); }
+       ;
+
+exp    :       '+' exp    %prec UNARY
+                       { write_exp_elt_opcode (UNOP_PLUS); }
+       ;
+
+exp     :      NOT exp    %prec UNARY
+                       { write_exp_elt_opcode (UNOP_LOGICAL_NOT); }
+       ;
+
+exp    :       ABS exp    %prec UNARY
+                       { write_exp_elt_opcode (UNOP_ABS); }
+       ;
+
+arglist        :               { $$ = 0; }
+       ;
+
+arglist        :       exp
+                       { $$ = 1; }
+       |       any_name ARROW exp
+                       { $$ = 1; }
+       |       arglist ',' exp
+                       { $$ = $1 + 1; }
+       |       arglist ',' any_name ARROW exp
+                       { $$ = $1 + 1; }
+       ;
+
+exp    :       '{' type '}' exp  %prec '.'
+               /* GDB extension */
+                       { write_exp_elt_opcode (UNOP_MEMVAL);
+                         write_exp_elt_type ($2);
+                         write_exp_elt_opcode (UNOP_MEMVAL); 
+                       }
+       ;
+
+/* Binary operators in order of decreasing precedence.  */
+
+exp    :       exp STARSTAR exp
+                       { write_exp_elt_opcode (BINOP_EXP); }
+       ;
+
+exp    :       exp '*' exp
+                       { write_exp_elt_opcode (BINOP_MUL); }
+       ;
+
+exp    :       exp '/' exp
+                       { write_exp_elt_opcode (BINOP_DIV); }
+       ;
+
+exp    :       exp REM exp /* May need to be fixed to give correct Ada REM */
+                       { write_exp_elt_opcode (BINOP_REM); }
+       ;
+
+exp    :       exp MOD exp
+                       { write_exp_elt_opcode (BINOP_MOD); }
+       ;
+
+exp    :       exp '@' exp     /* GDB extension */
+                       { write_exp_elt_opcode (BINOP_REPEAT); }
+       ;
+
+exp    :       exp '+' exp
+                       { write_exp_elt_opcode (BINOP_ADD); }
+       ;
+
+exp    :       exp '&' exp
+                       { write_exp_elt_opcode (BINOP_CONCAT); }
+       ;
+
+exp    :       exp '-' exp
+                       { write_exp_elt_opcode (BINOP_SUB); }
+       ;
+
+exp    :       exp '=' exp
+                       { write_exp_elt_opcode (BINOP_EQUAL); }
+       ;
+
+exp    :       exp NOTEQUAL exp
+                       { write_exp_elt_opcode (BINOP_NOTEQUAL); }
+       ;
+
+exp    :       exp LEQ exp
+                       { write_exp_elt_opcode (BINOP_LEQ); }
+       ;
+
+exp    :       exp IN exp DOTDOT exp
+                        { /*write_exp_elt_opcode (TERNOP_MBR); */ }
+                          /* FIXME: TERNOP_MBR should be defined in
+                            expression.h */
+        |       exp IN exp TICK_RANGE tick_arglist
+                        { /*write_exp_elt_opcode (BINOP_MBR); */
+                         /* FIXME: BINOP_MBR should be defined in expression.h */
+                         write_exp_elt_longcst ((LONGEST) $5);
+                         /*write_exp_elt_opcode (BINOP_MBR); */
+                       }
+       |       exp IN TYPENAME         %prec TICK_ACCESS
+                        { /*write_exp_elt_opcode (UNOP_MBR); */
+                         /* FIXME: UNOP_QUAL should be defined in expression.h */                        
+                         write_exp_elt_type ($3);
+                         /*                      write_exp_elt_opcode (UNOP_MBR); */
+                         /* FIXME: UNOP_MBR should be defined in expression.h */                         
+                       }
+       |       exp NOT IN exp DOTDOT exp
+                        { /*write_exp_elt_opcode (TERNOP_MBR); */
+                         /* FIXME: TERNOP_MBR should be defined in expression.h */                                               
+                         write_exp_elt_opcode (UNOP_LOGICAL_NOT); 
+                       }
+        |       exp NOT IN exp TICK_RANGE tick_arglist
+                        { /* write_exp_elt_opcode (BINOP_MBR); */
+                         /* FIXME: BINOP_MBR should be defined in expression.h */
+                         write_exp_elt_longcst ((LONGEST) $6);
+                         /*write_exp_elt_opcode (BINOP_MBR);*/
+                         /* FIXME: BINOP_MBR should be defined in expression.h */                        
+                         write_exp_elt_opcode (UNOP_LOGICAL_NOT); 
+                       }
+       |       exp NOT IN TYPENAME     %prec TICK_ACCESS
+                        { /*write_exp_elt_opcode (UNOP_MBR);*/
+                         /* FIXME: UNOP_MBR should be defined in expression.h */                         
+                         write_exp_elt_type ($4);
+                         /*                      write_exp_elt_opcode (UNOP_MBR);*/
+                         /* FIXME: UNOP_MBR should be defined in expression.h */                                                 
+                         write_exp_elt_opcode (UNOP_LOGICAL_NOT); 
+                       }
+       ;
+
+exp    :       exp GEQ exp
+                       { write_exp_elt_opcode (BINOP_GEQ); }
+       ;
+
+exp    :       exp '<' exp
+                       { write_exp_elt_opcode (BINOP_LESS); }
+       ;
+
+exp    :       exp '>' exp
+                       { write_exp_elt_opcode (BINOP_GTR); }
+       ;
+
+exp     :      exp _AND_ exp  /* Fix for Ada elementwise AND. */
+                       { write_exp_elt_opcode (BINOP_BITWISE_AND); }
+        ;
+
+exp     :       exp _AND_ THEN exp     %prec _AND_
+                       { write_exp_elt_opcode (BINOP_LOGICAL_AND); }
+        ;
+
+exp     :      exp OR exp     /* Fix for Ada elementwise OR */
+                       { write_exp_elt_opcode (BINOP_BITWISE_IOR); }
+        ;
+
+exp     :       exp OR ELSE exp        
+                       { write_exp_elt_opcode (BINOP_LOGICAL_OR); }
+        ;
+
+exp     :       exp XOR exp    /* Fix for Ada elementwise XOR */
+                       { write_exp_elt_opcode (BINOP_BITWISE_XOR); }
+        ;
+
+simple_exp :   simple_exp TICK_ACCESS
+                       { write_exp_elt_opcode (UNOP_ADDR); }
+       |       simple_exp TICK_ADDRESS
+                       { write_exp_elt_opcode (UNOP_ADDR);
+                         write_exp_elt_opcode (UNOP_CAST);
+                         write_exp_elt_type (builtin_type_ada_system_address);
+                         write_exp_elt_opcode (UNOP_CAST);
+                       }
+       |       simple_exp TICK_FIRST tick_arglist
+                       { write_attribute_call1 (ATR_FIRST, $3); }
+       |       simple_exp TICK_LAST tick_arglist
+                       { write_attribute_call1 (ATR_LAST, $3); }
+       |       simple_exp TICK_LENGTH tick_arglist
+                       { write_attribute_call1 (ATR_LENGTH, $3); }
+        |       simple_exp TICK_SIZE 
+                       { write_attribute_call0 (ATR_SIZE); }
+       |       simple_exp TICK_TAG
+                       { write_attribute_call0 (ATR_TAG); }
+        |       opt_type_prefix TICK_MIN '(' exp ',' exp ')'
+                       { write_attribute_calln (ATR_MIN, 2); }
+        |       opt_type_prefix TICK_MAX '(' exp ',' exp ')'
+                       { write_attribute_calln (ATR_MAX, 2); }
+       |       opt_type_prefix TICK_POS '(' exp ')'
+                       { write_attribute_calln (ATR_POS, 1); }
+       |       type_prefix TICK_FIRST tick_arglist
+                       { write_attribute_call1 (ATR_FIRST, $3); }
+       |       type_prefix TICK_LAST tick_arglist
+                       { write_attribute_call1 (ATR_LAST, $3); }
+       |       type_prefix TICK_LENGTH tick_arglist
+                       { write_attribute_call1 (ATR_LENGTH, $3); }
+       |       type_prefix TICK_VAL '(' exp ')'
+                       { write_attribute_calln (ATR_VAL, 1); }
+       |       type_prefix TICK_MODULUS 
+                       { write_attribute_call0 (ATR_MODULUS); }
+       ;
+
+tick_arglist :                 %prec '('
+                       { $$ = 1; }
+       |       '(' INT ')'
+                       { $$ = $2.val; }
+       ;
+
+type_prefix :
+               TYPENAME
+                       { write_exp_elt_opcode (OP_TYPE);
+                         write_exp_elt_type ($1);
+                         write_exp_elt_opcode (OP_TYPE); }
+       ;
+
+opt_type_prefix :
+               type_prefix
+       |       /* EMPTY */     
+                       { write_exp_elt_opcode (OP_TYPE);
+                         write_exp_elt_type (builtin_type_void);
+                         write_exp_elt_opcode (OP_TYPE); }
+       ;
+               
+
+exp    :       INT
+                       { write_exp_elt_opcode (OP_LONG);
+                         write_exp_elt_type ($1.type);
+                         write_exp_elt_longcst ((LONGEST)($1.val));
+                         write_exp_elt_opcode (OP_LONG); 
+                       }
+       ;
+
+exp    :       CHARLIT
+                       { write_exp_elt_opcode (OP_LONG);
+                         if (type_qualifier == NULL) 
+                           write_exp_elt_type ($1.type);
+                         else
+                           write_exp_elt_type (type_qualifier);
+                         write_exp_elt_longcst 
+                           (convert_char_literal (type_qualifier, $1.val));
+                         write_exp_elt_opcode (OP_LONG); 
+                       }
+
+                             
+exp    :       FLOAT
+                       { write_exp_elt_opcode (OP_DOUBLE);
+                         write_exp_elt_type ($1.type);
+                         write_exp_elt_dblcst ($1.dval);
+                         write_exp_elt_opcode (OP_DOUBLE); 
+                       }
+       ;
+
+exp    :       NULL_PTR
+                       { write_exp_elt_opcode (OP_LONG);
+                         write_exp_elt_type (builtin_type_int);
+                         write_exp_elt_longcst ((LONGEST)(0));
+                         write_exp_elt_opcode (OP_LONG); 
+                        }
+
+exp    :       STRING
+                       { /* Ada strings are converted into array constants 
+                            a lower bound of 1.  Thus, the array upper bound 
+                            is the string length. */
+                         char *sp = $1.ptr; int count;
+                         if ($1.length == 0) 
+                           { /* One dummy character for the type */
+                             write_exp_elt_opcode (OP_LONG);
+                             write_exp_elt_type (builtin_type_ada_char);
+                             write_exp_elt_longcst ((LONGEST)(0));
+                             write_exp_elt_opcode (OP_LONG);
+                           }
+                         for (count = $1.length; count > 0; count -= 1)
+                           {
+                             write_exp_elt_opcode (OP_LONG);
+                             write_exp_elt_type (builtin_type_ada_char);
+                             write_exp_elt_longcst ((LONGEST)(*sp));
+                             sp += 1;
+                             write_exp_elt_opcode (OP_LONG);
+                           }
+                         write_exp_elt_opcode (OP_ARRAY);
+                         write_exp_elt_longcst ((LONGEST) 1);
+                         write_exp_elt_longcst ((LONGEST) ($1.length));
+                         write_exp_elt_opcode (OP_ARRAY); 
+                        }
+       ;
+
+exp    :       NEW TYPENAME
+                       { error ("NEW not implemented."); }
+       ;
+
+variable:      NAME            { write_var_from_name (NULL, $1); }
+       |       block NAME      /* GDB extension */
+                                { write_var_from_name ($1, $2); }
+       |       OBJECT_RENAMING { write_object_renaming (NULL, $1.sym); }
+       |       block OBJECT_RENAMING 
+                               { write_object_renaming ($1, $2.sym); }
+       ;
+
+any_name :     NAME            { }
+        |       TYPENAME       { }
+        |       OBJECT_RENAMING        { }
+        ;
+
+block  :       BLOCKNAME  /* GDB extension */
+                       { $$ = $1; }
+       |       block BLOCKNAME /* GDB extension */
+                       { $$ = $2; }
+       ;
+
+
+type   :       TYPENAME        { $$ = $1; }
+       |       block TYPENAME  { $$ = $2; }
+       |       TYPENAME TICK_ACCESS 
+                               { $$ = lookup_pointer_type ($1); }
+       |       block TYPENAME TICK_ACCESS
+                               { $$ = lookup_pointer_type ($2); }
+        ;
+
+/* Some extensions borrowed from C, for the benefit of those who find they
+   can't get used to Ada notation in GDB. */
+
+exp    :       '*' exp         %prec '.'
+                       { write_exp_elt_opcode (UNOP_IND); }
+       |       '&' exp         %prec '.'
+                       { write_exp_elt_opcode (UNOP_ADDR); }
+       |       exp '[' exp ']'
+                       { write_exp_elt_opcode (BINOP_SUBSCRIPT); }
+       ;
+
+%%
+
+/* yylex defined in ada-lex.c: Reads one token, getting characters */
+/* through lexptr.  */
+
+/* Remap normal flex interface names (yylex) as well as gratuitiously */
+/* global symbol names, so we can have multiple flex-generated parsers */
+/* in gdb.  */
+
+/* (See note above on previous definitions for YACC.) */
+
+#define yy_create_buffer ada_yy_create_buffer
+#define yy_delete_buffer ada_yy_delete_buffer
+#define yy_init_buffer ada_yy_init_buffer
+#define yy_load_buffer_state ada_yy_load_buffer_state
+#define yy_switch_to_buffer ada_yy_switch_to_buffer
+#define yyrestart ada_yyrestart
+#define yytext ada_yytext
+#define yywrap ada_yywrap
+
+/* The following kludge was found necessary to prevent conflicts between */
+/* defs.h and non-standard stdlib.h files.  */
+#define qsort __qsort__dummy
+#include "ada-lex.c"
+
+int
+ada_parse ()
+{
+  lexer_init (yyin);           /* (Re-)initialize lexer. */
+  left_block_context = NULL;
+  type_qualifier = NULL;
+  
+  return _ada_parse ();
+}
+
+void
+yyerror (msg)
+     char *msg;
+{
+  error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr);
+}
+
+/* The operator name corresponding to operator symbol STRING (adds 
+   quotes and maps to lower-case).  Destroys the previous contents of
+   the array pointed to by STRING.ptr.  Error if STRING does not match
+   a valid Ada operator.  Assumes that STRING.ptr points to a
+   null-terminated string and that, if STRING is a valid operator
+   symbol, the array pointed to by STRING.ptr contains at least
+   STRING.length+3 characters. */ 
+
+static struct stoken
+string_to_operator (string)
+     struct stoken string;
+{
+  int i;
+
+  for (i = 0; ada_opname_table[i].mangled != NULL; i += 1)
+    {
+      if (string.length == strlen (ada_opname_table[i].demangled)-2
+         && strncasecmp (string.ptr, ada_opname_table[i].demangled+1,
+                         string.length) == 0)
+       {
+         strncpy (string.ptr, ada_opname_table[i].demangled,
+                  string.length+2);
+         string.length += 2;
+         return string;
+       }
+    }
+  error ("Invalid operator symbol `%s'", string.ptr);
+}
+
+/* Emit expression to access an instance of SYM, in block BLOCK (if
+ * non-NULL), and with :: qualification ORIG_LEFT_CONTEXT. */
+static void
+write_var_from_sym (orig_left_context, block, sym)
+     struct block* orig_left_context;
+     struct block* block;
+     struct symbol* sym;
+{
+  if (orig_left_context == NULL && symbol_read_needs_frame (sym))
+    {
+      if (innermost_block == 0 ||
+         contained_in (block, innermost_block))
+       innermost_block = block;
+    }
+
+  write_exp_elt_opcode (OP_VAR_VALUE);
+  /* We want to use the selected frame, not another more inner frame
+     which happens to be in the same block */
+  write_exp_elt_block (NULL);
+  write_exp_elt_sym (sym);
+  write_exp_elt_opcode (OP_VAR_VALUE);
+}
+
+/* Emit expression to access an instance of NAME. */
+static void
+write_var_from_name (orig_left_context, name)
+     struct block* orig_left_context;
+     struct name_info name;
+{
+  if (name.msym != NULL)
+    {
+      write_exp_msymbol (name.msym, 
+                        lookup_function_type (builtin_type_int),
+                        builtin_type_int);
+    }
+  else if (name.sym == NULL) 
+    {
+      /* Multiple matches: record name and starting block for later 
+         resolution by ada_resolve. */
+      /*      write_exp_elt_opcode (OP_UNRESOLVED_VALUE); */
+      /* FIXME: OP_UNRESOLVED_VALUE should be defined in expression.h */      
+      write_exp_elt_block (name.block);
+      /*      write_exp_elt_name (name.stoken.ptr); */
+      /* FIXME: write_exp_elt_name should be defined in defs.h, located in parse.c */      
+      /*      write_exp_elt_opcode (OP_UNRESOLVED_VALUE); */
+      /* FIXME: OP_UNRESOLVED_VALUE should be defined in expression.h */      
+    }
+  else
+    write_var_from_sym (orig_left_context, name.block, name.sym);
+}
+
+/* Write a call on parameterless attribute ATR.  */
+
+static void
+write_attribute_call0 (atr)
+     enum ada_attribute atr;
+{
+  /*  write_exp_elt_opcode (OP_ATTRIBUTE); */
+  /* FIXME: OP_ATTRIBUTE should be defined in expression.h */      
+  write_exp_elt_longcst ((LONGEST) 0);
+  write_exp_elt_longcst ((LONGEST) atr);
+  /*  write_exp_elt_opcode (OP_ATTRIBUTE); */
+  /* FIXME: OP_ATTRIBUTE should be defined in expression.h */      
+}
+
+/* Write a call on an attribute ATR with one constant integer
+ * parameter. */
+
+static void
+write_attribute_call1 (atr, arg)
+     enum ada_attribute atr;
+     LONGEST arg;
+{
+  write_exp_elt_opcode (OP_LONG);
+  write_exp_elt_type (builtin_type_int);
+  write_exp_elt_longcst (arg);
+  write_exp_elt_opcode (OP_LONG);
+  /*write_exp_elt_opcode (OP_ATTRIBUTE);*/
+  /* FIXME: OP_ATTRIBUTE should be defined in expression.h */
+  write_exp_elt_longcst ((LONGEST) 1);
+  write_exp_elt_longcst ((LONGEST) atr);
+  /*write_exp_elt_opcode (OP_ATTRIBUTE);*/
+  /* FIXME: OP_ATTRIBUTE should be defined in expression.h */        
+}  
+
+/* Write a call on an attribute ATR with N parameters, whose code must have
+ * been generated previously. */
+
+static void
+write_attribute_calln (atr, n)
+     enum ada_attribute atr;
+     int n;
+{
+  /*write_exp_elt_opcode (OP_ATTRIBUTE);*/
+  /* FIXME: OP_ATTRIBUTE should be defined in expression.h */      
+  write_exp_elt_longcst ((LONGEST) n);
+  write_exp_elt_longcst ((LONGEST) atr);
+  /*  write_exp_elt_opcode (OP_ATTRIBUTE);*/
+  /* FIXME: OP_ATTRIBUTE should be defined in expression.h */        
+}  
+
+/* Emit expression corresponding to the renamed object designated by 
+ * the type RENAMING, which must be the referent of an object renaming
+ * type, in the context of ORIG_LEFT_CONTEXT (?). */
+static void
+write_object_renaming (orig_left_context, renaming)
+     struct block* orig_left_context;
+     struct symbol* renaming;
+{
+  const char* qualification = SYMBOL_NAME (renaming);
+  const char* simple_tail;
+  const char* expr = TYPE_FIELD_NAME (SYMBOL_TYPE (renaming), 0);
+  const char* suffix;
+  char* name;
+  struct symbol* sym;
+  enum { SIMPLE_INDEX, LOWER_BOUND, UPPER_BOUND } slice_state;
+
+  /* if orig_left_context is null, then use the currently selected
+     block, otherwise we might fail our symbol lookup below */
+  if (orig_left_context == NULL)
+    orig_left_context = get_selected_block (NULL);
+
+  for (simple_tail = qualification + strlen (qualification); 
+       simple_tail != qualification; simple_tail -= 1)
+    {
+      if (*simple_tail == '.')
+       {
+         simple_tail += 1;
+         break;
+       } 
+      else if (STREQN (simple_tail, "__", 2))
+       {
+         simple_tail += 2;
+         break;
+       }
+    }
+
+  suffix = strstr (expr, "___XE");
+  if (suffix == NULL)
+    goto BadEncoding;
+
+  name = (char*) malloc (suffix - expr + 1);
+  /*  add_name_string_cleanup (name); */
+  /* FIXME: add_name_string_cleanup should be defined in
+     parser-defs.h, implemented in parse.c */    
+  strncpy (name, expr, suffix-expr);
+  name[suffix-expr] = '\000';
+  sym = lookup_symbol (name, orig_left_context, VAR_NAMESPACE, 0, NULL);
+  /*  if (sym == NULL) 
+    error ("Could not find renamed variable: %s", ada_demangle (name));
+  */
+  /* FIXME: ada_demangle should be defined in defs.h, implemented in ada-lang.c */  
+  write_var_from_sym (orig_left_context, block_found, sym);
+
+  suffix += 5;
+  slice_state = SIMPLE_INDEX;
+  while (*suffix == 'X') 
+    {
+      suffix += 1;
+
+      switch (*suffix) {
+      case 'L':
+       slice_state = LOWER_BOUND;
+      case 'S':
+       suffix += 1;
+       if (isdigit (*suffix)) 
+         {
+           char* next;
+           long val = strtol (suffix, &next, 10);
+           if (next == suffix) 
+             goto BadEncoding;
+           suffix = next;
+           write_exp_elt_opcode (OP_LONG);
+           write_exp_elt_type (builtin_type_ada_int);
+           write_exp_elt_longcst ((LONGEST) val);
+           write_exp_elt_opcode (OP_LONG);
+         } 
+       else
+         {
+           const char* end;
+           char* index_name;
+           int index_len;
+           struct symbol* index_sym;
+
+           end = strchr (suffix, 'X');
+           if (end == NULL) 
+             end = suffix + strlen (suffix);
+           
+           index_len = simple_tail - qualification + 2 + (suffix - end) + 1;
+           index_name = (char*) malloc (index_len);
+           memset (index_name, '\000', index_len);
+           /*      add_name_string_cleanup (index_name);*/
+           /* FIXME: add_name_string_cleanup should be defined in
+              parser-defs.h, implemented in parse.c */             
+           strncpy (index_name, qualification, simple_tail - qualification);
+           index_name[simple_tail - qualification] = '\000';
+           strncat (index_name, suffix, suffix-end);
+           suffix = end;
+
+           index_sym = 
+             lookup_symbol (index_name, NULL, VAR_NAMESPACE, 0, NULL);
+           if (index_sym == NULL)
+             error ("Could not find %s", index_name);
+           write_var_from_sym (NULL, block_found, sym);
+         }
+       if (slice_state == SIMPLE_INDEX)
+         { 
+           write_exp_elt_opcode (OP_FUNCALL);
+           write_exp_elt_longcst ((LONGEST) 1);
+           write_exp_elt_opcode (OP_FUNCALL);
+         }
+       else if (slice_state == LOWER_BOUND)
+         slice_state = UPPER_BOUND;
+       else if (slice_state == UPPER_BOUND)
+         {
+           write_exp_elt_opcode (TERNOP_SLICE);
+           slice_state = SIMPLE_INDEX;
+         }
+       break;
+
+      case 'R':
+       {
+         struct stoken field_name;
+         const char* end;
+         suffix += 1;
+         
+         if (slice_state != SIMPLE_INDEX)
+           goto BadEncoding;
+         end = strchr (suffix, 'X');
+         if (end == NULL) 
+           end = suffix + strlen (suffix);
+         field_name.length = end - suffix;
+         field_name.ptr = (char*) malloc (end - suffix + 1);
+         strncpy (field_name.ptr, suffix, end - suffix);
+         field_name.ptr[end - suffix] = '\000';
+         suffix = end;
+         write_exp_elt_opcode (STRUCTOP_STRUCT);
+         write_exp_string (field_name);
+         write_exp_elt_opcode (STRUCTOP_STRUCT);         
+         break;
+       }
+         
+      default:
+       goto BadEncoding;
+      }
+    }
+  if (slice_state == SIMPLE_INDEX)
+    return;
+
+ BadEncoding:
+  error ("Internal error in encoding of renaming declaration: %s",
+        SYMBOL_NAME (renaming));
+}
+
+/* Convert the character literal whose ASCII value would be VAL to the
+   appropriate value of type TYPE, if there is a translation.
+   Otherwise return VAL.  Hence, in an enumeration type ('A', 'B'), 
+   the literal 'A' (VAL == 65), returns 0. */
+static LONGEST
+convert_char_literal (struct type* type, LONGEST val)
+{
+  char name[7];
+  int f;
+
+  if (type == NULL || TYPE_CODE (type) != TYPE_CODE_ENUM)
+    return val;
+  sprintf (name, "QU%02x", (int) val);
+  for (f = 0; f < TYPE_NFIELDS (type); f += 1) 
+    {
+      if (STREQ (name, TYPE_FIELD_NAME (type, f)))
+       return TYPE_FIELD_BITPOS (type, f);
+    }
+  return val;
+}
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
new file mode 100644 (file)
index 0000000..2c4f1d9
--- /dev/null
@@ -0,0 +1,8626 @@
+/* Ada language support routines for GDB, the GNU debugger.  Copyright
+   1992, 1993, 1994, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include "demangle.h"
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "gdbcmd.h"
+#include "expression.h"
+#include "parser-defs.h"
+#include "language.h"
+#include "c-lang.h"
+#include "inferior.h"
+#include "symfile.h"
+#include "objfiles.h"
+#include "breakpoint.h"
+#include "gdbcore.h"
+#include "ada-lang.h"
+#ifdef UI_OUT
+#include "ui-out.h"
+#endif
+
+struct cleanup* unresolved_names;
+
+void extract_string (CORE_ADDR addr, char *buf);
+
+static struct type * ada_create_fundamental_type (struct objfile *, int);
+
+static void modify_general_field (char *, LONGEST, int, int);
+
+static struct type* desc_base_type (struct type*);
+
+static struct type* desc_bounds_type (struct type*);
+
+static struct value* desc_bounds (struct value*);
+
+static int fat_pntr_bounds_bitpos (struct type*);
+
+static int fat_pntr_bounds_bitsize (struct type*);
+
+static struct type* desc_data_type (struct type*);
+
+static struct value* desc_data (struct value*);
+
+static int fat_pntr_data_bitpos (struct type*);
+
+static int fat_pntr_data_bitsize (struct type*);
+
+static struct value* desc_one_bound (struct value*, int, int);
+
+static int desc_bound_bitpos (struct type*, int, int);
+
+static int desc_bound_bitsize (struct type*, int, int);
+
+static struct type*  desc_index_type (struct type*, int);
+
+static int desc_arity (struct type*);
+
+static int ada_type_match (struct type*, struct type*, int);
+
+static int ada_args_match (struct symbol*, struct value**, int);
+
+static struct value* place_on_stack (struct value*, CORE_ADDR*);
+
+static struct value* convert_actual (struct value*, struct type*, CORE_ADDR*);
+
+static struct value* make_array_descriptor (struct type*, struct value*, CORE_ADDR*);
+
+static void ada_add_block_symbols (struct block*, const char*,
+                                  namespace_enum, struct objfile*, int);
+
+static void fill_in_ada_prototype (struct symbol*);
+
+static int is_nonfunction (struct symbol**, int);
+
+static void add_defn_to_vec (struct symbol*, struct block*);
+
+static struct partial_symbol* 
+ada_lookup_partial_symbol (struct partial_symtab*, const char*, 
+                          int, namespace_enum, int);
+
+static struct symtab* symtab_for_sym (struct symbol*);
+
+static struct value* ada_resolve_subexp (struct expression**, int*, int, struct type*);
+
+static void replace_operator_with_call (struct expression**, int, int, int,
+                                       struct symbol*, struct block*);
+
+static int possible_user_operator_p (enum exp_opcode, struct value**);
+
+static const char* ada_op_name (enum exp_opcode);
+
+static int numeric_type_p (struct type*);
+
+static int integer_type_p (struct type*);
+
+static int scalar_type_p (struct type*);
+
+static int discrete_type_p (struct type*);
+
+static char* extended_canonical_line_spec (struct symtab_and_line, const char*);
+
+static struct value* evaluate_subexp (struct type*, struct expression*, int*, enum noside);
+
+static struct value* evaluate_subexp_type (struct expression*, int*);
+
+static struct type * ada_create_fundamental_type (struct objfile*, int);
+
+static int  is_dynamic_field (struct type *, int);
+
+static struct type*
+to_fixed_variant_branch_type (struct type*, char*, CORE_ADDR, struct value*);
+
+static struct type* to_fixed_range_type (char*, struct value*, struct objfile*);
+
+static struct type* to_static_fixed_type (struct type*);
+
+static struct value* unwrap_value (struct value*);
+
+static struct type* packed_array_type (struct type*, long*);
+
+static struct type* decode_packed_array_type (struct type*);
+
+static struct value* decode_packed_array (struct value*);
+
+static struct value* value_subscript_packed (struct value*, int, struct value**);
+
+static struct value* coerce_unspec_val_to_type (struct value*, long, struct type*);
+
+static struct value* get_var_value (char*, char*);
+
+static int lesseq_defined_than (struct symbol*, struct symbol*);
+
+static int equiv_types (struct type*, struct type*);
+
+static int is_name_suffix (const char*);
+
+static int wild_match (const char*, int, const char*);
+
+static struct symtabs_and_lines find_sal_from_funcs_and_line (const char*, int, struct symbol**, int);
+
+static int
+find_line_in_linetable (struct linetable*, int, struct symbol**, int, int*);
+
+static int find_next_line_in_linetable (struct linetable*, int, int, int);
+
+static struct symtabs_and_lines all_sals_for_line (const char*, int, char***);
+
+static void read_all_symtabs (const char*);
+
+static int is_plausible_func_for_line (struct symbol*, int);
+
+static struct value*  ada_coerce_ref (struct value*);
+
+static struct value* value_pos_atr (struct value*);
+
+static struct value* value_val_atr (struct type*, struct value*);
+
+static struct symbol* standard_lookup (const char*, namespace_enum);
+
+extern void markTimeStart (int index);
+extern void markTimeStop (int index);
+
+\f
+
+/* Maximum-sized dynamic type. */
+static unsigned int varsize_limit;
+
+static const char* ada_completer_word_break_characters =
+  " \t\n!@#$%^&*()+=|~`}{[]\";:?/,-";
+
+/* The name of the symbol to use to get the name of the main subprogram */
+#define ADA_MAIN_PROGRAM_SYMBOL_NAME "__gnat_ada_main_program_name"
+
+                               /* Utilities */
+
+/* extract_string
+ *
+ * read the string located at ADDR from the inferior and store the
+ * result into BUF
+ */
+void
+extract_string (CORE_ADDR addr, char *buf)
+{
+   int char_index = 0;
+
+   /* Loop, reading one byte at a time, until we reach the '\000' 
+      end-of-string marker */
+   do
+   {
+     target_read_memory (addr + char_index * sizeof (char), 
+                         buf + char_index * sizeof (char), 
+                         sizeof (char));
+     char_index++;
+   }
+   while (buf[char_index - 1] != '\000');
+}
+
+/* Assuming *OLD_VECT points to an array of *SIZE objects of size
+   ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects,
+   updating *OLD_VECT and *SIZE as necessary. */
+
+void
+grow_vect (old_vect, size, min_size, element_size)
+     void** old_vect;
+     size_t* size;
+     size_t min_size;
+     int element_size;
+{
+  if (*size < min_size) {
+    *size *= 2;
+    if (*size < min_size)
+      *size = min_size;
+    *old_vect = xrealloc (*old_vect, *size * element_size);
+  }
+}
+
+/* True (non-zero) iff TARGET matches FIELD_NAME up to any trailing
+   suffix of FIELD_NAME beginning "___" */
+
+static int
+field_name_match (field_name, target)
+     const char *field_name;
+     const char *target;
+{
+  int len = strlen (target);
+  return 
+    STREQN (field_name, target, len) 
+    && (field_name[len] == '\0' 
+       || (STREQN (field_name + len, "___", 3)
+          && ! STREQ (field_name + strlen (field_name) - 6, "___XVN")));
+}
+
+
+/* The length of the prefix of NAME prior to any "___" suffix. */
+
+int
+ada_name_prefix_len (name)
+     const char* name;
+{
+  if (name == NULL)
+    return 0;
+  else 
+    {
+      const char* p = strstr (name, "___");
+      if (p == NULL)
+       return strlen (name);
+      else
+       return p - name;
+    }
+}
+
+/* SUFFIX is a suffix of STR. False if STR is null. */
+static int
+is_suffix (const char* str, const char* suffix)
+{
+  int len1, len2;
+  if (str == NULL)
+    return 0;
+  len1 = strlen (str);
+  len2 = strlen (suffix);
+  return (len1 >= len2 && STREQ (str + len1 - len2, suffix));
+}
+
+/* Create a value of type TYPE whose contents come from VALADDR, if it
+ * is non-null, and whose memory address (in the inferior) is
+ * ADDRESS. */
+struct value*
+value_from_contents_and_address (type, valaddr, address)
+     struct type* type;
+     char* valaddr;
+     CORE_ADDR address;
+{
+  struct value* v = allocate_value (type);
+  if (valaddr == NULL) 
+    VALUE_LAZY (v) = 1;
+  else
+    memcpy (VALUE_CONTENTS_RAW (v), valaddr, TYPE_LENGTH (type));
+  VALUE_ADDRESS (v) = address;
+  if (address != 0)
+    VALUE_LVAL (v) = lval_memory;
+  return v;
+}
+
+/* The contents of value VAL, beginning at offset OFFSET, treated as a
+   value of type TYPE.  The result is an lval in memory if VAL is. */
+
+static struct value*
+coerce_unspec_val_to_type (val, offset, type)
+     struct value* val;
+     long offset;
+     struct type *type;
+{
+  CHECK_TYPEDEF (type);
+  if (VALUE_LVAL (val) == lval_memory)
+    return value_at_lazy (type,
+      VALUE_ADDRESS (val) + VALUE_OFFSET (val) + offset, NULL);
+  else 
+    {
+      struct value* result = allocate_value (type);
+      VALUE_LVAL (result) = not_lval;
+      if (VALUE_ADDRESS (val) == 0) 
+       memcpy (VALUE_CONTENTS_RAW (result), VALUE_CONTENTS (val) + offset,
+               TYPE_LENGTH (type) > TYPE_LENGTH (VALUE_TYPE (val)) 
+               ? TYPE_LENGTH (VALUE_TYPE (val)) : TYPE_LENGTH (type));
+      else 
+       {
+         VALUE_ADDRESS (result) = 
+           VALUE_ADDRESS (val) + VALUE_OFFSET (val) + offset;
+         VALUE_LAZY (result) = 1;
+       }
+      return result;
+    }
+}
+
+static char*
+cond_offset_host (valaddr, offset)
+     char* valaddr;
+     long offset;
+{
+  if (valaddr == NULL)
+    return NULL;
+  else
+    return valaddr + offset;
+}
+
+static CORE_ADDR
+cond_offset_target (address, offset)
+     CORE_ADDR address;
+     long offset;
+{
+  if (address == 0)
+    return 0;
+  else 
+    return address + offset;
+}
+
+/* Perform execute_command on the result of concatenating all
+   arguments up to NULL. */
+static void
+do_command (const char* arg, ...)
+{
+  int len;
+  char* cmd;
+  const char* s;
+  va_list ap;
+
+  va_start (ap, arg);
+  len = 0;
+  s = arg;
+  cmd = "";
+  for (; s != NULL; s = va_arg (ap, const char*)) 
+    {
+      char* cmd1;
+      len += strlen (s);
+      cmd1 = alloca (len+1);
+      strcpy (cmd1, cmd);
+      strcat (cmd1, s);
+      cmd = cmd1;
+    }
+  va_end (ap);
+  execute_command (cmd, 0);
+}
+
+\f
+                               /* Language Selection */
+
+/* If the main program is in Ada, return language_ada, otherwise return LANG
+   (the main program is in Ada iif the adainit symbol is found).
+
+   MAIN_PST is not used. */
+   
+enum language
+ada_update_initial_language (lang, main_pst)
+     enum language lang;
+     struct partial_symtab* main_pst;
+{
+  if (lookup_minimal_symbol ("adainit", (const char*) NULL,
+                            (struct objfile*) NULL) != NULL)
+    /*    return language_ada; */
+    /* FIXME: language_ada should be defined in defs.h */
+    return language_unknown;
+
+  return lang;
+}
+      
+\f
+                               /* Symbols */
+
+/* Table of Ada operators and their GNAT-mangled names.  Last entry is pair 
+   of NULLs. */
+
+const struct ada_opname_map ada_opname_table[] =
+{
+  { "Oadd", "\"+\"", BINOP_ADD },
+  { "Osubtract", "\"-\"", BINOP_SUB },
+  { "Omultiply", "\"*\"", BINOP_MUL },
+  { "Odivide", "\"/\"", BINOP_DIV },
+  { "Omod", "\"mod\"", BINOP_MOD },
+  { "Orem", "\"rem\"", BINOP_REM },
+  { "Oexpon", "\"**\"", BINOP_EXP },
+  { "Olt", "\"<\"", BINOP_LESS },
+  { "Ole", "\"<=\"", BINOP_LEQ },
+  { "Ogt", "\">\"", BINOP_GTR },
+  { "Oge", "\">=\"", BINOP_GEQ },
+  { "Oeq", "\"=\"", BINOP_EQUAL },
+  { "One", "\"/=\"", BINOP_NOTEQUAL },
+  { "Oand", "\"and\"", BINOP_BITWISE_AND },
+  { "Oor", "\"or\"", BINOP_BITWISE_IOR },
+  { "Oxor", "\"xor\"", BINOP_BITWISE_XOR },
+  { "Oconcat", "\"&\"", BINOP_CONCAT },
+  { "Oabs", "\"abs\"", UNOP_ABS },
+  { "Onot", "\"not\"", UNOP_LOGICAL_NOT },
+  { "Oadd", "\"+\"", UNOP_PLUS },
+  { "Osubtract", "\"-\"", UNOP_NEG },
+  { NULL, NULL }
+};
+
+/* True if STR should be suppressed in info listings. */
+static int
+is_suppressed_name (str) 
+     const char* str;
+{
+  if (STREQN (str, "_ada_", 5))
+    str += 5;
+  if (str[0] == '_' || str[0] == '\000')
+    return 1;
+  else
+    {
+      const char* p;
+      const char* suffix = strstr (str, "___");
+      if (suffix != NULL && suffix[3] != 'X')
+       return 1;
+      if (suffix == NULL)
+       suffix = str + strlen (str);
+      for (p = suffix-1; p != str; p -= 1)
+       if (isupper (*p))
+         {
+           int i;
+           if (p[0] == 'X' && p[-1] != '_')
+             goto OK;
+           if (*p != 'O')
+             return 1;
+           for (i = 0; ada_opname_table[i].mangled != NULL; i += 1)
+             if (STREQN (ada_opname_table[i].mangled, p, 
+                         strlen (ada_opname_table[i].mangled)))
+               goto OK;
+           return 1;
+         OK: ;
+         }
+      return 0;
+    }
+}
+
+/* The "mangled" form of DEMANGLED, according to GNAT conventions.
+ * The result is valid until the next call to ada_mangle. */
+char *
+ada_mangle (demangled)
+     const char* demangled;
+{
+  static char* mangling_buffer = NULL;
+  static size_t mangling_buffer_size = 0;
+  const char* p;
+  int k;
+  
+  if (demangled == NULL)
+    return NULL;
+
+  GROW_VECT (mangling_buffer, mangling_buffer_size, 2*strlen (demangled) + 10);
+
+  k = 0;
+  for (p = demangled; *p != '\0'; p += 1)
+    {
+      if (*p == '.') 
+       {
+         mangling_buffer[k] = mangling_buffer[k+1] = '_';
+         k += 2;
+       }
+      else if (*p == '"')
+       {
+         const struct ada_opname_map* mapping;
+
+         for (mapping = ada_opname_table;
+              mapping->mangled != NULL && 
+              ! STREQN (mapping->demangled, p, strlen (mapping->demangled));
+              p += 1)
+           ;
+         if (mapping->mangled == NULL)
+           error ("invalid Ada operator name: %s", p);
+         strcpy (mangling_buffer+k, mapping->mangled);
+         k += strlen (mapping->mangled);
+         break;
+       }
+      else 
+       {
+         mangling_buffer[k] = *p;
+         k += 1;
+       }
+    }
+
+  mangling_buffer[k] = '\0';
+  return mangling_buffer;
+}
+
+/* Return NAME folded to lower case, or, if surrounded by single
+ * quotes, unfolded, but with the quotes stripped away.  Result good
+ * to next call. */
+char*
+ada_fold_name (const char* name)
+{
+  static char* fold_buffer = NULL;
+  static size_t fold_buffer_size = 0;
+
+  int len = strlen (name);
+  GROW_VECT (fold_buffer, fold_buffer_size, len+1);
+
+  if (name[0] == '\'')
+    {
+      strncpy (fold_buffer, name+1, len-2);
+      fold_buffer[len-2] = '\000';
+    }
+  else
+    {
+      int i;
+      for (i = 0; i <= len; i += 1)
+       fold_buffer[i] = tolower (name[i]);
+    }
+
+  return fold_buffer;
+}
+
+/* Demangle: 
+     1. Discard final __{DIGIT}+ or ${DIGIT}+
+     2. Convert other instances of embedded "__" to `.'.
+     3. Discard leading _ada_.
+     4. Convert operator names to the appropriate quoted symbols.
+     5. Remove everything after first ___ if it is followed by 
+        'X'.
+     6. Replace TK__ with __, and a trailing B or TKB with nothing.
+     7. Put symbols that should be suppressed in <...> brackets.
+     8. Remove trailing X[bn]* suffix (indicating names in package bodies).
+   The resulting string is valid until the next call of ada_demangle.
+  */
+
+char *
+ada_demangle (mangled)
+     const char* mangled;
+{
+  int i, j;
+  int len0;
+  const char* p;
+  char* demangled;
+  int at_start_name;
+  static char* demangling_buffer = NULL;
+  static size_t demangling_buffer_size = 0;
+  
+  if (STREQN (mangled, "_ada_", 5))
+    mangled += 5;
+
+  if (mangled[0] == '_' || mangled[0] == '<')
+    goto Suppress;
+
+  p = strstr (mangled, "___");
+  if (p == NULL)
+    len0 = strlen (mangled);
+  else 
+    {
+      if (p[3] == 'X')
+       len0 = p - mangled;
+      else
+       goto Suppress;
+    }
+  if (len0 > 3 && STREQ (mangled + len0 - 3, "TKB"))
+    len0 -= 3;
+  if (len0 > 1 && STREQ (mangled + len0 - 1, "B"))
+    len0 -= 1;
+
+  /* Make demangled big enough for possible expansion by operator name. */
+  GROW_VECT (demangling_buffer, demangling_buffer_size, 2*len0+1);
+  demangled = demangling_buffer;
+
+  if (isdigit (mangled[len0 - 1])) {
+    for (i = len0-2; i >= 0 && isdigit (mangled[i]); i -= 1)
+      ;
+    if (i > 1 && mangled[i] == '_' && mangled[i-1] == '_')
+      len0 = i - 1;
+    else if (mangled[i] == '$')
+      len0 = i;
+  }
+
+  for (i = 0, j = 0; i < len0 && ! isalpha (mangled[i]); i += 1, j += 1)
+    demangled[j] = mangled[i];
+
+  at_start_name = 1;
+  while (i < len0)
+    {
+      if (at_start_name && mangled[i] == 'O')
+       {
+         int k;
+         for (k = 0; ada_opname_table[k].mangled != NULL; k += 1)
+           {
+             int op_len = strlen (ada_opname_table[k].mangled); 
+             if (STREQN (ada_opname_table[k].mangled+1, mangled+i+1, op_len-1)
+                 && ! isalnum (mangled[i + op_len]))
+               {
+                 strcpy (demangled + j, ada_opname_table[k].demangled);
+                 at_start_name = 0;
+                 i += op_len;
+                 j += strlen (ada_opname_table[k].demangled);
+                 break;
+               }
+           }
+         if (ada_opname_table[k].mangled != NULL)
+           continue;
+       }
+      at_start_name = 0;
+
+      if (i < len0-4 && STREQN (mangled+i, "TK__", 4))
+       i += 2;
+      if (mangled[i] == 'X' && i != 0 && isalnum (mangled[i-1]))
+       {
+         do
+           i += 1;
+         while (i < len0 && (mangled[i] == 'b' || mangled[i] == 'n'));
+         if (i < len0)
+           goto Suppress;
+       }
+      else if (i < len0-2 && mangled[i] == '_' && mangled[i+1] == '_') 
+       {
+         demangled[j] = '.';
+         at_start_name = 1;
+         i += 2; j += 1;
+       }
+      else
+       {
+         demangled[j] = mangled[i];
+         i += 1;  j += 1;
+       }
+    }
+  demangled[j] = '\000';
+
+  for (i = 0; demangled[i] != '\0'; i += 1)
+    if (isupper (demangled[i]) || demangled[i] == ' ')
+      goto Suppress;
+
+  return demangled;
+
+Suppress:
+  GROW_VECT (demangling_buffer, demangling_buffer_size, 
+            strlen (mangled) + 3);  
+  demangled = demangling_buffer;
+  if (mangled[0] == '<')
+    strcpy (demangled, mangled);
+  else
+    sprintf (demangled, "<%s>", mangled);
+  return demangled;
+
+}
+
+/* Returns non-zero iff SYM_NAME matches NAME, ignoring any trailing
+ * suffixes that encode debugging information or leading _ada_ on
+ * SYM_NAME (see is_name_suffix commentary for the debugging
+ * information that is ignored).  If WILD, then NAME need only match a
+ * suffix of SYM_NAME minus the same suffixes. Also returns 0 if
+ * either argument is NULL. */
+
+int
+ada_match_name (sym_name, name, wild)
+     const char* sym_name;
+     const char* name;
+     int wild;
+{
+  if (sym_name == NULL || name == NULL)
+    return 0;
+  else if (wild)
+    return wild_match (name, strlen (name), sym_name);
+  else {
+    int len_name = strlen (name);
+    return (STREQN (sym_name, name, len_name) 
+           && is_name_suffix (sym_name+len_name))
+      ||   (STREQN (sym_name, "_ada_", 5) 
+           && STREQN (sym_name+5, name, len_name)
+           && is_name_suffix (sym_name+len_name+5));
+  }
+}
+
+/* True (non-zero) iff in Ada mode, the symbol SYM should be
+   suppressed in info listings. */
+
+int
+ada_suppress_symbol_printing (sym)
+     struct symbol *sym;
+{
+  if (SYMBOL_NAMESPACE (sym) == STRUCT_NAMESPACE)
+    return 1;
+  else 
+    return is_suppressed_name (SYMBOL_NAME (sym));
+}
+
+\f
+                               /* Arrays */
+
+/* Names of MAX_ADA_DIMENS bounds in P_BOUNDS fields of 
+   array descriptors.  */
+
+static char* bound_name[] = {
+  "LB0", "UB0", "LB1", "UB1", "LB2", "UB2", "LB3", "UB3", 
+  "LB4", "UB4", "LB5", "UB5", "LB6", "UB6", "LB7", "UB7"
+};
+
+/* Maximum number of array dimensions we are prepared to handle.  */
+
+#define MAX_ADA_DIMENS (sizeof(bound_name) / (2*sizeof(char*)))
+
+/* Like modify_field, but allows bitpos > wordlength. */
+
+static void
+modify_general_field (addr, fieldval, bitpos, bitsize)
+     char *addr;
+     LONGEST fieldval;
+     int bitpos, bitsize;
+{
+  modify_field (addr + sizeof (LONGEST) * bitpos / (8 * sizeof (LONGEST)), 
+               fieldval, bitpos % (8 * sizeof (LONGEST)), 
+               bitsize);
+}
+
+
+/* The desc_* routines return primitive portions of array descriptors 
+   (fat pointers). */
+
+/* The descriptor or array type, if any, indicated by TYPE; removes
+   level of indirection, if needed. */
+static struct type*
+desc_base_type (type)
+     struct type* type;
+{
+  if (type == NULL)
+    return NULL;
+  CHECK_TYPEDEF (type);
+  if (type != NULL && TYPE_CODE (type) == TYPE_CODE_PTR)
+    return check_typedef (TYPE_TARGET_TYPE (type));
+  else
+    return type;
+}
+
+/* True iff TYPE indicates a "thin" array pointer type. */
+static int
+is_thin_pntr (struct type* type)
+{
+  return 
+    is_suffix (ada_type_name (desc_base_type (type)), "___XUT")
+    || is_suffix (ada_type_name (desc_base_type (type)), "___XUT___XVE");
+}
+
+/* The descriptor type for thin pointer type TYPE. */
+static struct type*
+thin_descriptor_type (struct type* type)
+{
+  struct type* base_type = desc_base_type (type);
+  if (base_type == NULL)
+    return NULL;
+  if (is_suffix (ada_type_name (base_type), "___XVE"))
+    return base_type;
+  else 
+    {
+      struct type* alt_type = 
+       ada_find_parallel_type (base_type, "___XVE");
+      if (alt_type == NULL)
+       return base_type;
+      else
+       return alt_type;
+    }
+}
+
+/* A pointer to the array data for thin-pointer value VAL. */
+static struct value*
+thin_data_pntr (struct value* val)
+{
+  struct type* type = VALUE_TYPE (val);
+  if (TYPE_CODE (type) == TYPE_CODE_PTR)
+    return value_cast (desc_data_type (thin_descriptor_type (type)), 
+                      value_copy (val));
+  else 
+    return value_from_longest (desc_data_type (thin_descriptor_type (type)),
+                              VALUE_ADDRESS (val) + VALUE_OFFSET (val));
+}
+
+/* True iff TYPE indicates a "thick" array pointer type. */
+static int
+is_thick_pntr (struct type* type) 
+{
+  type = desc_base_type (type);
+  return (type != NULL && TYPE_CODE (type) == TYPE_CODE_STRUCT
+         && lookup_struct_elt_type (type, "P_BOUNDS", 1) != NULL);
+}
+
+/* If TYPE is the type of an array descriptor (fat or thin pointer) or a 
+   pointer to one, the type of its bounds data; otherwise, NULL. */
+static struct type*
+desc_bounds_type (type)
+     struct type* type;
+{
+  struct type* r;
+
+  type = desc_base_type (type);
+
+  if (type == NULL)
+    return NULL;
+  else if (is_thin_pntr (type))
+    {
+      type = thin_descriptor_type (type);
+      if (type == NULL)
+       return NULL;
+      r = lookup_struct_elt_type (type, "BOUNDS", 1);
+      if (r != NULL)
+       return check_typedef (r);
+    }
+  else if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
+    {
+      r = lookup_struct_elt_type (type, "P_BOUNDS", 1);
+      if (r != NULL)
+       return check_typedef (TYPE_TARGET_TYPE (check_typedef (r)));
+    }
+  return NULL;
+}
+
+/* If ARR is an array descriptor (fat or thin pointer), or pointer to
+   one, a pointer to its bounds data.   Otherwise NULL. */
+static struct value*
+desc_bounds (arr)
+     struct value* arr;
+{
+  struct type* type = check_typedef (VALUE_TYPE (arr));
+  if (is_thin_pntr (type)) 
+    {
+      struct type* bounds_type = desc_bounds_type (thin_descriptor_type (type));
+      LONGEST addr;
+
+      if (desc_bounds_type == NULL)
+       error ("Bad GNAT array descriptor");
+
+      /* NOTE: The following calculation is not really kosher, but
+        since desc_type is an XVE-encoded type (and shouldn't be),
+        the correct calculation is a real pain. FIXME (and fix GCC). */
+      if (TYPE_CODE (type) == TYPE_CODE_PTR)
+       addr = value_as_long (arr);
+      else 
+       addr = VALUE_ADDRESS (arr) + VALUE_OFFSET (arr);
+
+      return 
+         value_from_longest (lookup_pointer_type (bounds_type), 
+                             addr - TYPE_LENGTH (bounds_type));
+    }
+
+  else if (is_thick_pntr (type))
+    return value_struct_elt (&arr, NULL, "P_BOUNDS", NULL, 
+                            "Bad GNAT array descriptor");
+  else
+    return NULL;
+}
+
+/* If TYPE is the type of an array-descriptor (fat pointer), the bit
+   position of the field containing the address of the bounds data. */
+static int
+fat_pntr_bounds_bitpos (type)
+     struct type* type;
+{
+  return TYPE_FIELD_BITPOS (desc_base_type (type), 1);
+}
+
+/* If TYPE is the type of an array-descriptor (fat pointer), the bit
+   size of the field containing the address of the bounds data. */
+static int
+fat_pntr_bounds_bitsize (type)
+     struct type* type;
+{
+  type = desc_base_type (type);
+
+  if (TYPE_FIELD_BITSIZE (type, 1) > 0) 
+    return TYPE_FIELD_BITSIZE (type, 1);
+  else
+    return 8 * TYPE_LENGTH (check_typedef (TYPE_FIELD_TYPE (type, 1)));
+}
+
+/* If TYPE is the type of an array descriptor (fat or thin pointer) or a 
+   pointer to one, the type of its array data (a
+   pointer-to-array-with-no-bounds type); otherwise,  NULL.  Use
+   ada_type_of_array to get an array type with bounds data. */
+static struct type*
+desc_data_type (type)
+     struct type* type;
+{
+  type = desc_base_type (type);
+
+  /* NOTE: The following is bogus; see comment in desc_bounds. */
+  if (is_thin_pntr (type))
+    return lookup_pointer_type 
+      (desc_base_type (TYPE_FIELD_TYPE (thin_descriptor_type (type),1)));
+  else if (is_thick_pntr (type))
+    return lookup_struct_elt_type (type, "P_ARRAY", 1);
+  else
+    return NULL;
+}
+
+/* If ARR is an array descriptor (fat or thin pointer), a pointer to
+   its array data.  */
+static struct value*
+desc_data (arr)
+     struct value* arr;
+{
+  struct type* type = VALUE_TYPE (arr);
+  if (is_thin_pntr (type))
+    return thin_data_pntr (arr);
+  else if (is_thick_pntr (type))
+    return value_struct_elt (&arr, NULL, "P_ARRAY", NULL, 
+                            "Bad GNAT array descriptor");
+  else
+    return NULL;
+}
+
+
+/* If TYPE is the type of an array-descriptor (fat pointer), the bit
+   position of the field containing the address of the data. */
+static int
+fat_pntr_data_bitpos (type)
+     struct type* type;
+{
+  return TYPE_FIELD_BITPOS (desc_base_type (type), 0);
+}
+
+/* If TYPE is the type of an array-descriptor (fat pointer), the bit
+   size of the field containing the address of the data. */
+static int
+fat_pntr_data_bitsize (type)
+     struct type* type;
+{
+  type = desc_base_type (type);
+
+  if (TYPE_FIELD_BITSIZE (type, 0) > 0)
+    return TYPE_FIELD_BITSIZE (type, 0);
+  else 
+    return TARGET_CHAR_BIT * TYPE_LENGTH (TYPE_FIELD_TYPE (type, 0));
+}
+
+/* If BOUNDS is an array-bounds structure (or pointer to one), return 
+   the Ith lower bound stored in it, if WHICH is 0, and the Ith upper
+   bound, if WHICH is 1.  The first bound is I=1. */
+static struct value*
+desc_one_bound (bounds, i, which)
+     struct value* bounds;
+     int i;
+     int which;
+{
+  return value_struct_elt (&bounds, NULL, bound_name[2*i+which-2], NULL,
+                          "Bad GNAT array descriptor bounds");
+}
+
+/* If BOUNDS is an array-bounds structure type, return the bit position
+   of the Ith lower bound stored in it, if WHICH is 0, and the Ith upper
+   bound, if WHICH is 1.  The first bound is I=1. */
+static int
+desc_bound_bitpos (type, i, which)
+     struct type* type;
+     int i;
+     int which;
+{
+  return TYPE_FIELD_BITPOS (desc_base_type (type), 2*i+which-2);
+}
+
+/* If BOUNDS is an array-bounds structure type, return the bit field size
+   of the Ith lower bound stored in it, if WHICH is 0, and the Ith upper
+   bound, if WHICH is 1.  The first bound is I=1. */
+static int
+desc_bound_bitsize (type, i, which)
+     struct type* type;
+     int i;
+     int which;
+{
+  type = desc_base_type (type);
+
+  if (TYPE_FIELD_BITSIZE (type, 2*i+which-2) > 0)
+    return TYPE_FIELD_BITSIZE (type, 2*i+which-2);
+  else 
+    return 8 * TYPE_LENGTH (TYPE_FIELD_TYPE (type, 2*i+which-2));
+}
+
+/* If TYPE is the type of an array-bounds structure, the type of its
+   Ith bound (numbering from 1). Otherwise, NULL. */ 
+static struct type* 
+desc_index_type (type, i)
+     struct type* type;
+     int i;
+{
+  type = desc_base_type (type);
+
+  if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
+    return lookup_struct_elt_type (type, bound_name[2*i-2], 1);
+  else 
+    return NULL;
+}
+
+/* The number of index positions in the array-bounds type TYPE.  0
+   if TYPE is NULL. */
+static int
+desc_arity (type)
+     struct type* type;
+{
+  type = desc_base_type (type);
+
+  if (type != NULL)
+    return TYPE_NFIELDS (type) / 2;
+  return 0;
+}
+
+
+/* Non-zero iff type is a simple array type (or pointer to one). */
+int
+ada_is_simple_array (type)
+     struct type* type;
+{
+  if (type == NULL)
+    return 0;
+  CHECK_TYPEDEF (type);
+  return (TYPE_CODE (type) == TYPE_CODE_ARRAY
+         || (TYPE_CODE (type) == TYPE_CODE_PTR
+             && TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_ARRAY));
+}
+
+/* Non-zero iff type belongs to a GNAT array descriptor. */
+int
+ada_is_array_descriptor (type)
+     struct type* type;
+{
+  struct type* data_type = desc_data_type (type);
+
+  if (type == NULL)
+    return 0;
+  CHECK_TYPEDEF (type);
+  return 
+    data_type != NULL
+    && ((TYPE_CODE (data_type) == TYPE_CODE_PTR
+        && TYPE_TARGET_TYPE (data_type) != NULL
+        && TYPE_CODE (TYPE_TARGET_TYPE (data_type)) == TYPE_CODE_ARRAY)
+       || 
+       TYPE_CODE (data_type) == TYPE_CODE_ARRAY)
+    && desc_arity (desc_bounds_type (type)) > 0;
+}
+
+/* Non-zero iff type is a partially mal-formed GNAT array
+   descriptor.  (FIXME: This is to compensate for some problems with 
+   debugging output from GNAT.  Re-examine periodically to see if it
+   is still needed. */
+int
+ada_is_bogus_array_descriptor (type)
+     struct type *type;
+{
+  return 
+    type != NULL
+    && TYPE_CODE (type) == TYPE_CODE_STRUCT
+    && (lookup_struct_elt_type (type, "P_BOUNDS", 1) != NULL
+       || lookup_struct_elt_type (type, "P_ARRAY", 1) != NULL)
+    && ! ada_is_array_descriptor (type);
+}
+
+
+/* If ARR has a record type in the form of a standard GNAT array descriptor, 
+   (fat pointer) returns the type of the array data described---specifically,
+   a pointer-to-array type.  If BOUNDS is non-zero, the bounds data are filled 
+   in from the descriptor; otherwise, they are left unspecified.  If
+   the ARR denotes a null array descriptor and BOUNDS is non-zero, 
+   returns NULL.  The result is simply the type of ARR if ARR is not 
+   a descriptor.  */
+struct type*
+ada_type_of_array (arr, bounds)
+     struct value* arr;
+     int bounds;
+{
+  if (ada_is_packed_array_type (VALUE_TYPE (arr)))
+    return decode_packed_array_type (VALUE_TYPE (arr));
+
+  if (! ada_is_array_descriptor (VALUE_TYPE (arr)))
+    return VALUE_TYPE (arr);
+  
+  if (! bounds)
+    return check_typedef (TYPE_TARGET_TYPE (desc_data_type (VALUE_TYPE (arr))));
+  else
+    {
+      struct type* elt_type;
+      int arity;
+      struct value* descriptor;
+      struct objfile *objf = TYPE_OBJFILE (VALUE_TYPE (arr));
+
+      elt_type = ada_array_element_type (VALUE_TYPE (arr), -1);
+      arity = ada_array_arity (VALUE_TYPE (arr));
+
+      if (elt_type == NULL || arity == 0) 
+       return check_typedef (VALUE_TYPE (arr));
+
+      descriptor = desc_bounds (arr);
+      if (value_as_long (descriptor) == 0) 
+       return NULL;
+      while (arity > 0) {
+       struct type* range_type = alloc_type (objf);
+       struct type* array_type = alloc_type (objf);
+       struct value* low = desc_one_bound (descriptor, arity, 0);
+       struct value* high = desc_one_bound (descriptor, arity, 1);
+       arity -= 1;
+
+       create_range_type (range_type, VALUE_TYPE (low), 
+                          (int) value_as_long (low), 
+                          (int) value_as_long (high));
+       elt_type = create_array_type (array_type, elt_type, range_type);
+      }
+
+      return lookup_pointer_type (elt_type);
+    }
+}
+
+/* If ARR does not represent an array, returns ARR unchanged.
+   Otherwise, returns either a standard GDB array with bounds set 
+   appropriately or, if ARR is a non-null fat pointer, a pointer to a standard 
+   GDB array.  Returns NULL if ARR is a null fat pointer. */
+struct value*
+ada_coerce_to_simple_array_ptr (arr)
+     struct value* arr;
+{
+  if (ada_is_array_descriptor (VALUE_TYPE (arr)))
+    {
+      struct type* arrType = ada_type_of_array (arr, 1);
+      if (arrType == NULL)
+       return NULL;
+      return value_cast (arrType, value_copy (desc_data (arr)));
+    }
+  else if (ada_is_packed_array_type (VALUE_TYPE (arr)))
+    return decode_packed_array (arr);
+  else
+    return arr;
+}
+
+/* If ARR does not represent an array, returns ARR unchanged.
+   Otherwise, returns a standard GDB array describing ARR (which may
+   be ARR itself if it already is in the proper form). */
+struct value*
+ada_coerce_to_simple_array (arr)
+     struct value* arr;
+{
+  if (ada_is_array_descriptor (VALUE_TYPE (arr)))
+    {
+      struct value* arrVal = ada_coerce_to_simple_array_ptr (arr);
+      if (arrVal == NULL)
+       error ("Bounds unavailable for null array pointer.");
+      return value_ind (arrVal);
+    }
+  else if (ada_is_packed_array_type (VALUE_TYPE (arr)))
+    return decode_packed_array (arr);
+  else 
+    return arr;
+}
+
+/* If TYPE represents a GNAT array type, return it translated to an
+   ordinary GDB array type (possibly with BITSIZE fields indicating
+   packing). For other types, is the identity. */
+struct type*
+ada_coerce_to_simple_array_type (type)
+     struct type* type;
+{
+  struct value* mark = value_mark ();
+  struct value* dummy = value_from_longest (builtin_type_long, 0);
+  struct type* result;
+  VALUE_TYPE (dummy) = type;
+  result = ada_type_of_array (dummy, 0);
+  value_free_to_mark (dummy);
+  return result;
+}
+
+/* Non-zero iff TYPE represents a standard GNAT packed-array type. */
+int
+ada_is_packed_array_type (type)
+     struct type* type;
+{
+  if (type == NULL)
+    return 0;
+  CHECK_TYPEDEF (type);
+  return 
+    ada_type_name (type) != NULL
+    && strstr (ada_type_name (type), "___XP") != NULL;
+}
+
+/* Given that TYPE is a standard GDB array type with all bounds filled
+   in, and that the element size of its ultimate scalar constituents
+   (that is, either its elements, or, if it is an array of arrays, its
+   elements' elements, etc.) is *ELT_BITS, return an identical type,
+   but with the bit sizes of its elements (and those of any
+   constituent arrays) recorded in the BITSIZE components of its
+   TYPE_FIELD_BITSIZE values, and with *ELT_BITS set to its total size 
+   in bits. */
+static struct type*
+packed_array_type (type, elt_bits)
+     struct type* type;
+     long* elt_bits;
+{
+  struct type* new_elt_type;
+  struct type* new_type;
+  LONGEST low_bound, high_bound;
+
+  CHECK_TYPEDEF (type);
+  if (TYPE_CODE (type) != TYPE_CODE_ARRAY)
+    return type;
+
+  new_type = alloc_type (TYPE_OBJFILE (type));
+  new_elt_type = packed_array_type (check_typedef (TYPE_TARGET_TYPE (type)),
+                                   elt_bits);
+  create_array_type (new_type, new_elt_type, TYPE_FIELD_TYPE (type, 0));
+  TYPE_FIELD_BITSIZE (new_type, 0) = *elt_bits;
+  TYPE_NAME (new_type) = ada_type_name (type);
+
+  if (get_discrete_bounds (TYPE_FIELD_TYPE (type, 0), 
+                          &low_bound, &high_bound) < 0)
+    low_bound = high_bound = 0;
+  if (high_bound < low_bound)
+    *elt_bits = TYPE_LENGTH (new_type) = 0;
+  else 
+    {
+      *elt_bits *= (high_bound - low_bound + 1);
+      TYPE_LENGTH (new_type) = 
+       (*elt_bits + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT;
+    }
+
+  /*  TYPE_FLAGS (new_type) |= TYPE_FLAG_FIXED_INSTANCE; */
+  /* FIXME:  TYPE_FLAG_FIXED_INSTANCE should be defined in gdbtypes.h */
+  return new_type;
+}
+
+/* The array type encoded by TYPE, where ada_is_packed_array_type (TYPE).
+ */
+static struct type*
+decode_packed_array_type (type)
+     struct type* type;
+{
+  struct symbol** syms;
+  struct block** blocks;
+  const char* raw_name = ada_type_name (check_typedef (type));
+  char* name = (char*) alloca (strlen (raw_name) + 1);
+  char* tail = strstr (raw_name, "___XP");
+  struct type* shadow_type;
+  long bits;
+  int i, n;
+
+  memcpy (name, raw_name, tail - raw_name);
+  name[tail - raw_name] = '\000';
+
+  /* NOTE: Use ada_lookup_symbol_list because of bug in some versions
+   * of gcc (Solaris, e.g.). FIXME when compiler is fixed. */
+  n = ada_lookup_symbol_list (name, get_selected_block (NULL), 
+                             VAR_NAMESPACE, &syms, &blocks);
+  for (i = 0; i < n; i += 1)
+    if (syms[i] != NULL && SYMBOL_CLASS (syms[i]) == LOC_TYPEDEF
+       && STREQ (name, ada_type_name (SYMBOL_TYPE (syms[i]))))
+      break;
+  if (i >= n)
+    {
+      warning ("could not find bounds information on packed array");
+      return NULL;
+    }
+  shadow_type = SYMBOL_TYPE (syms[i]);
+
+  if (TYPE_CODE (shadow_type) != TYPE_CODE_ARRAY)
+    {
+      warning ("could not understand bounds information on packed array");
+      return NULL;
+    }
+                                                                
+  if (sscanf (tail + sizeof ("___XP") - 1, "%ld", &bits) != 1)
+    {
+      warning ("could not understand bit size information on packed array");
+      return NULL;
+    }
+    
+  return packed_array_type (shadow_type, &bits);
+}
+
+/* Given that ARR is a struct value* indicating a GNAT packed array,
+   returns a simple array that denotes that array.  Its type is a
+   standard GDB array type except that the BITSIZEs of the array
+   target types are set to the number of bits in each element, and the
+   type length is set appropriately. */
+
+static struct value*
+decode_packed_array (arr)
+     struct value* arr;
+{
+  struct type* type = decode_packed_array_type (VALUE_TYPE (arr));
+
+  if (type == NULL)
+    {
+      error ("can't unpack array");
+      return NULL;
+    }
+  else
+    return coerce_unspec_val_to_type (arr, 0, type);
+}
+
+
+/* The value of the element of packed array ARR at the ARITY indices
+   given in IND.   ARR must be a simple array. */
+
+static struct value*
+value_subscript_packed (arr, arity, ind)
+     struct value* arr;
+     int arity;
+     struct value** ind;
+{
+  int i;
+  int bits, elt_off, bit_off;
+  long elt_total_bit_offset;
+  struct type* elt_type;
+  struct value* v;
+
+  bits = 0;
+  elt_total_bit_offset = 0;
+  elt_type = check_typedef (VALUE_TYPE (arr));
+  for (i = 0; i < arity; i += 1) 
+    {
+      if (TYPE_CODE (elt_type) != TYPE_CODE_ARRAY 
+         || TYPE_FIELD_BITSIZE (elt_type, 0) == 0)
+       error ("attempt to do packed indexing of something other than a packed array");
+      else
+       {
+         struct type *range_type = TYPE_INDEX_TYPE (elt_type);
+         LONGEST lowerbound, upperbound;
+         LONGEST idx;
+
+         if (get_discrete_bounds (range_type, &lowerbound,
+                                  &upperbound) < 0)
+           {
+             warning ("don't know bounds of array");
+             lowerbound = upperbound = 0;
+           }
+      
+         idx = value_as_long (value_pos_atr (ind[i]));
+         if (idx < lowerbound || idx > upperbound)
+           warning ("packed array index %ld out of bounds", (long) idx);
+         bits = TYPE_FIELD_BITSIZE (elt_type, 0);
+         elt_total_bit_offset += (idx - lowerbound) * bits;
+         elt_type = check_typedef (TYPE_TARGET_TYPE (elt_type));
+       }
+    }
+  elt_off = elt_total_bit_offset / HOST_CHAR_BIT;
+  bit_off = elt_total_bit_offset % HOST_CHAR_BIT;
+  
+  v = ada_value_primitive_packed_val (arr, NULL, elt_off, bit_off, 
+                                     bits, elt_type);
+  if (VALUE_LVAL (arr) == lval_internalvar)
+    VALUE_LVAL (v) = lval_internalvar_component;
+  else
+    VALUE_LVAL (v) = VALUE_LVAL (arr);
+  return v;
+}
+
+/* Non-zero iff TYPE includes negative integer values. */
+
+static int
+has_negatives (type)
+     struct type* type;
+{
+  switch (TYPE_CODE (type)) {
+  default:
+    return 0;
+  case TYPE_CODE_INT:
+    return ! TYPE_UNSIGNED (type);
+  case TYPE_CODE_RANGE:
+    return TYPE_LOW_BOUND (type) < 0;
+  }
+}
+      
+
+/* Create a new value of type TYPE from the contents of OBJ starting
+   at byte OFFSET, and bit offset BIT_OFFSET within that byte,
+   proceeding for BIT_SIZE bits.  If OBJ is an lval in memory, then
+   assigning through the result will set the field fetched from. OBJ
+   may also be NULL, in which case, VALADDR+OFFSET must address the
+   start of storage containing the packed value.  The value returned 
+   in this case is never an lval.   
+   Assumes 0 <= BIT_OFFSET < HOST_CHAR_BIT. */
+
+struct value*
+ada_value_primitive_packed_val (obj, valaddr, offset, bit_offset, 
+                               bit_size, type)
+     struct value* obj;
+     char* valaddr;
+     long offset;
+     int bit_offset;
+     int bit_size;
+     struct type* type;
+{
+  struct value* v;
+  int src,                     /* Index into the source area. */
+    targ,                      /* Index into the target area. */
+    i, 
+    srcBitsLeft,               /* Number of source bits left to move. */
+    nsrc, ntarg,               /* Number of source and target bytes. */
+    unusedLS,                  /* Number of bits in next significant
+                                * byte of source that are unused. */
+    accumSize;                 /* Number of meaningful bits in accum */
+  unsigned char* bytes;   /* First byte containing data to unpack. */
+  unsigned char* unpacked;
+  unsigned long accum;         /* Staging area for bits being transferred */
+  unsigned char sign;
+  int len = (bit_size + bit_offset + HOST_CHAR_BIT - 1) / 8;
+  /* Transmit bytes from least to most significant; delta is the
+   * direction the indices move. */     
+  int delta = BITS_BIG_ENDIAN ? -1 : 1;
+
+  CHECK_TYPEDEF (type);
+
+  if (obj == NULL)
+    {
+      v = allocate_value (type);
+      bytes = (unsigned char*) (valaddr + offset);
+    }
+  else if (VALUE_LAZY (obj))
+    {
+      v = value_at (type,
+                   VALUE_ADDRESS (obj) + VALUE_OFFSET (obj) + offset, NULL);
+      bytes = (unsigned char*) alloca (len);
+      read_memory (VALUE_ADDRESS (v), bytes, len);
+    }
+  else 
+    {
+      v = allocate_value (type);
+      bytes = (unsigned char*) VALUE_CONTENTS (obj) + offset;
+    }
+      
+  if (obj != NULL) 
+    {
+      VALUE_LVAL (v) = VALUE_LVAL (obj);
+      if (VALUE_LVAL (obj) == lval_internalvar)
+       VALUE_LVAL (v) = lval_internalvar_component;
+      VALUE_ADDRESS (v) = VALUE_ADDRESS (obj) + VALUE_OFFSET (obj) + offset;
+      VALUE_BITPOS (v) = bit_offset + VALUE_BITPOS (obj);
+      VALUE_BITSIZE (v) = bit_size;
+      if (VALUE_BITPOS (v) >= HOST_CHAR_BIT)
+        {
+          VALUE_ADDRESS (v) += 1;
+          VALUE_BITPOS (v) -= HOST_CHAR_BIT;
+        }
+    }
+  else
+    VALUE_BITSIZE (v) = bit_size;
+  unpacked = (unsigned char*) VALUE_CONTENTS (v);
+
+  srcBitsLeft = bit_size;
+  nsrc = len;
+  ntarg = TYPE_LENGTH (type);
+  sign = 0;
+  if (bit_size == 0)
+    {
+      memset (unpacked, 0, TYPE_LENGTH (type));
+      return v;
+    }
+  else if (BITS_BIG_ENDIAN)
+    {
+      src = len-1;
+      if (has_negatives (type) && 
+         ((bytes[0] << bit_offset) & (1 << (HOST_CHAR_BIT-1))))
+       sign = ~0;
+      
+      unusedLS = 
+       (HOST_CHAR_BIT - (bit_size + bit_offset) % HOST_CHAR_BIT)
+       % HOST_CHAR_BIT;
+
+      switch (TYPE_CODE (type))
+        {
+        case TYPE_CODE_ARRAY:
+        case TYPE_CODE_UNION:
+        case TYPE_CODE_STRUCT:
+          /* Non-scalar values must be aligned at a byte boundary. */
+          accumSize =
+            (HOST_CHAR_BIT - bit_size % HOST_CHAR_BIT) % HOST_CHAR_BIT;
+         /* And are placed at the beginning (most-significant) bytes
+          * of the target. */
+         targ = src;
+          break;
+        default:
+         accumSize = 0;
+         targ = TYPE_LENGTH (type) - 1;
+          break;
+        }
+    }
+  else 
+    {
+      int sign_bit_offset = (bit_size + bit_offset - 1) % 8;
+
+      src = targ = 0;
+      unusedLS = bit_offset;
+      accumSize = 0;
+
+      if (has_negatives (type) && (bytes[len-1] & (1 << sign_bit_offset)))
+       sign = ~0;
+    }
+      
+  accum = 0;
+  while (nsrc > 0)
+    {
+      /* Mask for removing bits of the next source byte that are not
+       * part of the value. */
+      unsigned int unusedMSMask = 
+       (1 << (srcBitsLeft >= HOST_CHAR_BIT ? HOST_CHAR_BIT : srcBitsLeft))-1;
+      /* Sign-extend bits for this byte. */
+      unsigned int signMask = sign & ~unusedMSMask;
+      accum |= 
+       (((bytes[src] >> unusedLS) & unusedMSMask) | signMask) << accumSize;
+      accumSize += HOST_CHAR_BIT - unusedLS;
+      if (accumSize >= HOST_CHAR_BIT) 
+       {
+         unpacked[targ] = accum & ~(~0L << HOST_CHAR_BIT);
+         accumSize -= HOST_CHAR_BIT;
+         accum >>= HOST_CHAR_BIT;
+         ntarg -= 1;
+         targ += delta;
+       }
+      srcBitsLeft -= HOST_CHAR_BIT - unusedLS;
+      unusedLS = 0;
+      nsrc -= 1;
+      src += delta;
+    }
+  while (ntarg > 0)
+    {
+      accum |= sign << accumSize;
+      unpacked[targ] = accum & ~(~0L << HOST_CHAR_BIT);
+      accumSize -= HOST_CHAR_BIT;
+      accum >>= HOST_CHAR_BIT;
+      ntarg -= 1;
+      targ += delta;
+    }
+
+  return v;
+}
+      
+/* Move N bits from SOURCE, starting at bit offset SRC_OFFSET to
+   TARGET, starting at bit offset TARG_OFFSET.  SOURCE and TARGET must
+   not overlap. */
+static void
+move_bits (char* target, int targ_offset, char* source, int src_offset, int n)
+{
+  unsigned int accum, mask;
+  int accum_bits, chunk_size;
+
+  target += targ_offset / HOST_CHAR_BIT;
+  targ_offset %= HOST_CHAR_BIT;
+  source += src_offset / HOST_CHAR_BIT;
+  src_offset %= HOST_CHAR_BIT;
+  if (BITS_BIG_ENDIAN) 
+    {
+      accum = (unsigned char) *source;
+      source += 1;
+      accum_bits = HOST_CHAR_BIT - src_offset;
+
+      while (n > 0) 
+       {
+         int unused_right;
+         accum = (accum << HOST_CHAR_BIT) + (unsigned char) *source;
+         accum_bits += HOST_CHAR_BIT;
+         source += 1;
+         chunk_size = HOST_CHAR_BIT - targ_offset;
+         if (chunk_size > n)
+           chunk_size = n;
+         unused_right = HOST_CHAR_BIT - (chunk_size + targ_offset);
+         mask = ((1 << chunk_size) - 1) << unused_right;
+         *target = 
+           (*target & ~mask) 
+           | ((accum >> (accum_bits - chunk_size - unused_right)) & mask);
+         n -= chunk_size;
+         accum_bits -= chunk_size;
+         target += 1;
+         targ_offset = 0;
+       }
+    }
+  else
+    {
+      accum = (unsigned char) *source >> src_offset;
+      source += 1;
+      accum_bits = HOST_CHAR_BIT - src_offset;
+
+      while (n > 0) 
+       {
+         accum = accum + ((unsigned char) *source << accum_bits);
+         accum_bits += HOST_CHAR_BIT;
+         source += 1;
+         chunk_size = HOST_CHAR_BIT - targ_offset;
+         if (chunk_size > n)
+           chunk_size = n;
+         mask = ((1 << chunk_size) - 1) << targ_offset;
+         *target = 
+           (*target & ~mask) | ((accum << targ_offset) & mask);
+         n -= chunk_size;
+         accum_bits -= chunk_size;
+         accum >>= chunk_size;
+         target += 1;
+         targ_offset = 0;
+       }
+    }
+}
+
+
+/* Store the contents of FROMVAL into the location of TOVAL.
+   Return a new value with the location of TOVAL and contents of
+   FROMVAL.   Handles assignment into packed fields that have
+   floating-point or non-scalar types. */
+
+static struct value*
+ada_value_assign (struct value* toval, struct value* fromval)
+{
+  struct type* type = VALUE_TYPE (toval);
+  int bits = VALUE_BITSIZE (toval);
+
+  if (!toval->modifiable)
+    error ("Left operand of assignment is not a modifiable lvalue.");
+
+  COERCE_REF (toval);
+
+  if (VALUE_LVAL (toval) == lval_memory 
+      && bits > 0
+      && (TYPE_CODE (type) == TYPE_CODE_FLT 
+         || TYPE_CODE (type) == TYPE_CODE_STRUCT))
+    {
+      int len = 
+       (VALUE_BITPOS (toval) + bits + HOST_CHAR_BIT - 1)
+       / HOST_CHAR_BIT;
+      char* buffer = (char*) alloca (len);
+      struct value* val;
+
+      if (TYPE_CODE (type) == TYPE_CODE_FLT)
+       fromval = value_cast (type, fromval);
+
+      read_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), buffer, len);
+      if (BITS_BIG_ENDIAN)
+       move_bits (buffer, VALUE_BITPOS (toval), 
+                  VALUE_CONTENTS (fromval), 
+                  TYPE_LENGTH (VALUE_TYPE (fromval)) * TARGET_CHAR_BIT - bits,
+                  bits);
+      else
+       move_bits (buffer, VALUE_BITPOS (toval), VALUE_CONTENTS (fromval), 
+                  0, bits);
+      write_memory (VALUE_ADDRESS (toval) + VALUE_OFFSET (toval), buffer, len);
+
+      val = value_copy (toval);
+      memcpy (VALUE_CONTENTS_RAW (val), VALUE_CONTENTS (fromval),
+             TYPE_LENGTH (type));
+      VALUE_TYPE (val) = type;
+  
+      return val;
+    }
+
+  return value_assign (toval, fromval);
+}
+
+
+/* The value of the element of array ARR at the ARITY indices given in IND. 
+   ARR may be either a simple array, GNAT array descriptor, or pointer 
+   thereto.  */
+
+struct value*
+ada_value_subscript (arr, arity, ind)
+     struct value* arr;
+     int arity;
+     struct value** ind;
+{
+  int k;
+  struct value* elt;
+  struct type* elt_type;
+
+  elt = ada_coerce_to_simple_array (arr);
+
+  elt_type = check_typedef (VALUE_TYPE (elt));
+  if (TYPE_CODE (elt_type) == TYPE_CODE_ARRAY 
+      && TYPE_FIELD_BITSIZE (elt_type, 0) > 0)
+    return value_subscript_packed (elt, arity, ind);
+
+  for (k = 0; k < arity; k += 1)
+    {
+      if (TYPE_CODE (elt_type) != TYPE_CODE_ARRAY)
+       error("too many subscripts (%d expected)", k);
+      elt = value_subscript (elt, value_pos_atr (ind[k]));
+    }
+  return elt;
+}
+
+/* Assuming ARR is a pointer to a standard GDB array of type TYPE, the
+   value of the element of *ARR at the ARITY indices given in
+   IND. Does not read the entire array into memory. */
+
+struct value*
+ada_value_ptr_subscript (arr, type, arity, ind)
+     struct value* arr;
+     struct type* type;
+     int arity;
+     struct value** ind;
+{
+  int k;
+
+  for (k = 0; k < arity; k += 1)
+    {
+      LONGEST lwb, upb;
+      struct value* idx;
+
+      if (TYPE_CODE (type) != TYPE_CODE_ARRAY)
+       error("too many subscripts (%d expected)", k);
+      arr = value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (type)), 
+                       value_copy (arr));
+      get_discrete_bounds (TYPE_INDEX_TYPE (type), &lwb, &upb);
+      if (lwb == 0) 
+       idx = ind[k];
+      else
+       idx = value_sub (ind[k], value_from_longest (builtin_type_int, lwb));
+      arr = value_add (arr, idx);
+      type = TYPE_TARGET_TYPE (type);
+    }
+
+  return value_ind (arr);
+}
+
+/* If type is a record type in the form of a standard GNAT array
+   descriptor, returns the number of dimensions for type.  If arr is a
+   simple array, returns the number of "array of"s that prefix its
+   type designation. Otherwise, returns 0. */
+
+int
+ada_array_arity (type)
+     struct type* type;
+{
+  int arity;
+
+  if (type == NULL)
+    return 0;
+
+  type = desc_base_type (type);
+
+  arity = 0;
+  if (TYPE_CODE (type) == TYPE_CODE_STRUCT) 
+    return desc_arity (desc_bounds_type (type));
+  else 
+    while (TYPE_CODE (type) == TYPE_CODE_ARRAY) 
+      {
+       arity += 1;
+       type = check_typedef (TYPE_TARGET_TYPE (type));
+      }
+           
+  return arity;
+}
+
+/* If TYPE is a record type in the form of a standard GNAT array
+   descriptor or a simple array type, returns the element type for
+   TYPE after indexing by NINDICES indices, or by all indices if
+   NINDICES is -1. Otherwise, returns NULL. */
+
+struct type*
+ada_array_element_type (type, nindices)
+     struct type* type;
+     int nindices;
+{
+  type = desc_base_type (type);
+
+  if (TYPE_CODE (type) == TYPE_CODE_STRUCT) 
+    {
+      int k;
+      struct type* p_array_type;
+
+      p_array_type = desc_data_type (type);
+
+      k = ada_array_arity (type);
+      if (k == 0)
+       return NULL;
+      
+      /* Initially p_array_type = elt_type(*)[]...(k times)...[] */
+      if (nindices >= 0 && k > nindices)
+       k = nindices;
+      p_array_type = TYPE_TARGET_TYPE (p_array_type);
+      while (k > 0 && p_array_type != NULL) 
+       {
+         p_array_type = check_typedef (TYPE_TARGET_TYPE (p_array_type));
+         k -= 1;
+       }
+      return p_array_type;
+    }
+  else if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
+    {
+      while (nindices != 0 && TYPE_CODE (type) == TYPE_CODE_ARRAY)
+       {
+         type = TYPE_TARGET_TYPE (type);
+         nindices -= 1;
+       }
+      return type;
+    }
+
+  return NULL;
+}
+
+/* The type of nth index in arrays of given type (n numbering from 1).  Does 
+   not examine memory. */
+
+struct type*
+ada_index_type (type, n)
+     struct type* type;
+     int n;
+{
+  type = desc_base_type (type);
+
+  if (n > ada_array_arity (type))
+    return NULL;
+
+  if (ada_is_simple_array (type))
+    {
+      int i;
+
+      for (i = 1; i < n; i += 1)
+       type = TYPE_TARGET_TYPE (type);
+
+      return TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, 0));
+    }
+  else 
+    return desc_index_type (desc_bounds_type (type), n);
+}
+
+/* Given that arr is an array type, returns the lower bound of the
+   Nth index (numbering from 1) if WHICH is 0, and the upper bound if
+   WHICH is 1. This returns bounds 0 .. -1 if ARR_TYPE is an
+   array-descriptor type.  If TYPEP is non-null, *TYPEP is set to the 
+   bounds type.  It works for other arrays with bounds supplied by 
+   run-time quantities other than discriminants. */
+
+LONGEST
+ada_array_bound_from_type (arr_type, n, which, typep)
+     struct type* arr_type;
+     int n; 
+     int which;
+     struct type** typep;
+{
+  struct type* type;
+  struct type* index_type_desc;
+
+  if (ada_is_packed_array_type (arr_type))
+    arr_type = decode_packed_array_type (arr_type);
+
+  if (arr_type == NULL || ! ada_is_simple_array (arr_type)) 
+    {
+      if (typep != NULL)
+       *typep = builtin_type_int;
+      return (LONGEST) -which;
+    }
+
+  if (TYPE_CODE (arr_type) == TYPE_CODE_PTR)
+    type = TYPE_TARGET_TYPE (arr_type);
+  else
+    type = arr_type;
+
+  index_type_desc = ada_find_parallel_type (type, "___XA");
+  if (index_type_desc == NULL) 
+    {
+      struct type* range_type;
+      struct type* index_type;
+
+      while (n > 1) 
+       {
+         type = TYPE_TARGET_TYPE (type);
+         n -= 1;
+       }
+
+      range_type = TYPE_INDEX_TYPE (type);
+      index_type = TYPE_TARGET_TYPE (range_type);
+      if (TYPE_CODE (index_type) == TYPE_CODE_UNDEF)
+         index_type = builtin_type_long;
+      if (typep != NULL)
+       *typep = index_type;
+      return 
+       (LONGEST) (which == 0 
+                  ? TYPE_LOW_BOUND (range_type)
+                  : TYPE_HIGH_BOUND (range_type));
+    }
+  else 
+    {
+      struct type* index_type =
+       to_fixed_range_type (TYPE_FIELD_NAME (index_type_desc, n-1),
+                            NULL, TYPE_OBJFILE (arr_type));
+      if (typep != NULL)
+       *typep = TYPE_TARGET_TYPE (index_type);
+      return 
+       (LONGEST) (which == 0 
+                  ? TYPE_LOW_BOUND (index_type)
+                  : TYPE_HIGH_BOUND (index_type));
+    }
+}
+
+/* Given that arr is an array value, returns the lower bound of the
+   nth index (numbering from 1) if which is 0, and the upper bound if
+   which is 1. This routine will also work for arrays with bounds
+   supplied by run-time quantities other than discriminants. */
+
+struct value*
+ada_array_bound (arr, n, which)
+     struct value* arr;
+     int n; 
+     int which;
+{
+  struct type* arr_type = VALUE_TYPE (arr);
+
+  if (ada_is_packed_array_type (arr_type))
+    return ada_array_bound (decode_packed_array (arr), n, which);
+  else if (ada_is_simple_array (arr_type)) 
+    {
+      struct type* type;
+      LONGEST v = ada_array_bound_from_type (arr_type, n, which, &type);
+      return value_from_longest (type, v);
+    }
+  else
+    return desc_one_bound (desc_bounds (arr), n, which);
+}
+
+/* Given that arr is an array value, returns the length of the
+   nth index.  This routine will also work for arrays with bounds
+   supplied by run-time quantities other than discriminants. Does not
+   work for arrays indexed by enumeration types with representation
+   clauses at the moment. */ 
+
+struct value*
+ada_array_length (arr, n)
+     struct value* arr;
+     int n; 
+{
+  struct type* arr_type = check_typedef (VALUE_TYPE (arr));
+  struct type* index_type_desc;
+
+  if (ada_is_packed_array_type (arr_type))
+    return ada_array_length (decode_packed_array (arr), n);
+
+  if (ada_is_simple_array (arr_type))
+    {
+      struct type* type;
+      LONGEST v =
+       ada_array_bound_from_type (arr_type, n, 1, &type) -
+       ada_array_bound_from_type (arr_type, n, 0, NULL) + 1;
+      return value_from_longest (type, v);
+    }
+  else
+    return 
+      value_from_longest (builtin_type_ada_int,
+                         value_as_long (desc_one_bound (desc_bounds (arr),
+                                                        n, 1))
+                         - value_as_long (desc_one_bound (desc_bounds (arr),
+                                                          n, 0))
+                         + 1);
+}
+
+\f
+                               /* Name resolution */
+
+/* The "demangled" name for the user-definable Ada operator corresponding
+   to op. */
+
+static const char*
+ada_op_name (op)
+     enum exp_opcode op;
+{
+  int i;
+
+  for (i = 0; ada_opname_table[i].mangled != NULL; i += 1)
+    {
+      if (ada_opname_table[i].op == op)
+       return ada_opname_table[i].demangled;
+    }
+  error ("Could not find operator name for opcode");
+}
+
+
+/* Same as evaluate_type (*EXP), but resolves ambiguous symbol 
+   references (OP_UNRESOLVED_VALUES) and converts operators that are 
+   user-defined into appropriate function calls.  If CONTEXT_TYPE is 
+   non-null, it provides a preferred result type [at the moment, only
+   type void has any effect---causing procedures to be preferred over
+   functions in calls].  A null CONTEXT_TYPE indicates that a non-void
+   return type is preferred.  The variable unresolved_names contains a list
+   of character strings referenced by expout that should be freed.  
+   May change (expand) *EXP.  */
+
+void
+ada_resolve (expp, context_type)
+     struct expression** expp;
+     struct type* context_type;
+{
+  int pc;
+  pc = 0;
+  ada_resolve_subexp (expp, &pc, 1, context_type);
+}
+
+/* Resolve the operator of the subexpression beginning at 
+   position *POS of *EXPP. "Resolving" consists of replacing
+   OP_UNRESOLVED_VALUE with an appropriate OP_VAR_VALUE, replacing
+   built-in operators with function calls to user-defined operators,
+   where appropriate, and (when DEPROCEDURE_P is non-zero), converting
+   function-valued variables into parameterless calls.  May expand
+   EXP. The CONTEXT_TYPE functions as in ada_resolve, above. */
+
+static struct value*
+ada_resolve_subexp (expp, pos, deprocedure_p, context_type) 
+     struct expression** expp;
+     int *pos;
+     int deprocedure_p;
+     struct type* context_type;
+{
+  int pc = *pos;
+  int i;
+  struct expression* exp;      /* Convenience: == *expp */
+  enum exp_opcode op = (*expp)->elts[pc].opcode;
+  struct value** argvec;               /* Vector of operand types (alloca'ed). */
+  int nargs;                   /* Number of operands */
+
+  argvec = NULL;
+  nargs = 0;
+  exp = *expp;
+
+  /* Pass one: resolve operands, saving their types and updating *pos. */
+  switch (op)
+    {
+    case OP_VAR_VALUE:
+      /*    case OP_UNRESOLVED_VALUE:*/
+      /* FIXME:  OP_UNRESOLVED_VALUE should be defined in expression.h */
+      *pos += 4;
+      break;
+
+    case OP_FUNCALL:
+      nargs = longest_to_int (exp->elts[pc + 1].longconst) + 1;
+      /* FIXME:  OP_UNRESOLVED_VALUE should be defined in expression.h */
+      /*      if (exp->elts[pc+3].opcode == OP_UNRESOLVED_VALUE)       
+       {
+         *pos += 7;
+
+         argvec = (struct value* *) alloca (sizeof (struct value*) * (nargs + 1));
+         for (i = 0; i < nargs-1; i += 1)
+           argvec[i] = ada_resolve_subexp (expp, pos, 1, NULL);
+         argvec[i] = NULL;
+       }
+      else
+       {
+         *pos += 3;
+         ada_resolve_subexp (expp, pos, 0, NULL);
+         for (i = 1; i < nargs; i += 1)
+           ada_resolve_subexp (expp, pos, 1, NULL);
+       }
+      */
+      exp = *expp;
+      break;
+
+      /* FIXME:  UNOP_QUAL should be defined in expression.h */
+      /*    case UNOP_QUAL:
+      nargs = 1;
+      *pos += 3;
+      ada_resolve_subexp (expp, pos, 1, exp->elts[pc + 1].type);
+      exp = *expp;
+      break;
+      */
+      /* FIXME:  OP_ATTRIBUTE should be defined in expression.h */      
+      /*    case OP_ATTRIBUTE:
+      nargs = longest_to_int (exp->elts[pc + 1].longconst) + 1;
+      *pos += 4;
+      for (i = 0; i < nargs; i += 1)
+       ada_resolve_subexp (expp, pos, 1, NULL);
+      exp = *expp;
+      break;
+      */
+    case UNOP_ADDR:
+      nargs = 1;
+      *pos += 1;
+      ada_resolve_subexp (expp, pos, 0, NULL);
+      exp = *expp;
+      break;
+
+    case BINOP_ASSIGN:
+      {
+       struct value* arg1;
+       nargs = 2;
+       *pos += 1;
+       arg1 = ada_resolve_subexp (expp, pos, 0, NULL);
+       if (arg1 == NULL)
+         ada_resolve_subexp (expp, pos, 1, NULL);
+       else
+         ada_resolve_subexp (expp, pos, 1, VALUE_TYPE (arg1));
+       break;
+      }
+
+    default:
+      switch (op) 
+       {
+       default:
+         error ("Unexpected operator during name resolution");
+       case UNOP_CAST:
+         /*    case UNOP_MBR:
+         nargs = 1;
+         *pos += 3;
+         break;
+         */
+       case BINOP_ADD:
+       case BINOP_SUB:
+       case BINOP_MUL:
+       case BINOP_DIV:
+       case BINOP_REM:
+       case BINOP_MOD:
+       case BINOP_EXP:
+       case BINOP_CONCAT:
+       case BINOP_LOGICAL_AND:
+       case BINOP_LOGICAL_OR:
+       case BINOP_BITWISE_AND:
+       case BINOP_BITWISE_IOR:
+       case BINOP_BITWISE_XOR:
+
+       case BINOP_EQUAL:
+       case BINOP_NOTEQUAL:
+       case BINOP_LESS:
+       case BINOP_GTR:
+       case BINOP_LEQ:
+       case BINOP_GEQ:
+
+       case BINOP_REPEAT:
+       case BINOP_SUBSCRIPT:
+       case BINOP_COMMA:
+         nargs = 2;
+         *pos += 1;
+         break;
+
+       case UNOP_NEG:
+       case UNOP_PLUS:
+       case UNOP_LOGICAL_NOT:
+       case UNOP_ABS:
+       case UNOP_IND:
+         nargs = 1;
+         *pos += 1;
+         break;
+
+       case OP_LONG:
+       case OP_DOUBLE:
+       case OP_VAR_VALUE:
+         *pos += 4;
+         break;
+
+       case OP_TYPE:
+       case OP_BOOL:
+       case OP_LAST:
+       case OP_REGISTER:
+       case OP_INTERNALVAR:
+         *pos += 3;
+         break;
+
+       case UNOP_MEMVAL:
+         *pos += 3;
+         nargs = 1;
+         break;
+
+       case STRUCTOP_STRUCT:
+       case STRUCTOP_PTR:
+         nargs = 1;
+         *pos += 4 + BYTES_TO_EXP_ELEM (exp->elts[pc + 1].longconst + 1);
+         break;
+
+       case OP_ARRAY:
+         *pos += 4;  
+         nargs = longest_to_int (exp->elts[pc + 2].longconst) + 1;
+         nargs -= longest_to_int (exp->elts[pc + 1].longconst);
+         /* A null array contains one dummy element to give the type. */
+         /*      if (nargs == 0)
+           nargs = 1;
+           break;*/
+
+       case TERNOP_SLICE:
+         /* FIXME: TERNOP_MBR should be defined in expression.h */
+         /*    case TERNOP_MBR:
+         *pos += 1;
+         nargs = 3;
+         break;
+         */
+         /* FIXME: BINOP_MBR should be defined in expression.h */
+         /*    case BINOP_MBR:
+         *pos += 3;
+         nargs = 2;
+         break;*/
+       }
+
+      argvec = (struct value* *) alloca (sizeof (struct value*) * (nargs + 1));
+      for (i = 0; i < nargs; i += 1)
+       argvec[i] = ada_resolve_subexp (expp, pos, 1, NULL);
+      argvec[i] = NULL;
+      exp = *expp;
+      break;
+    }
+
+  /* Pass two: perform any resolution on principal operator. */
+  switch (op)
+    {
+    default:
+      break;
+
+      /* FIXME:  OP_UNRESOLVED_VALUE should be defined in expression.h */
+      /*    case OP_UNRESOLVED_VALUE:
+      {
+       struct symbol** candidate_syms;
+       struct block** candidate_blocks;
+       int n_candidates;
+
+       n_candidates = ada_lookup_symbol_list (exp->elts[pc + 2].name,
+                                              exp->elts[pc + 1].block,
+                                              VAR_NAMESPACE,
+                                              &candidate_syms,
+                                              &candidate_blocks);
+       
+       if (n_candidates > 1) 
+       {*/
+           /* Types tend to get re-introduced locally, so if there
+              are any local symbols that are not types, first filter
+              out all types.*/        /*
+           int j;
+           for (j = 0; j < n_candidates; j += 1) 
+             switch (SYMBOL_CLASS (candidate_syms[j])) 
+               {
+               case LOC_REGISTER:
+               case LOC_ARG:
+               case LOC_REF_ARG:
+               case LOC_REGPARM:
+               case LOC_REGPARM_ADDR:
+               case LOC_LOCAL:
+               case LOC_LOCAL_ARG:
+               case LOC_BASEREG:
+               case LOC_BASEREG_ARG:
+                 goto FoundNonType;
+               default:
+                 break;
+               }
+         FoundNonType:
+           if (j < n_candidates) 
+             {
+               j = 0;
+               while (j < n_candidates) 
+                 {
+                   if (SYMBOL_CLASS (candidate_syms[j]) == LOC_TYPEDEF)
+                     {
+                       candidate_syms[j] = candidate_syms[n_candidates-1];
+                       candidate_blocks[j] = candidate_blocks[n_candidates-1];
+                       n_candidates -= 1;
+                     }
+                   else
+                     j += 1;
+                 }
+             }
+         }
+
+       if (n_candidates == 0)
+         error ("No definition found for %s", 
+                ada_demangle (exp->elts[pc + 2].name));
+       else if (n_candidates == 1)
+         i = 0;
+       else if (deprocedure_p 
+                && ! is_nonfunction (candidate_syms, n_candidates))
+         {
+           i = ada_resolve_function (candidate_syms, candidate_blocks,
+                                     n_candidates, NULL, 0,
+                                     exp->elts[pc + 2].name, context_type);
+           if (i < 0) 
+             error ("Could not find a match for %s", 
+                    ada_demangle (exp->elts[pc + 2].name));
+         }
+       else 
+         {
+           printf_filtered ("Multiple matches for %s\n", 
+                            ada_demangle (exp->elts[pc+2].name));
+           user_select_syms (candidate_syms, candidate_blocks, 
+                             n_candidates, 1);
+           i = 0;
+         }
+
+       exp->elts[pc].opcode = exp->elts[pc + 3].opcode = OP_VAR_VALUE;
+       exp->elts[pc + 1].block = candidate_blocks[i];
+       exp->elts[pc + 2].symbol = candidate_syms[i];
+       if (innermost_block == NULL ||
+           contained_in (candidate_blocks[i], innermost_block))
+         innermost_block = candidate_blocks[i];
+      }*/
+      /* FALL THROUGH */
+
+    case OP_VAR_VALUE:
+      if (deprocedure_p && 
+         TYPE_CODE (SYMBOL_TYPE (exp->elts[pc+2].symbol)) == TYPE_CODE_FUNC)
+       {
+         replace_operator_with_call (expp, pc, 0, 0, 
+                                     exp->elts[pc+2].symbol,
+                                     exp->elts[pc+1].block);
+         exp = *expp;
+       }
+      break;
+
+    case OP_FUNCALL:
+      {
+       /* FIXME:  OP_UNRESOLVED_VALUE should be defined in expression.h */
+       /*      if (exp->elts[pc+3].opcode == OP_UNRESOLVED_VALUE)      
+         {
+           struct symbol** candidate_syms;
+           struct block** candidate_blocks;
+           int n_candidates;
+
+           n_candidates = ada_lookup_symbol_list (exp->elts[pc + 5].name,
+                                                  exp->elts[pc + 4].block,
+                                                  VAR_NAMESPACE,
+                                                  &candidate_syms,
+                                                  &candidate_blocks);
+           if (n_candidates == 1)
+             i = 0;
+           else
+             {
+               i = ada_resolve_function (candidate_syms, candidate_blocks,
+                                         n_candidates, argvec, nargs-1,
+                                         exp->elts[pc + 5].name, context_type);
+               if (i < 0) 
+                 error ("Could not find a match for %s", 
+                        ada_demangle (exp->elts[pc + 5].name));
+             }
+
+           exp->elts[pc + 3].opcode = exp->elts[pc + 6].opcode = OP_VAR_VALUE;
+           exp->elts[pc + 4].block = candidate_blocks[i];
+           exp->elts[pc + 5].symbol = candidate_syms[i];
+           if (innermost_block == NULL ||
+               contained_in (candidate_blocks[i], innermost_block))
+             innermost_block = candidate_blocks[i];
+             }*/
+       
+      }
+      break;
+    case BINOP_ADD:
+    case BINOP_SUB:
+    case BINOP_MUL:
+    case BINOP_DIV:
+    case BINOP_REM:
+    case BINOP_MOD:
+    case BINOP_CONCAT:
+    case BINOP_BITWISE_AND:
+    case BINOP_BITWISE_IOR:
+    case BINOP_BITWISE_XOR:
+    case BINOP_EQUAL:
+    case BINOP_NOTEQUAL:
+    case BINOP_LESS:
+    case BINOP_GTR:
+    case BINOP_LEQ:
+    case BINOP_GEQ:
+    case BINOP_EXP:
+    case UNOP_NEG:
+    case UNOP_PLUS:
+    case UNOP_LOGICAL_NOT:
+    case UNOP_ABS:
+      if (possible_user_operator_p (op, argvec))
+       {
+         struct symbol** candidate_syms;
+         struct block** candidate_blocks;
+         int n_candidates;
+
+         n_candidates = ada_lookup_symbol_list (ada_mangle (ada_op_name (op)),
+                                                (struct block*) NULL,
+                                                VAR_NAMESPACE,
+                                                &candidate_syms,
+                                                &candidate_blocks);
+         i = ada_resolve_function (candidate_syms, candidate_blocks,
+                                   n_candidates, argvec, nargs,
+                                   ada_op_name (op), NULL);
+         if (i < 0)
+           break;
+
+         replace_operator_with_call (expp, pc, nargs, 1,
+                                     candidate_syms[i], candidate_blocks[i]);
+         exp = *expp;
+       }
+      break;
+    }
+
+  *pos = pc;
+  return evaluate_subexp_type (exp, pos);
+}
+
+/* Return non-zero if formal type FTYPE matches actual type ATYPE.  If
+   MAY_DEREF is non-zero, the formal may be a pointer and the actual 
+   a non-pointer. */ 
+/* The term "match" here is rather loose.  The match is heuristic and
+   liberal.  FIXME: TOO liberal, in fact. */
+
+static int
+ada_type_match (ftype, atype, may_deref)
+     struct type* ftype;
+     struct type* atype;
+     int may_deref;
+{
+  CHECK_TYPEDEF (ftype);
+  CHECK_TYPEDEF (atype);
+
+  if (TYPE_CODE (ftype) == TYPE_CODE_REF)
+    ftype = TYPE_TARGET_TYPE (ftype);
+  if (TYPE_CODE (atype) == TYPE_CODE_REF)
+    atype = TYPE_TARGET_TYPE (atype);
+
+  if (TYPE_CODE (ftype) == TYPE_CODE_VOID 
+      || TYPE_CODE (atype) == TYPE_CODE_VOID)
+    return 1;
+
+  switch (TYPE_CODE (ftype)) 
+    {
+    default:
+      return 1;
+    case TYPE_CODE_PTR:
+      if (TYPE_CODE (atype) == TYPE_CODE_PTR)
+       return ada_type_match (TYPE_TARGET_TYPE (ftype),
+                              TYPE_TARGET_TYPE (atype), 0);
+      else return (may_deref && 
+                  ada_type_match (TYPE_TARGET_TYPE (ftype), atype, 0));
+    case TYPE_CODE_INT:
+    case TYPE_CODE_ENUM:
+    case TYPE_CODE_RANGE:
+      switch (TYPE_CODE (atype))
+       {
+       case TYPE_CODE_INT:
+       case TYPE_CODE_ENUM:
+       case TYPE_CODE_RANGE:
+         return 1;
+       default:
+         return 0;
+       }
+
+    case TYPE_CODE_ARRAY:
+      return (TYPE_CODE (atype) == TYPE_CODE_ARRAY 
+             || ada_is_array_descriptor (atype));
+
+    case TYPE_CODE_STRUCT:
+      if (ada_is_array_descriptor (ftype))
+       return (TYPE_CODE (atype) == TYPE_CODE_ARRAY 
+               || ada_is_array_descriptor (atype));
+      else
+       return (TYPE_CODE (atype) == TYPE_CODE_STRUCT
+               && ! ada_is_array_descriptor (atype));
+
+    case TYPE_CODE_UNION:
+    case TYPE_CODE_FLT:
+      return (TYPE_CODE (atype) == TYPE_CODE (ftype));
+    }
+}
+
+/* Return non-zero if the formals of FUNC "sufficiently match" the
+   vector of actual argument types ACTUALS of size N_ACTUALS.  FUNC
+   may also be an enumeral, in which case it is treated as a 0-
+   argument function. */
+
+static int
+ada_args_match (func, actuals, n_actuals)
+     struct symbol* func;
+     struct value** actuals;
+     int n_actuals;
+{
+  int i;
+  struct type* func_type = SYMBOL_TYPE (func);
+
+  if (SYMBOL_CLASS (func) == LOC_CONST && 
+      TYPE_CODE (func_type) == TYPE_CODE_ENUM)
+    return (n_actuals == 0);
+  else if (func_type == NULL || TYPE_CODE (func_type) != TYPE_CODE_FUNC)
+    return 0;
+
+  if (TYPE_NFIELDS (func_type) != n_actuals)
+    return 0;
+
+  for (i = 0; i < n_actuals; i += 1)
+    {
+      struct type* ftype = check_typedef (TYPE_FIELD_TYPE (func_type, i));
+      struct type* atype = check_typedef (VALUE_TYPE (actuals[i]));
+
+      if (! ada_type_match (TYPE_FIELD_TYPE (func_type, i), 
+                           VALUE_TYPE (actuals[i]), 1))
+       return 0;
+    }
+  return 1;
+}
+
+/* False iff function type FUNC_TYPE definitely does not produce a value
+   compatible with type CONTEXT_TYPE.  Conservatively returns 1 if
+   FUNC_TYPE is not a valid function type with a non-null return type
+   or an enumerated type.  A null CONTEXT_TYPE indicates any non-void type.  */
+
+static int
+return_match (func_type, context_type)
+     struct type* func_type;
+     struct type* context_type;
+{
+  struct type* return_type;
+
+  if (func_type == NULL)
+    return 1;
+
+  /* FIXME: base_type should be declared in gdbtypes.h, implemented in valarith.c */
+  /*  if (TYPE_CODE (func_type) == TYPE_CODE_FUNC)
+        return_type = base_type (TYPE_TARGET_TYPE (func_type));
+      else 
+       return_type = base_type (func_type);*/
+  if (return_type == NULL)
+    return 1;
+
+  /* FIXME: base_type should be declared in gdbtypes.h, implemented in valarith.c */
+  /*  context_type = base_type (context_type);*/
+
+  if (TYPE_CODE (return_type) == TYPE_CODE_ENUM)
+    return context_type == NULL || return_type == context_type;
+  else if (context_type == NULL)
+    return TYPE_CODE (return_type) != TYPE_CODE_VOID;
+  else
+    return TYPE_CODE (return_type) == TYPE_CODE (context_type);
+}
+
+
+/* Return the index in SYMS[0..NSYMS-1] of symbol for the 
+   function (if any) that matches the types of the NARGS arguments in
+   ARGS.  If CONTEXT_TYPE is non-null, and there is at least one match
+   that returns type CONTEXT_TYPE, then eliminate other matches.  If
+   CONTEXT_TYPE is null, prefer a non-void-returning function.
+   Asks the user if there is more than one match remaining.  Returns -1
+   if there is no such symbol or none is selected.  NAME is used
+   solely for messages.   May re-arrange and modify SYMS in
+   the process; the index returned is for the modified vector.  BLOCKS
+   is modified in parallel to SYMS. */
+
+int
+ada_resolve_function (syms, blocks, nsyms, args, nargs, name, context_type)
+     struct symbol* syms[];
+     struct block* blocks[];
+     struct value** args;
+     int nsyms, nargs;
+     const char* name;
+     struct type* context_type;
+{
+  int k;
+  int m;                       /* Number of hits */
+  struct type* fallback;
+  struct type* return_type;
+
+  return_type = context_type;
+  if (context_type == NULL)
+    fallback = builtin_type_void;
+  else
+    fallback = NULL;
+
+  m = 0; 
+  while (1)
+    {
+      for (k = 0; k < nsyms; k += 1)
+       {
+         struct type* type = check_typedef (SYMBOL_TYPE (syms[k]));
+
+         if (ada_args_match (syms[k], args, nargs)
+             && return_match (SYMBOL_TYPE (syms[k]), return_type))
+           {
+             syms[m] = syms[k];
+             if (blocks != NULL)
+               blocks[m] = blocks[k];
+             m += 1;
+           }
+       }
+      if (m > 0 || return_type == fallback)
+       break;
+      else
+       return_type = fallback;
+    }
+
+  if (m == 0)
+    return -1;
+  else if (m > 1)
+    {
+      printf_filtered ("Multiple matches for %s\n", name);
+      user_select_syms (syms, blocks, m, 1);
+      return 0;
+    }
+  return 0;
+}
+
+/* Returns true (non-zero) iff demangled name N0 should appear before N1 */
+/* in a listing of choices during disambiguation (see sort_choices, below). */
+/* The idea is that overloadings of a subprogram name from the */
+/* same package should sort in their source order.  We settle for ordering */
+/* such symbols by their trailing number (__N  or $N). */
+static int
+mangled_ordered_before (char* N0, char* N1)
+{
+  if (N1 == NULL)
+    return 0;
+  else if (N0 == NULL)
+    return 1;
+  else
+    {
+      int k0, k1;
+      for (k0 = strlen (N0)-1; k0 > 0 && isdigit (N0[k0]); k0 -= 1)
+       ;
+      for (k1 = strlen (N1)-1; k1 > 0 && isdigit (N1[k1]); k1 -= 1)
+       ;
+      if ((N0[k0] == '_' || N0[k0] == '$') && N0[k0+1] != '\000'
+         && (N1[k1] == '_' || N1[k1] == '$') && N1[k1+1] != '\000')
+       {
+         int n0, n1;
+         n0 = k0;
+         while (N0[n0] == '_' && n0 > 0 && N0[n0-1] == '_')
+           n0 -= 1;
+         n1 = k1;
+         while (N1[n1] == '_' && n1 > 0 && N1[n1-1] == '_')
+           n1 -= 1;
+         if (n0 == n1 && STREQN (N0, N1, n0))
+           return (atoi (N0+k0+1) < atoi (N1+k1+1));
+       }
+      return (strcmp (N0, N1) < 0);
+    }
+}
+         
+/* Sort SYMS[0..NSYMS-1] to put the choices in a canonical order by their */
+/* mangled names, rearranging BLOCKS[0..NSYMS-1] according to the same */
+/* permutation. */
+static void 
+sort_choices (syms, blocks, nsyms)
+     struct symbol* syms[];
+     struct block* blocks[];
+     int nsyms;
+{
+  int i, j;
+  for (i = 1; i < nsyms; i += 1) 
+    {
+      struct symbol* sym = syms[i];
+      struct block* block = blocks[i];
+      int j;
+
+      for (j = i-1; j >= 0; j -= 1) 
+       {
+         if (mangled_ordered_before (SYMBOL_NAME (syms[j]),
+                                     SYMBOL_NAME (sym)))
+           break;
+         syms[j+1] = syms[j];
+         blocks[j+1] = blocks[j];
+       }
+      syms[j+1] = sym;
+      blocks[j+1] = block;
+    }
+}
+
+/* Given a list of NSYMS symbols in SYMS and corresponding blocks in */
+/* BLOCKS, select up to MAX_RESULTS>0 by asking the user (if */
+/* necessary), returning the number selected, and setting the first */
+/* elements of SYMS and BLOCKS to the selected symbols and */
+/* corresponding blocks.  Error if no symbols selected.   BLOCKS may */
+/* be NULL, in which case it is ignored. */
+
+/* NOTE: Adapted from decode_line_2 in symtab.c, with which it ought
+   to be re-integrated one of these days. */
+
+int
+user_select_syms (syms, blocks, nsyms, max_results)
+     struct symbol* syms[];
+     struct block* blocks[];
+     int nsyms;
+     int max_results;
+{
+  int i;
+  int* chosen = (int*) alloca (sizeof(int) * nsyms);
+  int n_chosen;
+  int first_choice = (max_results == 1) ? 1 : 2;
+
+  if (max_results < 1)
+    error ("Request to select 0 symbols!");
+  if (nsyms <= 1)
+    return nsyms;
+
+  printf_unfiltered("[0] cancel\n");
+  if (max_results > 1)
+      printf_unfiltered("[1] all\n");
+
+  sort_choices (syms, blocks, nsyms);
+
+  for (i = 0; i < nsyms; i += 1)
+    {
+      if (syms[i] == NULL)
+       continue;
+
+      if (SYMBOL_CLASS (syms[i]) == LOC_BLOCK)
+       {
+         struct symtab_and_line sal = find_function_start_sal (syms[i], 1);
+         printf_unfiltered ("[%d] %s at %s:%d\n",
+                            i + first_choice, 
+                            SYMBOL_SOURCE_NAME (syms[i]),
+                            sal.symtab == NULL 
+                              ? "<no source file available>"
+                              : sal.symtab->filename, 
+                            sal.line);
+         continue;
+       }
+      else 
+       {
+         int is_enumeral = 
+           (SYMBOL_CLASS (syms[i]) == LOC_CONST
+            && SYMBOL_TYPE (syms[i]) != NULL
+            && TYPE_CODE (SYMBOL_TYPE (syms[i]))
+               == TYPE_CODE_ENUM);
+         struct symtab* symtab = symtab_for_sym (syms[i]);
+
+         if (SYMBOL_LINE (syms[i]) != 0 && symtab != NULL)
+           printf_unfiltered ("[%d] %s at %s:%d\n",
+                              i + first_choice,
+                              SYMBOL_SOURCE_NAME (syms[i]),
+                              symtab->filename, SYMBOL_LINE (syms[i]));
+         else if (is_enumeral && 
+                  TYPE_NAME (SYMBOL_TYPE (syms[i])) != NULL)
+           {
+             printf_unfiltered ("[%d] ", i + first_choice);
+             ada_print_type (SYMBOL_TYPE (syms[i]), NULL, gdb_stdout, -1, 0);
+             printf_unfiltered ("'(%s) (enumeral)\n",
+                                SYMBOL_SOURCE_NAME (syms[i]));
+           }
+         else if (symtab != NULL)
+           printf_unfiltered (is_enumeral 
+                              ? "[%d] %s in %s (enumeral)\n"
+                              : "[%d] %s at %s:?\n",
+                              i + first_choice,
+                              SYMBOL_SOURCE_NAME (syms[i]),
+                              symtab->filename);
+         else
+           printf_unfiltered (is_enumeral
+                              ? "[%d] %s (enumeral)\n"
+                              : "[%d] %s at ?\n",
+                              i + first_choice, SYMBOL_SOURCE_NAME (syms[i]));
+       }
+    }
+  
+  n_chosen = get_selections (chosen, nsyms, max_results, max_results > 1,
+                            "overload-choice");
+
+  for (i = 0; i < n_chosen; i += 1)
+    {
+      syms[i] = syms[chosen[i]];
+      if (blocks != NULL) 
+       blocks[i] = blocks[chosen[i]];
+    }
+
+  return n_chosen;
+}
+
+/* Read and validate a set of numeric choices from the user in the
+   range 0 .. N_CHOICES-1. Place the results in increasing
+   order in CHOICES[0 .. N-1], and return N.
+
+   The user types choices as a sequence of numbers on one line
+   separated by blanks, encoding them as follows:
+
+     + A choice of 0 means to cancel the selection, throwing an error.  
+     + If IS_ALL_CHOICE, a choice of 1 selects the entire set 0 .. N_CHOICES-1.
+     + The user chooses k by typing k+IS_ALL_CHOICE+1.
+
+   The user is not allowed to choose more than MAX_RESULTS values. 
+
+   ANNOTATION_SUFFIX, if present, is used to annotate the input
+   prompts (for use with the -f switch). */
+
+int
+get_selections (choices, n_choices, max_results, is_all_choice, 
+               annotation_suffix)
+     int* choices;
+     int n_choices;
+     int max_results;
+     int is_all_choice;
+     char* annotation_suffix;
+{
+  int i;
+  char* args;
+  const char* prompt;
+  int n_chosen;
+  int first_choice = is_all_choice ? 2 : 1;
+  
+  prompt = getenv ("PS2");
+  if (prompt == NULL)
+    prompt = ">";
+
+  printf_unfiltered ("%s ", prompt);
+  gdb_flush (gdb_stdout);
+
+  args = command_line_input ((char *) NULL, 0, annotation_suffix);
+  
+  if (args == NULL)
+    error_no_arg ("one or more choice numbers");
+
+  n_chosen = 0;
+
+  /* Set choices[0 .. n_chosen-1] to the users' choices in ascending 
+     order, as given in args.   Choices are validated. */
+  while (1)
+    {
+      char* args2;
+      int choice, j;
+
+      while (isspace (*args))
+       args += 1;
+      if (*args == '\0' && n_chosen == 0)
+       error_no_arg ("one or more choice numbers");
+      else if (*args == '\0')
+       break;
+
+      choice = strtol (args, &args2, 10);
+      if (args == args2 || choice < 0 || choice > n_choices + first_choice - 1)
+       error ("Argument must be choice number");
+      args = args2;
+
+      if (choice == 0) 
+       error ("cancelled");
+
+      if (choice < first_choice)
+       {
+         n_chosen = n_choices;
+         for (j = 0; j < n_choices; j += 1)
+           choices[j] = j;
+         break;
+       }
+      choice -= first_choice;
+
+      for (j = n_chosen-1; j >= 0 && choice < choices[j]; j -= 1)
+       {}
+
+      if (j < 0 || choice != choices[j])
+       {
+         int k;
+         for (k = n_chosen-1; k > j; k -= 1)
+           choices[k+1] = choices[k];
+         choices[j+1] = choice;
+         n_chosen += 1;
+       }
+    }
+
+  if (n_chosen > max_results)
+    error ("Select no more than %d of the above", max_results);
+  
+  return n_chosen;
+}
+
+/* Replace the operator of length OPLEN at position PC in *EXPP with a call */
+/* on the function identified by SYM and BLOCK, and taking NARGS */
+/* arguments.  Update *EXPP as needed to hold more space. */
+
+static void
+replace_operator_with_call (expp, pc, nargs, oplen, sym, block)
+     struct expression** expp;
+     int pc, nargs, oplen;
+     struct symbol* sym;
+     struct block* block; 
+{
+  /* A new expression, with 6 more elements (3 for funcall, 4 for function
+     symbol, -oplen for operator being replaced). */
+  struct expression* newexp = (struct expression*)
+    xmalloc (sizeof (struct expression)
+            + EXP_ELEM_TO_BYTES ((*expp)->nelts + 7 - oplen));
+  struct expression* exp = *expp;
+
+  newexp->nelts = exp->nelts + 7 - oplen;
+  newexp->language_defn = exp->language_defn;
+  memcpy (newexp->elts, exp->elts, EXP_ELEM_TO_BYTES (pc));
+  memcpy (newexp->elts + pc + 7, exp->elts + pc + oplen, 
+         EXP_ELEM_TO_BYTES (exp->nelts - pc - oplen));
+
+  newexp->elts[pc].opcode = newexp->elts[pc + 2].opcode = OP_FUNCALL;
+  newexp->elts[pc + 1].longconst = (LONGEST) nargs;
+
+  newexp->elts[pc + 3].opcode = newexp->elts[pc + 6].opcode = OP_VAR_VALUE;
+  newexp->elts[pc + 4].block = block;
+  newexp->elts[pc + 5].symbol = sym;
+
+  *expp = newexp;
+  free (exp);
+}  
+
+/* Type-class predicates */
+
+/* True iff TYPE is numeric (i.e., an INT, RANGE (of numeric type), or */
+/* FLOAT.) */
+
+static int
+numeric_type_p (type)
+     struct type* type;
+{
+  if (type == NULL)
+    return 0;
+  else {
+    switch (TYPE_CODE (type))
+      {
+      case TYPE_CODE_INT:
+      case TYPE_CODE_FLT:
+       return 1;
+      case TYPE_CODE_RANGE:
+       return (type == TYPE_TARGET_TYPE (type)
+               || numeric_type_p (TYPE_TARGET_TYPE (type)));
+      default:
+       return 0;
+      }
+  }
+}
+
+/* True iff TYPE is integral (an INT or RANGE of INTs). */
+
+static int
+integer_type_p (type)
+     struct type* type;
+{
+  if (type == NULL)
+    return 0;
+  else {
+    switch (TYPE_CODE (type))
+      {
+      case TYPE_CODE_INT:
+       return 1;
+      case TYPE_CODE_RANGE:
+       return (type == TYPE_TARGET_TYPE (type) 
+               || integer_type_p (TYPE_TARGET_TYPE (type)));
+      default:
+       return 0;
+      }
+  }
+}
+
+/* True iff TYPE is scalar (INT, RANGE, FLOAT, ENUM). */
+
+static int
+scalar_type_p (type)
+     struct type* type;
+{
+  if (type == NULL)
+    return 0;
+  else {
+    switch (TYPE_CODE (type))
+      {
+      case TYPE_CODE_INT:
+      case TYPE_CODE_RANGE:
+      case TYPE_CODE_ENUM:
+      case TYPE_CODE_FLT:
+       return 1;
+      default:
+       return 0;
+      }
+  }
+}
+
+/* True iff TYPE is discrete (INT, RANGE, ENUM). */
+
+static int
+discrete_type_p (type)
+     struct type* type;
+{
+  if (type == NULL)
+    return 0;
+  else {
+    switch (TYPE_CODE (type))
+      {
+      case TYPE_CODE_INT:
+      case TYPE_CODE_RANGE:
+      case TYPE_CODE_ENUM:
+       return 1;
+      default:
+       return 0;
+      }
+  }
+}
+
+/* Returns non-zero if OP with operatands in the vector ARGS could be
+   a user-defined function. Errs on the side of pre-defined operators
+   (i.e., result 0). */
+
+static int
+possible_user_operator_p (op, args)
+     enum exp_opcode op;
+     struct value* args[];
+{
+  struct type* type0 = check_typedef (VALUE_TYPE (args[0]));
+  struct type* type1 = 
+    (args[1] == NULL) ? NULL : check_typedef (VALUE_TYPE (args[1]));
+  
+  switch (op)
+    {
+    default:
+      return 0;
+
+    case BINOP_ADD:
+    case BINOP_SUB:
+    case BINOP_MUL:
+    case BINOP_DIV:
+      return (! (numeric_type_p (type0) && numeric_type_p (type1)));
+
+    case BINOP_REM:
+    case BINOP_MOD:
+    case BINOP_BITWISE_AND:
+    case BINOP_BITWISE_IOR:
+    case BINOP_BITWISE_XOR:
+      return (! (integer_type_p (type0) && integer_type_p (type1)));
+
+    case BINOP_EQUAL:
+    case BINOP_NOTEQUAL:
+    case BINOP_LESS:
+    case BINOP_GTR:
+    case BINOP_LEQ:
+    case BINOP_GEQ:
+      return (! (scalar_type_p (type0) && scalar_type_p (type1)));
+
+    case BINOP_CONCAT:
+      return ((TYPE_CODE (type0) != TYPE_CODE_ARRAY && 
+              (TYPE_CODE (type0) != TYPE_CODE_PTR || 
+               TYPE_CODE (TYPE_TARGET_TYPE (type0)) 
+                   != TYPE_CODE_ARRAY))
+             || (TYPE_CODE (type1) != TYPE_CODE_ARRAY && 
+                 (TYPE_CODE (type1) != TYPE_CODE_PTR || 
+                  TYPE_CODE (TYPE_TARGET_TYPE (type1)) 
+                    != TYPE_CODE_ARRAY)));
+
+    case BINOP_EXP:
+      return (! (numeric_type_p (type0) && integer_type_p (type1)));
+
+    case UNOP_NEG:
+    case UNOP_PLUS:
+    case UNOP_LOGICAL_NOT:
+    case UNOP_ABS:      
+      return (! numeric_type_p (type0));
+
+    }
+}
+\f
+                               /* Renaming */
+
+/** NOTE: In the following, we assume that a renaming type's name may
+ *  have an ___XD suffix.  It would be nice if this went away at some
+ *  point. */
+
+/* If TYPE encodes a renaming, returns the renaming suffix, which
+ * is XR for an object renaming, XRP for a procedure renaming, XRE for
+ * an exception renaming, and XRS for a subprogram renaming.  Returns
+ * NULL if NAME encodes none of these. */
+const char*
+ada_renaming_type (type)
+     struct type* type;
+{
+  if (type != NULL && TYPE_CODE (type) == TYPE_CODE_ENUM)
+    {
+      const char* name = type_name_no_tag (type);
+      const char* suffix = (name == NULL) ? NULL : strstr (name, "___XR");
+      if (suffix == NULL 
+      || (suffix[5] != '\000' && strchr ("PES_", suffix[5]) == NULL))
+       return NULL;
+      else
+       return suffix + 3;
+    }
+  else
+    return NULL;
+}
+
+/* Return non-zero iff SYM encodes an object renaming. */
+int
+ada_is_object_renaming (sym)
+     struct symbol* sym;
+{
+  const char* renaming_type = ada_renaming_type (SYMBOL_TYPE (sym));
+  return renaming_type != NULL 
+    && (renaming_type[2] == '\0' || renaming_type[2] == '_');
+}
+
+/* Assuming that SYM encodes a non-object renaming, returns the original
+ * name of the renamed entity.   The name is good until the end of
+ * parsing. */
+const char*
+ada_simple_renamed_entity (sym)
+     struct symbol* sym;
+{
+  struct type* type;
+  const char* raw_name;
+  int len;
+  char* result;
+
+  type = SYMBOL_TYPE (sym);
+  if (type == NULL || TYPE_NFIELDS (type) < 1)
+    error ("Improperly encoded renaming.");
+
+  raw_name = TYPE_FIELD_NAME (type, 0);
+  len = (raw_name == NULL ? 0 : strlen (raw_name)) - 5;
+  if (len <= 0)
+    error ("Improperly encoded renaming.");
+
+  result = xmalloc (len + 1);
+  /* FIXME: add_name_string_cleanup should be defined in parse.c */  
+  /*  add_name_string_cleanup (result);*/
+  strncpy (result, raw_name, len);
+  result[len] = '\000';
+  return result;
+}
+
+\f
+                               /* Evaluation: Function Calls */
+
+/* Copy VAL onto the stack, using and updating *SP as the stack 
+   pointer. Return VAL as an lvalue. */
+
+static struct value*
+place_on_stack (val, sp)
+    struct value* val;
+     CORE_ADDR* sp;
+{
+  CORE_ADDR old_sp = *sp;
+
+#ifdef STACK_ALIGN
+  *sp = push_bytes (*sp, VALUE_CONTENTS_RAW (val), 
+                   STACK_ALIGN (TYPE_LENGTH (check_typedef (VALUE_TYPE (val)))));
+#else
+  *sp = push_bytes (*sp, VALUE_CONTENTS_RAW (val), 
+                   TYPE_LENGTH (check_typedef (VALUE_TYPE (val))));
+#endif
+
+  VALUE_LVAL (val) = lval_memory;
+  if (INNER_THAN (1, 2))
+    VALUE_ADDRESS (val) = *sp;
+  else
+    VALUE_ADDRESS (val) = old_sp;
+
+  return val;
+}
+
+/* Return the value ACTUAL, converted to be an appropriate value for a
+   formal of type FORMAL_TYPE.  Use *SP as a stack pointer for
+   allocating any necessary descriptors (fat pointers), or copies of
+   values not residing in memory, updating it as needed. */ 
+
+static struct value*
+convert_actual (actual, formal_type0, sp)
+     struct value* actual;
+     struct type* formal_type0;
+     CORE_ADDR* sp;
+{
+  struct type* actual_type = check_typedef (VALUE_TYPE (actual));
+  struct type* formal_type = check_typedef (formal_type0);
+  struct type* formal_target =
+    TYPE_CODE (formal_type) == TYPE_CODE_PTR 
+      ? check_typedef (TYPE_TARGET_TYPE (formal_type)) : formal_type;
+  struct type* actual_target = 
+    TYPE_CODE (actual_type) == TYPE_CODE_PTR 
+      ? check_typedef (TYPE_TARGET_TYPE (actual_type)) : actual_type;
+
+  if (ada_is_array_descriptor (formal_target)
+      && TYPE_CODE (actual_target) == TYPE_CODE_ARRAY)
+    return make_array_descriptor (formal_type, actual, sp);
+  else if (TYPE_CODE (formal_type) == TYPE_CODE_PTR)
+    {
+      if (TYPE_CODE (formal_target) == TYPE_CODE_ARRAY
+         && ada_is_array_descriptor (actual_target)) 
+       return desc_data (actual);
+      else if (TYPE_CODE (actual_type) != TYPE_CODE_PTR)
+       {
+         if (VALUE_LVAL (actual) != lval_memory)
+           {
+             struct value* val;
+             actual_type = check_typedef (VALUE_TYPE (actual));
+             val = allocate_value (actual_type);
+             memcpy ((char*) VALUE_CONTENTS_RAW (val), 
+                     (char*) VALUE_CONTENTS (actual),
+                     TYPE_LENGTH (actual_type));
+             actual = place_on_stack (val, sp);
+           }
+         return value_addr (actual);
+       }
+    }
+  else if (TYPE_CODE (actual_type) == TYPE_CODE_PTR)
+    return ada_value_ind (actual);
+
+  return actual;
+}
+
+
+/* Push a descriptor of type TYPE for array value ARR on the stack at 
+   *SP, updating *SP to reflect the new descriptor.  Return either 
+   an lvalue representing the new descriptor, or (if TYPE is a pointer-
+   to-descriptor type rather than a descriptor type), a struct value*
+   representing a pointer to this descriptor. */
+
+static struct value*
+make_array_descriptor (type, arr, sp)
+     struct type* type;
+     struct value* arr;
+     CORE_ADDR* sp;
+{
+  struct type* bounds_type = desc_bounds_type (type);
+  struct type* desc_type = desc_base_type (type);
+  struct value* descriptor = allocate_value (desc_type);
+  struct value* bounds = allocate_value (bounds_type);
+  CORE_ADDR bounds_addr;
+  int i;
+  
+  for (i = ada_array_arity (check_typedef (VALUE_TYPE (arr))); i > 0; i -= 1)
+    {
+      modify_general_field (VALUE_CONTENTS (bounds),
+                           value_as_long (ada_array_bound (arr, i, 0)), 
+                           desc_bound_bitpos (bounds_type, i, 0),
+                           desc_bound_bitsize (bounds_type, i, 0));
+      modify_general_field (VALUE_CONTENTS (bounds),
+                           value_as_long (ada_array_bound (arr, i, 1)), 
+                           desc_bound_bitpos (bounds_type, i, 1),
+                           desc_bound_bitsize (bounds_type, i, 1));
+    }
+  
+  bounds = place_on_stack (bounds, sp);
+  
+  modify_general_field (VALUE_CONTENTS (descriptor),
+                       arr,
+                       fat_pntr_data_bitpos (desc_type),
+                       fat_pntr_data_bitsize (desc_type));
+  modify_general_field (VALUE_CONTENTS (descriptor),
+                       VALUE_ADDRESS (bounds),
+                       fat_pntr_bounds_bitpos (desc_type),
+                       fat_pntr_bounds_bitsize (desc_type));
+
+  descriptor = place_on_stack (descriptor, sp);
+
+  if (TYPE_CODE (type) == TYPE_CODE_PTR)
+    return value_addr (descriptor);
+  else
+    return descriptor;
+}
+
+
+/* Assuming a dummy frame has been established on the target, perform any 
+   conversions needed for calling function FUNC on the NARGS actual
+   parameters in ARGS, other than standard C conversions.   Does
+   nothing if FUNC does not have Ada-style prototype data, or if NARGS
+   does not match the number of arguments expected.   Use *SP as a
+   stack pointer for additional data that must be pushed, updating its
+   value as needed. */
+
+void
+ada_convert_actuals (func, nargs, args, sp)
+     struct value* func;
+     int nargs;
+     struct value* args[];
+     CORE_ADDR* sp;
+{
+  int i;
+
+  if (TYPE_NFIELDS (VALUE_TYPE (func)) == 0 
+      || nargs != TYPE_NFIELDS (VALUE_TYPE (func)))
+    return;
+
+  for (i = 0; i < nargs; i += 1)
+    args[i] = 
+      convert_actual (args[i], 
+                     TYPE_FIELD_TYPE (VALUE_TYPE (func), i), 
+                     sp);
+}
+
+\f
+                               /* Symbol Lookup */
+
+
+/* The vectors of symbols and blocks ultimately returned from */
+/* ada_lookup_symbol_list. */
+
+/* Current size of defn_symbols and defn_blocks */
+static size_t defn_vector_size = 0; 
+
+/* Current number of symbols found. */
+static int ndefns = 0;
+
+static struct symbol** defn_symbols = NULL;
+static struct block** defn_blocks = NULL;
+
+/* Return the result of a standard (literal, C-like) lookup of NAME in 
+ * given NAMESPACE. */
+
+static struct symbol*
+standard_lookup (name, namespace)
+     const char* name;
+     namespace_enum namespace;
+{
+  struct symbol* sym;
+  struct symtab* symtab;
+  sym = lookup_symbol (name, (struct block*) NULL, namespace, 0, &symtab);
+  return sym;
+}
+  
+
+/* Non-zero iff there is at least one non-function/non-enumeral symbol */
+/* in SYMS[0..N-1].  We treat enumerals as functions, since they */
+/* contend in overloading in the same way. */ 
+static int
+is_nonfunction (syms, n)
+     struct symbol* syms[];
+     int n;
+{
+  int i;
+
+  for (i = 0; i < n; i += 1)
+    if (TYPE_CODE (SYMBOL_TYPE (syms[i])) != TYPE_CODE_FUNC
+       && TYPE_CODE (SYMBOL_TYPE (syms[i])) != TYPE_CODE_ENUM)
+      return 1;
+
+  return 0;
+}
+
+/* If true (non-zero), then TYPE0 and TYPE1 represent equivalent
+   struct types.  Otherwise, they may not. */
+
+static int
+equiv_types (type0, type1)
+     struct type* type0;
+     struct type* type1;
+{
+  if (type0 == type1) 
+    return 1;
+  if (type0 == NULL || type1 == NULL 
+      || TYPE_CODE (type0) != TYPE_CODE (type1))
+    return 0;
+  if ((TYPE_CODE (type0) == TYPE_CODE_STRUCT 
+       || TYPE_CODE (type0) == TYPE_CODE_ENUM)
+      && ada_type_name (type0) != NULL && ada_type_name (type1) != NULL
+      && STREQ (ada_type_name (type0), ada_type_name (type1)))
+    return 1;
+  
+  return 0;
+}
+
+/* True iff SYM0 represents the same entity as SYM1, or one that is
+   no more defined than that of SYM1. */
+
+static int
+lesseq_defined_than (sym0, sym1)
+     struct symbol* sym0;
+     struct symbol* sym1;
+{
+  if (sym0 == sym1)
+    return 1;
+  if (SYMBOL_NAMESPACE (sym0) != SYMBOL_NAMESPACE (sym1)
+      || SYMBOL_CLASS (sym0) != SYMBOL_CLASS (sym1))
+    return 0;
+
+  switch (SYMBOL_CLASS (sym0)) 
+    {
+    case LOC_UNDEF:
+      return 1;
+    case LOC_TYPEDEF:
+      {
+       struct type* type0 = SYMBOL_TYPE (sym0);
+       struct type* type1 = SYMBOL_TYPE (sym1);
+       char* name0 = SYMBOL_NAME (sym0);
+       char* name1 = SYMBOL_NAME (sym1);
+       int len0 = strlen (name0);
+       return 
+         TYPE_CODE (type0) == TYPE_CODE (type1)
+         && (equiv_types (type0, type1)
+             || (len0 < strlen (name1) && STREQN (name0, name1, len0)
+                 && STREQN (name1 + len0, "___XV", 5)));
+      }
+    case LOC_CONST:
+      return SYMBOL_VALUE (sym0) == SYMBOL_VALUE (sym1)
+       && equiv_types (SYMBOL_TYPE (sym0), SYMBOL_TYPE (sym1));
+    default: 
+      return 0;      
+    }
+}
+
+/* Append SYM to the end of defn_symbols, and BLOCK to the end of
+   defn_blocks, updating ndefns, and expanding defn_symbols and
+   defn_blocks as needed.   Do not include SYM if it is a duplicate.  */
+
+static void
+add_defn_to_vec (sym, block)
+     struct symbol* sym;
+     struct block* block;
+{
+  int i;
+  size_t tmp;
+
+  if (SYMBOL_TYPE (sym) != NULL) 
+    CHECK_TYPEDEF (SYMBOL_TYPE (sym));
+  for (i = 0; i < ndefns; i += 1)
+    {
+      if (lesseq_defined_than (sym, defn_symbols[i]))
+       return;
+      else if (lesseq_defined_than (defn_symbols[i], sym))
+       {
+         defn_symbols[i] = sym;
+         defn_blocks[i] = block;
+         return;
+       }
+    }
+
+  tmp = defn_vector_size;
+  GROW_VECT (defn_symbols, tmp, ndefns+2);
+  GROW_VECT (defn_blocks, defn_vector_size, ndefns+2);
+
+  defn_symbols[ndefns] = sym;
+  defn_blocks[ndefns] = block;
+  ndefns += 1;
+}
+
+/* Look, in partial_symtab PST, for symbol NAME in given namespace.
+   Check the global symbols if GLOBAL, the static symbols if not.  Do
+   wild-card match if WILD. */
+
+static struct partial_symbol *
+ada_lookup_partial_symbol (pst, name, global, namespace, wild)
+     struct partial_symtab *pst;
+     const char *name;
+     int global;
+     namespace_enum namespace;
+     int wild;
+{
+  struct partial_symbol **start;
+  int name_len = strlen (name);
+  int length = (global ? pst->n_global_syms : pst->n_static_syms);
+  int i;
+
+  if (length == 0)
+    {
+      return (NULL);
+    }
+  
+  start = (global ?
+          pst->objfile->global_psymbols.list + pst->globals_offset :
+          pst->objfile->static_psymbols.list + pst->statics_offset  );
+
+  if (wild)
+    {
+      for (i = 0; i < length; i += 1)
+       {
+         struct partial_symbol* psym = start[i];
+
+         if (SYMBOL_NAMESPACE (psym) == namespace &&
+             wild_match (name, name_len, SYMBOL_NAME (psym)))
+           return psym;
+       }
+      return NULL;
+    }
+  else 
+    {
+      if (global)
+       {
+         int U;
+         i = 0; U = length-1;
+         while (U - i > 4) 
+           {
+             int M = (U+i) >> 1;
+             struct partial_symbol* psym = start[M];
+             if (SYMBOL_NAME (psym)[0] < name[0])
+               i = M+1;
+             else if (SYMBOL_NAME (psym)[0] > name[0])
+               U = M-1;
+             else if (strcmp (SYMBOL_NAME (psym), name) < 0)
+               i = M+1;
+             else
+               U = M;
+           }
+       }
+      else
+       i = 0;
+
+      while (i < length)
+       {
+         struct partial_symbol *psym = start[i];
+
+         if (SYMBOL_NAMESPACE (psym) == namespace)
+           {
+             int cmp = strncmp (name, SYMBOL_NAME (psym), name_len);
+       
+             if (cmp < 0) 
+               {
+                 if (global)
+                   break;
+               }
+             else if (cmp == 0 
+                      && is_name_suffix (SYMBOL_NAME (psym) + name_len)) 
+               return psym;
+           }
+         i += 1;
+       }
+
+      if (global)
+       {
+         int U;
+         i = 0; U = length-1;
+         while (U - i > 4) 
+           {
+             int M = (U+i) >> 1;
+             struct partial_symbol *psym = start[M];
+             if (SYMBOL_NAME (psym)[0] < '_')
+               i = M+1;
+             else if (SYMBOL_NAME (psym)[0] > '_')
+               U = M-1;
+             else if (strcmp (SYMBOL_NAME (psym), "_ada_") < 0)
+               i = M+1;
+             else
+               U = M;
+           }
+       }
+      else
+       i = 0;
+
+      while (i < length)
+       {
+         struct partial_symbol* psym = start[i];
+
+         if (SYMBOL_NAMESPACE (psym) == namespace)
+           {
+             int cmp;
+
+             cmp = (int) '_' - (int) SYMBOL_NAME (psym)[0];
+             if (cmp == 0) 
+               {
+                 cmp = strncmp ("_ada_", SYMBOL_NAME (psym), 5);
+                 if (cmp == 0)
+                   cmp = strncmp (name, SYMBOL_NAME (psym) + 5, name_len);
+               }
+       
+             if (cmp < 0) 
+               {
+                 if (global)
+                   break;
+               }
+             else if (cmp == 0 
+                      && is_name_suffix (SYMBOL_NAME (psym) + name_len + 5)) 
+               return psym;
+           }
+         i += 1;
+       }
+      
+    }
+  return NULL;
+}
+
+
+/* Find a symbol table containing symbol SYM or NULL if none.  */
+static struct symtab*
+symtab_for_sym (sym)
+     struct symbol* sym;
+{
+  struct symtab* s;
+  struct objfile *objfile;
+  struct block *b;
+  int i, j;
+
+  ALL_SYMTABS (objfile, s)
+    {
+      switch (SYMBOL_CLASS (sym))
+       {
+       case LOC_CONST:
+       case LOC_STATIC:
+       case LOC_TYPEDEF:
+       case LOC_REGISTER:
+       case LOC_LABEL:
+       case LOC_BLOCK:
+       case LOC_CONST_BYTES:
+         b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK);
+         for (i = 0; i < BLOCK_NSYMS (b); i += 1)
+           if (sym == BLOCK_SYM (b, i))
+             return s;
+         b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK);
+         for (i = 0; i < BLOCK_NSYMS (b); i += 1)
+           if (sym == BLOCK_SYM (b, i))
+             return s;
+         break;
+       default:
+         break;
+       }
+      switch (SYMBOL_CLASS (sym))
+       {
+       case LOC_REGISTER:
+       case LOC_ARG:
+       case LOC_REF_ARG:
+       case LOC_REGPARM:
+       case LOC_REGPARM_ADDR:
+       case LOC_LOCAL:
+       case LOC_TYPEDEF:
+       case LOC_LOCAL_ARG:
+       case LOC_BASEREG:
+       case LOC_BASEREG_ARG:
+         for (j = FIRST_LOCAL_BLOCK; 
+              j < BLOCKVECTOR_NBLOCKS (BLOCKVECTOR (s)); j += 1)
+           {
+             b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), j);
+             for (i = 0; i < BLOCK_NSYMS (b); i += 1)
+               if (sym == BLOCK_SYM (b, i))
+                 return s;
+           }
+         break;
+       default:
+         break;
+       }
+    }
+  return NULL;
+}
+
+/* Return a minimal symbol matching NAME according to Ada demangling 
+   rules. Returns NULL if there is no such minimal symbol. */
+
+struct minimal_symbol*
+ada_lookup_minimal_symbol (name)
+     const char* name;
+{
+  struct objfile* objfile;
+  struct minimal_symbol* msymbol;
+  int wild_match = (strstr (name, "__") == NULL);
+
+  ALL_MSYMBOLS (objfile, msymbol)
+    {
+      if (ada_match_name (SYMBOL_NAME (msymbol), name, wild_match)
+         && MSYMBOL_TYPE (msymbol) != mst_solib_trampoline)
+       return msymbol;
+    }
+
+  return NULL;
+}
+
+/* For all subprograms that statically enclose the subprogram of the
+ * selected frame, add symbols matching identifier NAME in NAMESPACE
+ * and their blocks to vectors *defn_symbols and *defn_blocks, as for
+ * ada_add_block_symbols (q.v.).   If WILD, treat as NAME with a
+ * wildcard prefix.  At the moment, this function uses a heuristic to
+ * find the frames of enclosing subprograms: it treats the
+ * pointer-sized value at location 0 from the local-variable base of a
+ * frame as a static link, and then searches up the call stack for a
+ * frame with that same local-variable base. */
+static void
+add_symbols_from_enclosing_procs (name, namespace, wild_match)
+     const char* name;
+     namespace_enum namespace;
+     int wild_match;
+{
+#ifdef i386
+  static struct symbol static_link_sym;
+  static struct symbol *static_link;
+
+  struct cleanup* old_chain = make_cleanup (null_cleanup, NULL);
+  struct frame_info* frame;
+  struct frame_info* target_frame;
+
+  if (static_link == NULL)
+    {
+      /* Initialize the local variable symbol that stands for the
+       * static link (when it exists). */
+      static_link = &static_link_sym;
+      SYMBOL_NAME (static_link) = "";
+      SYMBOL_LANGUAGE (static_link) = language_unknown;
+      SYMBOL_CLASS (static_link) = LOC_LOCAL;
+      SYMBOL_NAMESPACE (static_link) = VAR_NAMESPACE;
+      SYMBOL_TYPE (static_link) = lookup_pointer_type (builtin_type_void);
+      SYMBOL_VALUE (static_link) = 
+       - (long) TYPE_LENGTH (SYMBOL_TYPE (static_link));
+    }
+
+  frame = selected_frame;
+  while (frame != NULL && ndefns == 0)
+    {
+      struct block* block;
+      struct value* target_link_val = read_var_value (static_link, frame);
+      CORE_ADDR target_link;
+
+      if (target_link_val == NULL)
+       break;
+      QUIT;
+
+      target_link = target_link_val;
+      do {
+         QUIT;
+         frame = get_prev_frame (frame);
+      } while (frame != NULL && FRAME_LOCALS_ADDRESS (frame) != target_link);
+
+      if (frame == NULL)
+       break;
+
+      block = get_frame_block (frame, 0);
+      while (block != NULL && block_function (block) != NULL && ndefns == 0)
+       {
+         ada_add_block_symbols (block, name, namespace, NULL, wild_match);
+      
+         block = BLOCK_SUPERBLOCK (block);
+       }
+    }
+
+  do_cleanups (old_chain);
+#endif
+}
+
+/* True if TYPE is definitely an artificial type supplied to a symbol
+ * for which no debugging information was given in the symbol file. */
+static int
+is_nondebugging_type (type)
+     struct type* type;
+{
+  char* name = ada_type_name (type);
+  return (name != NULL && STREQ (name, "<variable, no debug info>"));
+}
+
+/* Remove any non-debugging symbols in SYMS[0 .. NSYMS-1] that definitely 
+ * duplicate other symbols in the list.  (The only case I know of where
+ * this happens is when object files containing stabs-in-ecoff are
+ * linked with files containing ordinary ecoff debugging symbols (or no
+ * debugging symbols)). Modifies SYMS to squeeze out deleted symbols,
+ * and applies the same modification to BLOCKS to maintain the
+ * correspondence between SYMS[i] and BLOCKS[i].  Returns the number
+ * of symbols in the modified list. */
+static int
+remove_extra_symbols (syms, blocks, nsyms)
+     struct symbol** syms;
+     struct block** blocks;
+     int nsyms;
+{
+  int i, j;
+
+  i = 0;
+  while (i < nsyms)
+    {
+      if (SYMBOL_NAME (syms[i]) != NULL && SYMBOL_CLASS (syms[i]) == LOC_STATIC
+         && is_nondebugging_type (SYMBOL_TYPE (syms[i])))
+       {
+         for (j = 0; j < nsyms; j += 1)
+           {
+             if (i != j 
+                 && SYMBOL_NAME (syms[j]) != NULL
+                 && STREQ (SYMBOL_NAME (syms[i]), SYMBOL_NAME (syms[j]))
+                 && SYMBOL_CLASS (syms[i]) == SYMBOL_CLASS (syms[j])
+                 && SYMBOL_VALUE_ADDRESS (syms[i]) 
+                 == SYMBOL_VALUE_ADDRESS (syms[j]))
+               {
+                 int k;
+                 for (k = i+1; k < nsyms; k += 1) 
+                   {
+                     syms[k-1] = syms[k];
+                     blocks[k-1] = blocks[k];
+                   }
+                 nsyms -= 1;
+                 goto NextSymbol;
+               }
+           }
+       }
+      i += 1;
+    NextSymbol:
+      ;
+    }
+  return nsyms;
+}
+
+/* Find symbols in NAMESPACE matching NAME, in BLOCK0 and enclosing 
+   scope and in global scopes, returning the number of matches.  Sets 
+   *SYMS to point to a vector of matching symbols, with *BLOCKS
+   pointing to the vector of corresponding blocks in which those
+   symbols reside.  These two vectors are transient---good only to the
+   next call of ada_lookup_symbol_list.  Any non-function/non-enumeral symbol
+   match within the nest of blocks whose innermost member is BLOCK0,
+   is the outermost match returned (no other matches in that or
+   enclosing blocks is returned).  If there are any matches in or
+   surrounding BLOCK0, then these alone are returned. */
+
+int
+ada_lookup_symbol_list (name, block0, namespace, syms, blocks)
+     const char *name;
+     struct block *block0;
+     namespace_enum namespace;
+     struct symbol*** syms;
+     struct block*** blocks;
+{
+  struct symbol *sym;
+  struct symtab *s;
+  struct partial_symtab *ps;
+  struct blockvector *bv;
+  struct objfile *objfile;
+  struct block *b;
+  struct block *block;
+  struct minimal_symbol *msymbol;
+  int wild_match = (strstr (name, "__") == NULL);
+  int cacheIfUnique;
+
+#ifdef TIMING
+  markTimeStart (0);
+#endif
+
+  ndefns = 0;
+  cacheIfUnique = 0;
+
+  /* Search specified block and its superiors.  */
+
+  block = block0;
+  while (block != NULL)
+    {
+      ada_add_block_symbols (block, name, namespace, NULL, wild_match);
+
+      /* If we found a non-function match, assume that's the one. */
+      if (is_nonfunction (defn_symbols, ndefns))
+       goto done;
+
+      block = BLOCK_SUPERBLOCK (block);
+    }
+
+  /* If we found ANY matches in the specified BLOCK, we're done. */
+
+  if (ndefns > 0)
+    goto done;
+  
+  cacheIfUnique = 1;
+
+  /* Now add symbols from all global blocks: symbol tables, minimal symbol
+     tables, and psymtab's */
+
+  ALL_SYMTABS (objfile, s)
+    {
+      QUIT;
+      if (! s->primary)
+       continue;
+      bv = BLOCKVECTOR (s);
+      block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+      ada_add_block_symbols (block, name, namespace, objfile, wild_match);
+    }
+
+  if (namespace == VAR_NAMESPACE)
+    {
+      ALL_MSYMBOLS (objfile, msymbol)
+       {
+         if (ada_match_name (SYMBOL_NAME (msymbol), name, wild_match))
+           {
+             switch (MSYMBOL_TYPE (msymbol))
+               {
+               case mst_solib_trampoline:
+                 break;
+               default:
+                 s = find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol));
+                 if (s != NULL)
+                   {
+                     int old_ndefns = ndefns;
+                     QUIT;
+                     bv = BLOCKVECTOR (s);
+                     block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+                     ada_add_block_symbols (block, 
+                                            SYMBOL_NAME (msymbol), 
+                                            namespace, objfile, wild_match);
+                     if (ndefns == old_ndefns) 
+                       {
+                         block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+                         ada_add_block_symbols (block, 
+                                                SYMBOL_NAME (msymbol), 
+                                                namespace, objfile,
+                                                wild_match);
+                       }
+                   }
+               }
+           }
+       }
+    }
+      
+  ALL_PSYMTABS (objfile, ps)
+    {
+      QUIT;
+      if (!ps->readin 
+         && ada_lookup_partial_symbol (ps, name, 1, namespace, wild_match))
+       {
+         s = PSYMTAB_TO_SYMTAB (ps);
+         if (! s->primary)
+           continue;
+         bv = BLOCKVECTOR (s);
+         block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+         ada_add_block_symbols (block, name, namespace, objfile, wild_match);
+       }
+    }
+  
+  /* Now add symbols from all per-file blocks if we've gotten no hits.  
+     (Not strictly correct, but perhaps better than an error).
+     Do the symtabs first, then check the psymtabs */
+  
+  if (ndefns == 0)
+    {
+
+      ALL_SYMTABS (objfile, s)
+       {
+         QUIT;
+         if (! s->primary)
+           continue;
+         bv = BLOCKVECTOR (s);
+         block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+         ada_add_block_symbols (block, name, namespace, objfile, wild_match);
+       }
+      
+      ALL_PSYMTABS (objfile, ps)
+       {
+         QUIT;
+         if (!ps->readin 
+             && ada_lookup_partial_symbol (ps, name, 0, namespace, wild_match))
+           {
+             s = PSYMTAB_TO_SYMTAB(ps);
+             bv = BLOCKVECTOR (s);
+             if (! s->primary)
+               continue;
+             block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
+             ada_add_block_symbols (block, name, namespace, 
+                                    objfile, wild_match);
+           }
+       }
+    }  
+
+  /* Finally, we try to find NAME as a local symbol in some lexically
+     enclosing block.  We do this last, expecting this case to be
+     rare. */
+  if (ndefns == 0) 
+    {
+      add_symbols_from_enclosing_procs (name, namespace, wild_match);
+      if (ndefns > 0)
+       goto done;
+    }
+
+ done:
+  ndefns = remove_extra_symbols (defn_symbols, defn_blocks, ndefns);
+
+
+  *syms = defn_symbols;
+  *blocks = defn_blocks;
+#ifdef TIMING
+  markTimeStop (0);
+#endif
+  return ndefns;
+}
+
+/* Return a symbol in NAMESPACE matching NAME, in BLOCK0 and enclosing 
+ * scope and in global scopes, or NULL if none.  NAME is folded to
+ * lower case first, unless it is surrounded in single quotes. 
+ * Otherwise, the result is as for ada_lookup_symbol_list, but is 
+ * disambiguated by user query if needed. */
+
+struct symbol*
+ada_lookup_symbol (name, block0, namespace)
+     const char *name;
+     struct block *block0;
+     namespace_enum namespace;
+{
+  struct symbol** candidate_syms;
+  struct block** candidate_blocks;
+  int n_candidates;
+
+  n_candidates = ada_lookup_symbol_list (name,
+                                        block0, namespace,
+                                        &candidate_syms, &candidate_blocks);
+
+  if (n_candidates == 0)
+    return NULL;
+  else if (n_candidates != 1)
+    user_select_syms (candidate_syms, candidate_blocks, n_candidates, 1);
+
+  return candidate_syms[0];
+}
+
+
+/* True iff STR is a possible encoded suffix of a normal Ada name 
+ * that is to be ignored for matching purposes.  Suffixes of parallel
+ * names (e.g., XVE) are not included here.  Currently, the possible suffixes 
+ * are given by the regular expression:
+ *        (X[nb]*)?(__[0-9]+|\$[0-9]+|___(LJM|X([FDBUP].*|R[^T]?)))?$
+ * 
+ */
+static int
+is_name_suffix (str)
+     const char* str;
+{
+  int k;
+  if (str[0] == 'X')
+    {
+      str += 1;
+      while (str[0] != '_' && str[0] != '\0') 
+       {
+         if (str[0] != 'n' && str[0] != 'b')
+           return 0;
+         str += 1;
+       } 
+    }
+  if (str[0] == '\000')
+    return 1;
+  if (str[0] == '_') 
+    {
+      if (str[1] != '_' || str[2] == '\000')
+       return 0;
+      if (str[2] == '_') 
+       {
+         if (STREQ (str+3, "LJM"))
+           return 1;
+         if (str[3] != 'X')
+           return 0;
+         if (str[4] == 'F' || str[4] == 'D' || str[4] == 'B' ||
+             str[4] == 'U' || str[4] == 'P')
+           return 1;
+         if (str[4] == 'R' && str[5] != 'T')
+           return 1;
+         return 0;
+       }
+      for (k = 2; str[k] != '\0'; k += 1)
+       if (!isdigit (str[k]))
+         return 0;
+      return 1;
+    }
+  if (str[0] == '$' && str[1] != '\000')
+    {
+      for (k = 1; str[k] != '\0'; k += 1)
+       if (!isdigit (str[k]))
+         return 0;
+      return 1;
+    }
+  return 0;
+}
+      
+/* True if NAME represents a name of the form A1.A2....An, n>=1 and 
+ * PATN[0..PATN_LEN-1] = Ak.Ak+1.....An for some k >= 1.  Ignores
+ * informational suffixes of NAME (i.e., for which is_name_suffix is
+ * true). */ 
+static int
+wild_match (patn, patn_len, name)
+     const char* patn;
+     int patn_len;
+     const char* name;
+{
+  int name_len;
+  int s, e;
+
+  name_len = strlen (name);
+  if (name_len >= patn_len+5 && STREQN (name, "_ada_", 5)
+      && STREQN (patn, name+5, patn_len)
+      && is_name_suffix (name+patn_len+5))
+    return 1;
+
+  while (name_len >= patn_len) 
+    {
+      if (STREQN (patn, name, patn_len)
+         && is_name_suffix (name+patn_len))
+       return 1;
+      do {
+       name += 1; name_len -= 1;
+      } while (name_len > 0
+              && name[0] != '.' && (name[0] != '_' || name[1] != '_'));
+      if (name_len <= 0)
+       return 0;
+      if (name[0] == '_')
+       {
+         if (! islower (name[2]))
+           return 0;
+         name += 2; name_len -= 2;
+       }
+      else
+       {
+         if (! islower (name[1]))
+           return 0;
+         name += 1; name_len -= 1;
+       }
+    }
+
+  return 0;
+}
+
+
+/* Add symbols from BLOCK matching identifier NAME in NAMESPACE to 
+   vector *defn_symbols, updating *defn_symbols (if necessary), *SZ (the size of
+   the vector *defn_symbols), and *ndefns (the number of symbols
+   currently stored in *defn_symbols).  If WILD, treat as NAME with a
+   wildcard prefix. OBJFILE is the section containing BLOCK. */
+
+static void 
+ada_add_block_symbols (block, name, namespace, objfile, wild)
+     struct block* block;
+     const char* name;
+     namespace_enum namespace;
+     struct objfile* objfile;
+     int wild;
+{
+  int i;
+  int name_len = strlen (name);
+  /* A matching argument symbol, if any. */
+  struct symbol *arg_sym;
+  /* Set true when we find a matching non-argument symbol */
+  int found_sym;
+  int is_sorted = BLOCK_SHOULD_SORT (block);
+
+  arg_sym = NULL; found_sym = 0;
+  if (wild)
+    {
+      for (i = 0; i < BLOCK_NSYMS (block); i += 1)
+       {
+         struct symbol *sym = BLOCK_SYM (block, i);
+
+         if (SYMBOL_NAMESPACE (sym) == namespace &&
+             wild_match (name, name_len, SYMBOL_NAME (sym)))
+           {
+             switch (SYMBOL_CLASS (sym))
+               {
+               case LOC_ARG:
+               case LOC_LOCAL_ARG:
+               case LOC_REF_ARG:
+               case LOC_REGPARM:
+               case LOC_REGPARM_ADDR:
+               case LOC_BASEREG_ARG:
+                 arg_sym = sym;
+                 break;
+               case LOC_UNRESOLVED:
+                 continue;
+               default:
+                 found_sym = 1;
+                 fill_in_ada_prototype (sym);
+                 add_defn_to_vec (fixup_symbol_section (sym, objfile), block);
+                 break;
+               }
+           }
+       }
+    }
+  else 
+    {
+      if (is_sorted)
+       {
+         int U;
+         i = 0; U = BLOCK_NSYMS (block)-1;
+         while (U - i > 4) 
+           {
+             int M = (U+i) >> 1;
+             struct symbol *sym = BLOCK_SYM (block, M);
+             if (SYMBOL_NAME (sym)[0] < name[0])
+               i = M+1;
+             else if (SYMBOL_NAME (sym)[0] > name[0])
+               U = M-1;
+             else if (strcmp (SYMBOL_NAME (sym), name) < 0)
+               i = M+1;
+             else
+               U = M;
+           }
+       }
+      else
+       i = 0;
+
+      for (; i < BLOCK_NSYMS (block); i += 1)
+       {
+         struct symbol *sym = BLOCK_SYM (block, i);
+
+         if (SYMBOL_NAMESPACE (sym) == namespace)
+           {
+             int cmp = strncmp (name, SYMBOL_NAME (sym), name_len);
+       
+             if (cmp < 0) 
+               {
+                 if (is_sorted)
+                   break;
+               }
+             else if (cmp == 0 
+                      && is_name_suffix (SYMBOL_NAME (sym) + name_len)) 
+               {
+                 switch (SYMBOL_CLASS (sym))
+                   {
+                   case LOC_ARG:
+                   case LOC_LOCAL_ARG:
+                   case LOC_REF_ARG:
+                   case LOC_REGPARM:
+                   case LOC_REGPARM_ADDR:
+                   case LOC_BASEREG_ARG:
+                     arg_sym = sym;
+                     break;
+                   case LOC_UNRESOLVED:
+                     break;
+                   default:
+                     found_sym = 1;
+                     fill_in_ada_prototype (sym);
+                     add_defn_to_vec (fixup_symbol_section (sym, objfile),
+                                      block);
+                     break;
+                   }
+               }
+           }
+       }
+    }
+
+  if (! found_sym && arg_sym != NULL)
+    {
+      fill_in_ada_prototype (arg_sym);
+      add_defn_to_vec (fixup_symbol_section (arg_sym, objfile), block);
+    }
+
+  if (! wild)
+    {
+      arg_sym = NULL; found_sym = 0;
+      if (is_sorted)
+       {
+         int U;
+         i = 0; U = BLOCK_NSYMS (block)-1;
+         while (U - i > 4) 
+           {
+             int M = (U+i) >> 1;
+             struct symbol *sym = BLOCK_SYM (block, M);
+             if (SYMBOL_NAME (sym)[0] < '_')
+               i = M+1;
+             else if (SYMBOL_NAME (sym)[0] > '_')
+               U = M-1;
+             else if (strcmp (SYMBOL_NAME (sym), "_ada_") < 0)
+               i = M+1;
+             else
+               U = M;
+           }
+       }
+      else
+       i = 0;
+
+      for (; i < BLOCK_NSYMS (block); i += 1)
+       {
+         struct symbol *sym = BLOCK_SYM (block, i);
+
+         if (SYMBOL_NAMESPACE (sym) == namespace)
+           {
+             int cmp;
+
+             cmp = (int) '_' - (int) SYMBOL_NAME (sym)[0];
+             if (cmp == 0) 
+               {
+                 cmp = strncmp ("_ada_", SYMBOL_NAME (sym), 5);
+                 if (cmp == 0)
+                   cmp = strncmp (name, SYMBOL_NAME (sym) + 5, name_len);
+               }
+       
+             if (cmp < 0) 
+               {
+                 if (is_sorted)
+                   break;
+               }
+             else if (cmp == 0 
+                      && is_name_suffix (SYMBOL_NAME (sym) + name_len + 5)) 
+               {
+                 switch (SYMBOL_CLASS (sym))
+                   {
+                   case LOC_ARG:
+                   case LOC_LOCAL_ARG:
+                   case LOC_REF_ARG:
+                   case LOC_REGPARM:
+                   case LOC_REGPARM_ADDR:
+                   case LOC_BASEREG_ARG:
+                     arg_sym = sym;
+                     break;
+                   case LOC_UNRESOLVED:
+                     break;
+                   default:
+                     found_sym = 1;
+                     fill_in_ada_prototype (sym);
+                     add_defn_to_vec (fixup_symbol_section (sym, objfile),
+                                      block);
+                     break;
+                   }
+               }
+           }
+       }
+      
+      /* NOTE: This really shouldn't be needed for _ada_ symbols.
+        They aren't parameters, right? */
+      if (! found_sym && arg_sym != NULL)
+       {
+         fill_in_ada_prototype (arg_sym);
+         add_defn_to_vec (fixup_symbol_section (arg_sym, objfile), block);
+       }
+    }
+}
+
+\f
+                               /* Function Types */
+
+/* Assuming that SYM is the symbol for a function, fill in its type 
+   with prototype information, if it is not already there.  
+   
+   Why is there provision in struct type for BOTH an array of argument
+   types (TYPE_ARG_TYPES) and for an array of typed fields, whose
+   comment suggests it may also represent argument types?  I presume
+   this is some attempt to save space.  The problem is that argument
+   names in Ada are significant.  Therefore, for Ada we use the
+   (apparently older) TYPE_FIELD_* stuff to store argument types. */
+
+
+static void
+fill_in_ada_prototype (func)
+     struct symbol* func;
+{
+  struct block* b;
+  int nargs, nsyms;
+  int i;
+  struct type* ftype;
+  struct type* rtype;
+  size_t max_fields;
+
+  if (func == NULL
+      || TYPE_CODE (SYMBOL_TYPE (func)) != TYPE_CODE_FUNC
+      || TYPE_FIELDS (SYMBOL_TYPE (func)) != NULL)
+    return;
+
+  /* We make each function type unique, so that each may have its own */
+  /* parameter types.  This particular way of doing so wastes space: */
+  /* it would be nicer to build the argument types while the original */
+  /* function type is being built (FIXME). */
+  rtype = check_typedef (TYPE_TARGET_TYPE (SYMBOL_TYPE (func)));
+  ftype = alloc_type (TYPE_OBJFILE (SYMBOL_TYPE (func)));
+  make_function_type (rtype, &ftype);
+  SYMBOL_TYPE (func) = ftype;
+
+  b = SYMBOL_BLOCK_VALUE (func);
+  nsyms = BLOCK_NSYMS (b);
+
+  nargs = 0;
+  max_fields = 8; 
+  TYPE_FIELDS (ftype) = 
+    (struct field*) xmalloc (sizeof (struct field) * max_fields);
+  for (i = 0; i < nsyms; i += 1)
+    {
+      struct symbol *sym = BLOCK_SYM (b, i);
+
+      GROW_VECT (TYPE_FIELDS (ftype), max_fields, nargs+1);
+       
+      switch (SYMBOL_CLASS (sym)) 
+       {
+       case LOC_REF_ARG:
+       case LOC_REGPARM_ADDR:
+         TYPE_FIELD_BITPOS (ftype, nargs) = nargs;
+         TYPE_FIELD_BITSIZE (ftype, nargs) = 0;
+         TYPE_FIELD_TYPE (ftype, nargs) = 
+           lookup_pointer_type (check_typedef (SYMBOL_TYPE (sym)));
+         TYPE_FIELD_NAME (ftype, nargs) = SYMBOL_NAME (sym);
+         nargs += 1;
+       
+         break;
+
+       case LOC_ARG:
+       case LOC_REGPARM:
+       case LOC_LOCAL_ARG:
+       case LOC_BASEREG_ARG:
+         TYPE_FIELD_BITPOS (ftype, nargs) = nargs;
+         TYPE_FIELD_BITSIZE (ftype, nargs) = 0;
+         TYPE_FIELD_TYPE (ftype, nargs) = check_typedef (SYMBOL_TYPE (sym));
+         TYPE_FIELD_NAME (ftype, nargs) = SYMBOL_NAME (sym);
+         nargs += 1;
+       
+         break;
+
+       default:
+         break;
+       }
+    }
+
+  /* Re-allocate fields vector; if there are no fields, make the */
+  /* fields pointer non-null anyway, to mark that this function type */
+  /* has been filled in. */
+
+  TYPE_NFIELDS (ftype) = nargs;
+  if (nargs == 0)
+    {
+      static struct field dummy_field = {0, 0, 0, 0};
+      free (TYPE_FIELDS (ftype));
+      TYPE_FIELDS (ftype) = &dummy_field;
+    }
+  else
+    {
+      struct field* fields = 
+       (struct field*) TYPE_ALLOC (ftype, nargs * sizeof (struct field));
+      memcpy ((char*) fields, 
+             (char*) TYPE_FIELDS (ftype), 
+             nargs * sizeof (struct field));
+      free (TYPE_FIELDS (ftype));
+      TYPE_FIELDS (ftype) = fields;
+    }
+}
+
+\f
+                               /* Breakpoint-related */
+
+char no_symtab_msg[] = "No symbol table is loaded.  Use the \"file\" command.";
+
+/* Assuming that LINE is pointing at the beginning of an argument to
+   'break', return a pointer to the delimiter for the initial segment
+   of that name.  This is the first ':', ' ', or end of LINE. 
+*/
+char*
+ada_start_decode_line_1 (line)
+     char* line;
+{
+  /* [NOTE: strpbrk would be more elegant, but I am reluctant to be
+     the first to use such a library function in GDB code.] */
+  char* p;
+  for (p = line; *p != '\000' && *p != ' ' && *p != ':'; p += 1)
+    ;
+  return p;
+}
+
+/* *SPEC points to a function and line number spec (as in a break
+   command), following any initial file name specification.
+
+   Return all symbol table/line specfications (sals) consistent with the
+   information in *SPEC and FILE_TABLE in the
+   following sense: 
+     + FILE_TABLE is null, or the sal refers to a line in the file
+       named by FILE_TABLE.
+     + If *SPEC points to an argument with a trailing ':LINENUM',
+       then the sal refers to that line (or one following it as closely as 
+       possible).
+     + If *SPEC does not start with '*', the sal is in a function with 
+       that name.
+
+   Returns with 0 elements if no matching non-minimal symbols found.
+
+   If *SPEC begins with a function name of the form <NAME>, then NAME
+   is taken as a literal name; otherwise the function name is subject
+   to the usual mangling.
+
+   *SPEC is updated to point after the function/line number specification.
+
+   FUNFIRSTLINE is non-zero if we desire the first line of real code
+   in each function (this is ignored in the presence of a LINENUM spec.).
+
+   If CANONICAL is non-NULL, and if any of the sals require a
+   'canonical line spec', then *CANONICAL is set to point to an array
+   of strings, corresponding to and equal in length to the returned
+   list of sals, such that (*CANONICAL)[i] is non-null and contains a 
+   canonical line spec for the ith returned sal, if needed.  If no 
+   canonical line specs are required and CANONICAL is non-null, 
+   *CANONICAL is set to NULL.
+
+   A 'canonical line spec' is simply a name (in the format of the
+   breakpoint command) that uniquely identifies a breakpoint position,
+   with no further contextual information or user selection.  It is
+   needed whenever the file name, function name, and line number
+   information supplied is insufficient for this unique
+   identification.  Currently overloaded functions, the name '*', 
+   or static functions without a filename yield a canonical line spec.
+   The array and the line spec strings are allocated on the heap; it
+   is the caller's responsibility to free them.   */
+
+struct symtabs_and_lines
+ada_finish_decode_line_1 (spec, file_table, funfirstline, canonical)
+     char** spec;
+     struct symtab* file_table;
+     int funfirstline;
+     char*** canonical;
+{
+  struct symbol** symbols;
+  struct block** blocks;
+  struct block* block;
+  int n_matches, i, line_num;
+  struct symtabs_and_lines selected;
+  struct cleanup* old_chain = make_cleanup (null_cleanup, NULL);
+  char* name;
+
+  int len;
+  char* lower_name;
+  char* unquoted_name;
+
+  if (file_table == NULL)
+    block = get_selected_block (NULL);
+  else
+    block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (file_table), STATIC_BLOCK);
+
+  if (canonical != NULL)
+    *canonical = (char**) NULL;
+
+  name = *spec;
+  if (**spec == '*') 
+    *spec += 1;
+  else
+    {
+      while (**spec != '\000' && 
+            ! strchr (ada_completer_word_break_characters, **spec))
+       *spec += 1;
+    }
+  len = *spec - name;
+
+  line_num = -1;
+  if (file_table != NULL && (*spec)[0] == ':' && isdigit ((*spec)[1]))
+    {
+      line_num = strtol (*spec + 1, spec, 10);
+      while (**spec == ' ' || **spec == '\t') 
+       *spec += 1;
+    }
+
+  if (name[0] == '*') 
+    {
+      if (line_num == -1)
+       error ("Wild-card function with no line number or file name.");
+
+      return all_sals_for_line (file_table->filename, line_num, canonical);
+    }
+
+  if (name[0] == '\'')
+    {
+      name += 1;
+      len -= 2;
+    }
+
+  if (name[0] == '<')
+    {
+      unquoted_name = (char*) alloca (len-1);
+      memcpy (unquoted_name, name+1, len-2);
+      unquoted_name[len-2] = '\000';
+      lower_name = NULL;
+    }
+  else
+    {
+      unquoted_name = (char*) alloca (len+1);
+      memcpy (unquoted_name, name, len);
+      unquoted_name[len] = '\000';
+      lower_name = (char*) alloca (len + 1);
+      for (i = 0; i < len; i += 1)
+       lower_name[i] = tolower (name[i]);
+      lower_name[len] = '\000';
+    }
+
+  n_matches = 0;
+  if (lower_name != NULL) 
+    n_matches = ada_lookup_symbol_list (ada_mangle (lower_name), block, 
+                                       VAR_NAMESPACE, &symbols, &blocks);
+  if (n_matches == 0)
+    n_matches = ada_lookup_symbol_list (unquoted_name, block, 
+                                       VAR_NAMESPACE, &symbols, &blocks);
+  if (n_matches == 0 && line_num >= 0)
+    error ("No line number information found for %s.", unquoted_name);
+  else if (n_matches == 0)
+    {
+#ifdef HPPA_COMPILER_BUG
+      /* FIXME: See comment in symtab.c::decode_line_1 */
+#undef volatile
+      volatile struct symtab_and_line val;
+#define volatile /*nothing*/
+#else
+      struct symtab_and_line val;
+#endif
+      struct minimal_symbol* msymbol;
+
+      INIT_SAL (&val);
+
+      msymbol = NULL;
+      if (lower_name != NULL) 
+       msymbol = ada_lookup_minimal_symbol (ada_mangle (lower_name));
+      if (msymbol == NULL)
+       msymbol = ada_lookup_minimal_symbol (unquoted_name);
+      if (msymbol != NULL)
+       {
+         val.pc      = SYMBOL_VALUE_ADDRESS (msymbol);
+         val.section = SYMBOL_BFD_SECTION (msymbol);
+         if (funfirstline)
+           {
+             val.pc += FUNCTION_START_OFFSET;
+             SKIP_PROLOGUE (val.pc);
+           }
+         selected.sals = (struct symtab_and_line *)
+           xmalloc (sizeof (struct symtab_and_line));
+         selected.sals[0] = val;
+         selected.nelts = 1;
+         return selected;
+       }       
+      
+      if (!have_full_symbols () &&
+         !have_partial_symbols () && !have_minimal_symbols ())
+       error (no_symtab_msg);
+
+      error ("Function \"%s\" not defined.", unquoted_name);
+      return selected; /* for lint */
+    }
+
+  if (line_num >= 0)
+    {
+      return 
+       find_sal_from_funcs_and_line (file_table->filename, line_num, 
+                                     symbols, n_matches);
+    }
+  else
+    {
+      selected.nelts = user_select_syms (symbols, blocks, n_matches, n_matches);
+    }
+
+  selected.sals = (struct symtab_and_line*) 
+    xmalloc (sizeof (struct symtab_and_line) * selected.nelts);
+  memset (selected.sals, 0, selected.nelts * sizeof (selected.sals[i]));
+  make_cleanup (free, selected.sals);
+
+  i = 0;
+  while (i < selected.nelts)
+    {
+      if (SYMBOL_CLASS (symbols[i]) == LOC_BLOCK) 
+       selected.sals[i] = find_function_start_sal (symbols[i], funfirstline);
+      else if (SYMBOL_LINE (symbols[i]) != 0) 
+       {
+         selected.sals[i].symtab = symtab_for_sym (symbols[i]);
+         selected.sals[i].line = SYMBOL_LINE (symbols[i]);
+       }
+      else if (line_num >= 0)
+       {
+         /* Ignore this choice */
+         symbols[i] = symbols[selected.nelts-1];
+         blocks[i] = blocks[selected.nelts-1];
+         selected.nelts -= 1;
+         continue;
+       }
+      else 
+       error ("Line number not known for symbol \"%s\"", unquoted_name);
+      i += 1;
+    }
+
+  if (canonical != NULL && (line_num >= 0 || n_matches > 1))
+    {
+      *canonical = (char**) xmalloc (sizeof(char*) * selected.nelts);
+      for (i = 0; i < selected.nelts; i += 1)
+       (*canonical)[i] = 
+         extended_canonical_line_spec (selected.sals[i], 
+                                       SYMBOL_SOURCE_NAME (symbols[i]));
+    }
+   
+  discard_cleanups (old_chain);
+  return selected;
+}  
+      
+/* The (single) sal corresponding to line LINE_NUM in a symbol table
+   with file name FILENAME that occurs in one of the functions listed 
+   in SYMBOLS[0 .. NSYMS-1]. */   
+static struct symtabs_and_lines
+find_sal_from_funcs_and_line (filename, line_num, symbols, nsyms)
+     const char* filename;
+     int line_num;
+     struct symbol** symbols;
+     int nsyms;
+{
+  struct symtabs_and_lines sals;
+  int best_index, best;
+  struct linetable* best_linetable;
+  struct objfile* objfile;
+  struct symtab* s;
+  struct symtab* best_symtab;
+
+  read_all_symtabs (filename);
+
+  best_index = 0; best_linetable = NULL; best_symtab = NULL;
+  best = 0;
+  ALL_SYMTABS (objfile, s)
+    {
+      struct linetable *l;
+      int ind, exact;
+
+      QUIT;    
+
+      if (!STREQ (filename, s->filename))
+       continue;
+      l = LINETABLE (s);
+      ind = find_line_in_linetable (l, line_num, symbols, nsyms, &exact);
+      if (ind >= 0)
+       {
+         if (exact)
+           {
+             best_index = ind;
+             best_linetable = l;
+             best_symtab = s;
+             goto done;
+           }
+         if (best == 0 || l->item[ind].line < best)
+           {
+             best = l->item[ind].line;
+             best_index = ind;
+             best_linetable = l;
+             best_symtab = s;
+           }
+       }
+    }
+
+  if (best == 0)
+    error ("Line number not found in designated function.");
+
+ done:
+  
+  sals.nelts = 1;
+  sals.sals = (struct symtab_and_line*) xmalloc (sizeof (sals.sals[0]));
+
+  INIT_SAL (&sals.sals[0]);
+  
+  sals.sals[0].line = best_linetable->item[best_index].line;
+  sals.sals[0].pc = best_linetable->item[best_index].pc;
+  sals.sals[0].symtab = best_symtab;
+
+  return sals;
+}
+
+/* Return the index in LINETABLE of the best match for LINE_NUM whose
+   pc falls within one of the functions denoted by SYMBOLS[0..NSYMS-1].  
+   Set *EXACTP to the 1 if the match is exact, and 0 otherwise. */
+static int
+find_line_in_linetable (linetable, line_num, symbols, nsyms, exactp)
+     struct linetable* linetable;
+     int line_num;
+     struct symbol** symbols;
+     int nsyms;
+     int* exactp;
+{
+  int i, len, best_index, best;
+
+  if (line_num <= 0 || linetable == NULL)
+    return -1;
+
+  len = linetable->nitems;
+  for (i = 0, best_index = -1, best = 0; i < len; i += 1)
+    {
+      int k;
+      struct linetable_entry* item = &(linetable->item[i]);
+
+      for (k = 0; k < nsyms; k += 1)
+       {
+         if (symbols[k] != NULL && SYMBOL_CLASS (symbols[k]) == LOC_BLOCK
+             && item->pc >= BLOCK_START (SYMBOL_BLOCK_VALUE (symbols[k]))
+             && item->pc < BLOCK_END (SYMBOL_BLOCK_VALUE (symbols[k])))
+           goto candidate;
+       }
+      continue;
+
+    candidate:
+
+      if (item->line == line_num)
+       {
+         *exactp = 1;
+         return i;
+       }
+
+      if (item->line > line_num && (best == 0 || item->line < best))
+       {
+         best = item->line;
+         best_index = i;
+       }
+    }
+
+  *exactp = 0;
+  return best_index;
+}
+
+/* Find the smallest k >= LINE_NUM such that k is a line number in
+   LINETABLE, and k falls strictly within a named function that begins at
+   or before LINE_NUM.  Return -1 if there is no such k. */
+static int
+nearest_line_number_in_linetable (linetable, line_num)
+     struct linetable* linetable;
+     int line_num;
+{
+  int i, len, best;
+
+  if (line_num <= 0 || linetable == NULL || linetable->nitems == 0)
+    return -1;
+  len = linetable->nitems;
+
+  i = 0; best = INT_MAX;
+  while (i < len)
+    {
+      int k;
+      struct linetable_entry* item = &(linetable->item[i]);
+
+      if (item->line >= line_num && item->line < best)
+       {
+         char* func_name;
+         CORE_ADDR start, end;
+
+         func_name = NULL;
+         find_pc_partial_function (item->pc, &func_name, &start, &end);
+
+         if (func_name != NULL && item->pc < end)
+           {
+             if (item->line == line_num)
+               return line_num;
+             else 
+               {
+                 struct symbol* sym = 
+                   standard_lookup (func_name, VAR_NAMESPACE);
+                 if (is_plausible_func_for_line (sym, line_num))
+                   best = item->line;
+                 else
+                   {
+                     do
+                       i += 1;
+                     while (i < len && linetable->item[i].pc < end);
+                     continue;
+                   }
+               }
+           }
+       }
+
+      i += 1;
+    }
+
+  return (best == INT_MAX) ? -1 : best;
+}
+
+
+/* Return the next higher index, k, into LINETABLE such that k > IND, 
+   entry k in LINETABLE has a line number equal to LINE_NUM, k
+   corresponds to a PC that is in a function different from that 
+   corresponding to IND, and falls strictly within a named function
+   that begins at a line at or preceding STARTING_LINE.  
+   Return -1 if there is no such k.  
+   IND == -1 corresponds to no function. */
+
+static int
+find_next_line_in_linetable (linetable, line_num, starting_line, ind)
+     struct linetable* linetable;
+     int line_num;
+     int starting_line;
+     int ind;
+{
+  int i, len;
+
+  if (line_num <= 0 || linetable == NULL || ind >= linetable->nitems)
+    return -1;
+  len = linetable->nitems;
+
+  if (ind >= 0) 
+    {
+      CORE_ADDR start, end;
+
+      if (find_pc_partial_function (linetable->item[ind].pc,
+                                   (char**) NULL, &start, &end)) 
+       {
+         while (ind < len && linetable->item[ind].pc < end)
+           ind += 1;
+       }
+      else
+       ind += 1;
+    }
+  else
+    ind = 0;
+
+  i = ind;
+  while (i < len)
+    {
+      int k;
+      struct linetable_entry* item = &(linetable->item[i]);
+
+      if (item->line >= line_num)
+       {
+         char* func_name;
+         CORE_ADDR start, end;
+
+         func_name = NULL;
+         find_pc_partial_function (item->pc, &func_name, &start, &end);
+
+         if (func_name != NULL && item->pc < end)
+           {
+             if (item->line == line_num)
+               {
+                 struct symbol* sym = 
+                   standard_lookup (func_name, VAR_NAMESPACE);
+                 if (is_plausible_func_for_line (sym, starting_line))
+                   return i;
+                 else
+                   {
+                     while ((i+1) < len && linetable->item[i+1].pc < end)
+                       i += 1;
+                   }
+               }
+           }
+       }
+      i += 1;
+    }
+
+  return -1;
+}
+
+/* True iff function symbol SYM starts somewhere at or before line #
+   LINE_NUM. */
+static int
+is_plausible_func_for_line (sym, line_num)
+     struct symbol* sym;
+     int line_num;
+{
+  struct symtab_and_line start_sal;
+
+  if (sym == NULL)
+    return 0;
+
+  start_sal = find_function_start_sal (sym, 0);
+
+  return (start_sal.line != 0 && line_num >= start_sal.line);
+}
+
+static void
+debug_print_lines (lt)
+     struct linetable* lt;
+{
+  int i;
+
+  if (lt == NULL) 
+    return;
+
+  fprintf (stderr, "\t");
+  for (i = 0; i < lt->nitems; i += 1)
+    fprintf (stderr, "(%d->%p) ", lt->item[i].line, (void *) lt->item[i].pc);
+  fprintf (stderr, "\n");
+}
+
+static void
+debug_print_block (b)
+     struct block* b;
+{
+  int i;
+  fprintf (stderr, "Block: %p; [0x%lx, 0x%lx]", 
+          b, BLOCK_START(b), BLOCK_END(b));
+  if (BLOCK_FUNCTION(b) != NULL)
+    fprintf (stderr, " Function: %s", SYMBOL_NAME (BLOCK_FUNCTION(b)));
+  fprintf (stderr, "\n");
+  fprintf (stderr, "\t    Superblock: %p\n", BLOCK_SUPERBLOCK(b));
+  fprintf (stderr, "\t    Symbols:");
+  for (i = 0; i < BLOCK_NSYMS (b); i += 1)
+    {
+      if (i > 0 && i % 4 == 0)
+       fprintf (stderr, "\n\t\t    ");
+      fprintf (stderr, " %s", SYMBOL_NAME (BLOCK_SYM (b, i)));
+    }
+  fprintf (stderr, "\n");
+}
+
+static void
+debug_print_blocks (bv)
+     struct blockvector* bv;
+{
+  int i;
+
+  if (bv == NULL)
+    return;
+  for (i = 0; i < BLOCKVECTOR_NBLOCKS (bv); i += 1) {
+    fprintf (stderr, "%6d. ", i);
+    debug_print_block (BLOCKVECTOR_BLOCK (bv, i));
+  }
+}
+
+static void
+debug_print_symtab (s)
+     struct symtab* s;
+{
+  fprintf (stderr, "Symtab %p\n    File: %s; Dir: %s\n", s,
+          s->filename, s->dirname);
+  fprintf (stderr, "    Blockvector: %p, Primary: %d\n",
+          BLOCKVECTOR(s), s->primary);
+  debug_print_blocks (BLOCKVECTOR(s));
+  fprintf (stderr, "    Line table: %p\n", LINETABLE (s));
+  debug_print_lines (LINETABLE(s));
+}
+
+/* Read in all symbol tables corresponding to partial symbol tables
+   with file name FILENAME. */
+static void
+read_all_symtabs (filename)
+     const char* filename;
+{
+  struct partial_symtab* ps;
+  struct objfile* objfile;
+
+  ALL_PSYMTABS (objfile, ps)
+    {
+      QUIT;
+
+      if (STREQ (filename, ps->filename))
+       PSYMTAB_TO_SYMTAB (ps);
+    }
+}
+
+/* All sals corresponding to line LINE_NUM in a symbol table from file
+   FILENAME, as filtered by the user.  If CANONICAL is not null, set
+   it to a corresponding array of canonical line specs. */
+static struct symtabs_and_lines
+all_sals_for_line (filename, line_num, canonical)
+     const char* filename;
+     int line_num;
+     char*** canonical;
+{
+  struct symtabs_and_lines result;
+  struct objfile* objfile;
+  struct symtab* s;
+  struct cleanup* old_chain = make_cleanup (null_cleanup, NULL);
+  size_t len;
+
+  read_all_symtabs (filename);
+
+  result.sals = (struct symtab_and_line*) xmalloc (4 * sizeof (result.sals[0]));
+  result.nelts = 0;
+  len = 4;
+  make_cleanup (free_current_contents, &result.sals);
+
+  ALL_SYMTABS (objfile, s) 
+    {
+      int ind, target_line_num;
+
+      QUIT;
+
+      if (!STREQ (s->filename, filename))
+       continue;
+
+      target_line_num = 
+       nearest_line_number_in_linetable (LINETABLE (s), line_num);
+      if (target_line_num == -1)
+       continue;
+
+      ind = -1;
+      while (1) 
+       {
+         ind = 
+           find_next_line_in_linetable (LINETABLE (s),
+                                        target_line_num, line_num, ind);
+         
+         if (ind < 0)
+           break;
+
+         GROW_VECT (result.sals, len, result.nelts+1);
+         INIT_SAL (&result.sals[result.nelts]);
+         result.sals[result.nelts].line = LINETABLE(s)->item[ind].line;
+         result.sals[result.nelts].pc = LINETABLE(s)->item[ind].pc;
+         result.sals[result.nelts].symtab = s;
+         result.nelts += 1;
+       }
+    }
+
+  if (canonical != NULL || result.nelts > 1)
+    {
+      int k;
+      char** func_names = (char**) alloca (result.nelts * sizeof (char*));
+      int first_choice = (result.nelts > 1) ? 2 : 1;
+      int n;
+      int* choices = (int*) alloca (result.nelts * sizeof (int));
+      
+      for (k = 0; k < result.nelts; k += 1) 
+       {
+         find_pc_partial_function (result.sals[k].pc, &func_names[k], 
+                                   (CORE_ADDR*) NULL, (CORE_ADDR*) NULL);
+         if (func_names[k] == NULL)
+           error ("Could not find function for one or more breakpoints.");
+       }
+      
+      if (result.nelts > 1) 
+       {
+         printf_unfiltered("[0] cancel\n");
+         if (result.nelts > 1) 
+           printf_unfiltered("[1] all\n");
+         for (k = 0; k < result.nelts; k += 1)
+           printf_unfiltered ("[%d] %s\n", k + first_choice, 
+                              ada_demangle (func_names[k]));
+         
+         n = get_selections (choices, result.nelts, result.nelts,
+                             result.nelts > 1, "instance-choice");
+      
+         for (k = 0; k < n; k += 1) 
+           {
+             result.sals[k] = result.sals[choices[k]];
+             func_names[k] = func_names[choices[k]];
+           }
+         result.nelts = n;
+       }
+
+      if (canonical != NULL) 
+       {
+         *canonical = (char**) xmalloc (result.nelts * sizeof (char**));
+         make_cleanup (free, *canonical);
+         for (k = 0; k < result.nelts; k += 1) 
+           {
+             (*canonical)[k] = 
+               extended_canonical_line_spec (result.sals[k], func_names[k]);
+             if ((*canonical)[k] == NULL)
+               error ("Could not locate one or more breakpoints.");
+             make_cleanup (free, (*canonical)[k]);
+           }
+       }
+    }
+
+  discard_cleanups (old_chain);
+  return result;
+}
+
+
+/* A canonical line specification of the form FILE:NAME:LINENUM for
+   symbol table and line data SAL.  NULL if insufficient
+   information. The caller is responsible for releasing any space
+   allocated. */
+
+static char*
+extended_canonical_line_spec (sal, name)
+     struct symtab_and_line sal;
+     const char* name;
+{
+  char* r;
+
+  if (sal.symtab == NULL || sal.symtab->filename == NULL || 
+      sal.line <= 0)
+    return NULL;
+
+  r = (char*) xmalloc (strlen (name) + strlen (sal.symtab->filename)  
+                      + sizeof(sal.line)*3 + 3);
+  sprintf (r, "%s:'%s':%d", sal.symtab->filename, name, sal.line);
+  return r;
+}
+
+#if 0
+int begin_bnum = -1;
+#endif
+int begin_annotate_level = 0;
+
+static void 
+begin_cleanup (void* dummy) 
+{
+  begin_annotate_level = 0;
+}
+
+static void
+begin_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  struct minimal_symbol *msym;
+  CORE_ADDR main_program_name_addr;
+  char main_program_name[1024];
+  struct cleanup* old_chain = make_cleanup (begin_cleanup, NULL);
+  begin_annotate_level = 2;
+
+  /* Check that there is a program to debug */
+  if (!have_full_symbols () && !have_partial_symbols ())
+    error ("No symbol table is loaded.  Use the \"file\" command.");
+  
+  /* Check that we are debugging an Ada program */
+  /*  if (ada_update_initial_language (language_unknown, NULL) != language_ada)
+    error ("Cannot find the Ada initialization procedure.  Is this an Ada main program?");
+  */
+  /* FIXME: language_ada should be defined in defs.h */
+
+  /* Get the address of the name of the main procedure */
+  msym = lookup_minimal_symbol (ADA_MAIN_PROGRAM_SYMBOL_NAME, NULL, NULL);
+
+  if (msym != NULL)
+  {
+    main_program_name_addr = SYMBOL_VALUE_ADDRESS (msym);
+    if (main_program_name_addr == 0)
+      error ("Invalid address for Ada main program name.");
+
+    /* Read the name of the main procedure */
+    extract_string (main_program_name_addr, main_program_name);
+
+    /* Put a temporary breakpoint in the Ada main program and run */
+    do_command ("tbreak ", main_program_name, 0);
+    do_command ("run ", args, 0);
+  }
+  else
+  {
+    /* If we could not find the symbol containing the name of the
+       main program, that means that the compiler that was used to build
+       was not recent enough. In that case, we fallback to the previous
+       mechanism, which is a little bit less reliable, but has proved to work
+       in most cases. The only cases where it will fail is when the user
+       has set some breakpoints which will be hit before the end of the
+       begin command processing (eg in the initialization code).
+
+       The begining of the main Ada subprogram is located by breaking
+       on the adainit procedure. Since we know that the binder generates
+       the call to this procedure exactly 2 calls before the call to the
+       Ada main subprogram, it is then easy to put a breakpoint on this
+       Ada main subprogram once we hit adainit.
+     */
+     do_command ("tbreak adainit", 0);
+     do_command ("run ", args, 0);
+     do_command ("up", 0);
+     do_command ("tbreak +2", 0);
+     do_command ("continue", 0);
+     do_command ("step", 0);
+  }
+
+  do_cleanups (old_chain);
+}
+
+int
+is_ada_runtime_file (filename)
+     char *filename;
+{
+  return (STREQN (filename, "s-", 2) ||
+         STREQN (filename, "a-", 2) ||
+         STREQN (filename, "g-", 2) ||
+         STREQN (filename, "i-", 2));
+}
+
+/* find the first frame that contains debugging information and that is not
+   part of the Ada run-time, starting from fi and moving upward. */
+
+int
+find_printable_frame (fi, level)
+     struct frame_info *fi;
+     int level;
+{
+  struct symtab_and_line sal;
+  
+  for (; fi != NULL; level += 1, fi = get_prev_frame (fi))
+    {
+      /* If fi is not the innermost frame, that normally means that fi->pc
+        points to *after* the call instruction, and we want to get the line
+        containing the call, never the next line.  But if the next frame is
+        a signal_handler_caller or a dummy frame, then the next frame was
+        not entered as the result of a call, and we want to get the line
+        containing fi->pc.  */
+      sal =
+        find_pc_line (fi->pc,
+                     fi->next != NULL
+                     && !fi->next->signal_handler_caller
+                     && !frame_in_dummy (fi->next));
+      if (sal.symtab && !is_ada_runtime_file (sal.symtab->filename))
+       {
+#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
+       /* libpthread.so contains some debugging information that prevents us
+          from finding the right frame */
+
+         if (sal.symtab->objfile &&
+             STREQ (sal.symtab->objfile->name, "/usr/shlib/libpthread.so"))
+             continue;
+#endif
+         selected_frame = fi;
+         break;
+       }
+    }
+
+  return level;
+}
+
+void
+ada_report_exception_break (b)
+     struct breakpoint *b;
+{
+#ifdef UI_OUT
+  /* FIXME: break_on_exception should be defined in breakpoint.h */
+  /*  if (b->break_on_exception == 1)
+    {
+      /* Assume that cond has 16 elements, the 15th
+        being the exception */ /*
+      if (b->cond && b->cond->nelts == 16)
+       {
+         ui_out_text (uiout, "on ");
+         ui_out_field_string (uiout, "exception",
+                              SYMBOL_NAME (b->cond->elts[14].symbol));
+       }
+      else
+       ui_out_text (uiout, "on all exceptions");
+    }
+  else if (b->break_on_exception == 2)
+    ui_out_text (uiout, "on unhandled exception");
+  else if (b->break_on_exception == 3)
+    ui_out_text (uiout, "on assert failure");
+#else
+  if (b->break_on_exception == 1)
+  {*/
+      /* Assume that cond has 16 elements, the 15th
+        being the exception */ /*
+      if (b->cond && b->cond->nelts == 16)
+       {
+         fputs_filtered ("on ", gdb_stdout);
+         fputs_filtered (SYMBOL_NAME
+                         (b->cond->elts[14].symbol), gdb_stdout);
+       }
+      else
+       fputs_filtered ("on all exceptions", gdb_stdout);
+    }
+  else if (b->break_on_exception == 2)
+    fputs_filtered ("on unhandled exception", gdb_stdout);
+  else if (b->break_on_exception == 3)
+    fputs_filtered ("on assert failure", gdb_stdout);
+*/    
+#endif
+}
+
+int
+ada_is_exception_sym (struct symbol* sym)
+{
+  char *type_name = type_name_no_tag (SYMBOL_TYPE (sym));
+  
+  return (SYMBOL_CLASS (sym) != LOC_TYPEDEF
+         && SYMBOL_CLASS (sym) != LOC_BLOCK
+         && SYMBOL_CLASS (sym) != LOC_CONST
+         && type_name != NULL
+         && STREQ (type_name, "exception"));
+}
+
+int
+ada_maybe_exception_partial_symbol (struct partial_symbol* sym)
+{
+  return (SYMBOL_CLASS (sym) != LOC_TYPEDEF
+         && SYMBOL_CLASS (sym) != LOC_BLOCK
+         && SYMBOL_CLASS (sym) != LOC_CONST);
+}
+
+/* If ARG points to an Ada exception or assert breakpoint, rewrite
+   into equivalent form.  Return resulting argument string. Set
+   *BREAK_ON_EXCEPTIONP to 1 for ordinary break on exception, 2 for
+   break on unhandled, 3 for assert, 0 otherwise. */
+char* ada_breakpoint_rewrite (char* arg, int* break_on_exceptionp)
+{
+  if (arg == NULL)
+    return arg;
+  *break_on_exceptionp = 0;
+  /* FIXME: language_ada should be defined in defs.h */  
+  /*  if (current_language->la_language == language_ada
+      && STREQN (arg, "exception", 9) &&
+      (arg[9] == ' ' || arg[9] == '\t' || arg[9] == '\0'))
+    {
+      char *tok, *end_tok;
+      int toklen;
+
+      *break_on_exceptionp = 1;
+
+      tok = arg+9;
+      while (*tok == ' ' || *tok == '\t')
+       tok += 1;
+
+      end_tok = tok;
+
+      while (*end_tok != ' ' && *end_tok != '\t' && *end_tok != '\000')
+       end_tok += 1;
+
+      toklen = end_tok - tok;
+
+      arg = (char*) xmalloc (sizeof ("__gnat_raise_nodefer_with_msg if "
+                                    "long_integer(e) = long_integer(&)")
+                            + toklen + 1);
+      make_cleanup (free, arg);
+      if (toklen == 0)
+       strcpy (arg, "__gnat_raise_nodefer_with_msg");
+      else if (STREQN (tok, "unhandled", toklen))
+       {
+         *break_on_exceptionp = 2;
+         strcpy (arg, "__gnat_unhandled_exception");
+       }
+      else
+       {
+         sprintf (arg, "__gnat_raise_nodefer_with_msg if "
+                  "long_integer(e) = long_integer(&%.*s)", 
+                  toklen, tok);
+       }
+    }
+  else if (current_language->la_language == language_ada
+          && STREQN (arg, "assert", 6) &&
+          (arg[6] == ' ' || arg[6] == '\t' || arg[6] == '\0'))
+    {
+      char *tok = arg + 6;
+
+      *break_on_exceptionp = 3;
+
+      arg = (char*) 
+       xmalloc (sizeof ("system__assertions__raise_assert_failure")
+                + strlen (tok) + 1);
+      make_cleanup (free, arg);
+      sprintf (arg, "system__assertions__raise_assert_failure%s", tok);
+    }
+  */
+  return arg;
+}
+
+\f
+                               /* Field Access */
+
+/* True if field number FIELD_NUM in struct or union type TYPE is supposed
+   to be invisible to users. */
+
+int
+ada_is_ignored_field (type, field_num)
+     struct type *type;
+     int field_num;
+{
+  if (field_num < 0 || field_num > TYPE_NFIELDS (type))
+    return 1;
+  else 
+    {
+      const char* name = TYPE_FIELD_NAME (type, field_num);
+      return (name == NULL
+             || (name[0] == '_' && ! STREQN (name, "_parent", 7)));
+    }
+}
+
+/* True iff structure type TYPE has a tag field. */
+
+int
+ada_is_tagged_type (type)
+     struct type *type;
+{
+  if (type == NULL || TYPE_CODE (type) != TYPE_CODE_STRUCT)
+    return 0;
+
+  return (ada_lookup_struct_elt_type (type, "_tag", 1, NULL) != NULL);
+}
+
+/* The type of the tag on VAL. */
+
+struct type*
+ada_tag_type (val)
+     struct value* val;
+{
+  return ada_lookup_struct_elt_type (VALUE_TYPE (val), "_tag", 0, NULL);
+}
+
+/* The value of the tag on VAL. */
+
+struct value*
+ada_value_tag (val)
+     struct value* val;
+{
+  return ada_value_struct_elt (val, "_tag", "record");
+}
+
+/* The parent type of TYPE, or NULL if none. */
+
+struct type*
+ada_parent_type (type)
+     struct type *type;
+{
+  int i;
+
+  CHECK_TYPEDEF (type);
+
+  if (type == NULL || TYPE_CODE (type) != TYPE_CODE_STRUCT)
+    return NULL;
+
+  for (i = 0; i < TYPE_NFIELDS (type); i += 1)
+    if (ada_is_parent_field (type, i))
+      return check_typedef (TYPE_FIELD_TYPE (type, i));
+
+  return NULL;
+}
+
+/* True iff field number FIELD_NUM of structure type TYPE contains the 
+   parent-type (inherited) fields of a derived type.  Assumes TYPE is 
+   a structure type with at least FIELD_NUM+1 fields. */
+
+int
+ada_is_parent_field (type, field_num)
+     struct type *type;
+     int field_num;
+{
+  const char* name = TYPE_FIELD_NAME (check_typedef (type), field_num);
+  return (name != NULL && 
+         (STREQN (name, "PARENT", 6) || STREQN (name, "_parent", 7)));
+}
+
+/* True iff field number FIELD_NUM of structure type TYPE is a 
+   transparent wrapper field (which should be silently traversed when doing
+   field selection and flattened when printing).  Assumes TYPE is a 
+   structure type with at least FIELD_NUM+1 fields.  Such fields are always
+   structures. */
+
+int
+ada_is_wrapper_field (type, field_num)
+     struct type *type;
+     int field_num;
+{
+  const char* name = TYPE_FIELD_NAME (type, field_num);
+  return (name != NULL 
+         && (STREQN (name, "PARENT", 6) || STREQ (name, "REP") 
+             || STREQN (name, "_parent", 7)
+             || name[0] == 'S' || name[0] == 'R' || name[0] == 'O'));
+}
+
+/* True iff field number FIELD_NUM of structure or union type TYPE 
+   is a variant wrapper.  Assumes TYPE is a structure type with at least 
+   FIELD_NUM+1 fields. */ 
+
+int
+ada_is_variant_part (type, field_num)
+     struct type *type;
+     int field_num;
+{
+  struct type* field_type = TYPE_FIELD_TYPE (type, field_num);
+  return (TYPE_CODE (field_type) == TYPE_CODE_UNION
+         || (is_dynamic_field (type, field_num)
+             && TYPE_CODE (TYPE_TARGET_TYPE (field_type)) == TYPE_CODE_UNION));
+}
+
+/* Assuming that VAR_TYPE is a variant wrapper (type of the variant part)
+   whose discriminants are contained in the record type OUTER_TYPE, 
+   returns the type of the controlling discriminant for the variant.  */
+
+struct type*
+ada_variant_discrim_type (var_type, outer_type)
+     struct type *var_type;
+     struct type *outer_type;
+{
+  char* name = ada_variant_discrim_name (var_type);
+  struct type *type = 
+    ada_lookup_struct_elt_type (outer_type, name, 1, NULL);
+  if (type == NULL)
+    return builtin_type_int;
+  else
+    return type;
+}
+
+/* Assuming that TYPE is the type of a variant wrapper, and FIELD_NUM is a 
+   valid field number within it, returns 1 iff field FIELD_NUM of TYPE
+   represents a 'when others' clause; otherwise 0. */
+
+int
+ada_is_others_clause (type, field_num)
+     struct type *type;
+     int field_num;
+{
+  const char* name = TYPE_FIELD_NAME (type, field_num);
+  return (name != NULL && name[0] == 'O');
+}
+
+/* Assuming that TYPE0 is the type of the variant part of a record,
+   returns the name of the discriminant controlling the variant.  The
+   value is valid until the next call to ada_variant_discrim_name. */
+
+char * 
+ada_variant_discrim_name (type0)
+     struct type *type0;
+{
+  static char* result = NULL;
+  static size_t result_len = 0;
+  struct type* type;
+  const char* name;
+  const char* discrim_end; 
+  const char* discrim_start;
+
+  if (TYPE_CODE (type0) == TYPE_CODE_PTR)
+    type = TYPE_TARGET_TYPE (type0);
+  else
+    type = type0;
+
+  name = ada_type_name (type);
+
+  if (name == NULL || name[0] == '\000')
+    return "";
+
+  for (discrim_end = name + strlen (name) - 6; discrim_end != name;
+       discrim_end -= 1)
+    {
+      if (STREQN (discrim_end, "___XVN", 6))
+       break;
+    }
+  if (discrim_end == name)
+    return "";
+
+  for (discrim_start = discrim_end; discrim_start != name+3;
+       discrim_start -= 1)
+    {
+      if (discrim_start == name+1)
+       return "";
+      if ((discrim_start > name+3 && STREQN (discrim_start-3, "___", 3))
+         || discrim_start[-1] == '.')
+       break;
+    }
+
+  GROW_VECT (result, result_len, discrim_end - discrim_start + 1);
+  strncpy (result, discrim_start, discrim_end - discrim_start);
+  result[discrim_end-discrim_start] = '\0';
+  return result;
+}
+
+/* Scan STR for a subtype-encoded number, beginning at position K. Put the 
+   position of the character just past the number scanned in *NEW_K, 
+   if NEW_K!=NULL. Put the scanned number in *R, if R!=NULL.  Return 1 
+   if there was a valid number at the given position, and 0 otherwise.  A 
+   "subtype-encoded" number consists of the absolute value in decimal, 
+   followed by the letter 'm' to indicate a negative number.  Assumes 0m 
+   does not occur. */
+
+int
+ada_scan_number (str, k, R, new_k)
+     const char str[];
+     int k;
+     LONGEST *R;
+     int *new_k;
+{
+  ULONGEST RU;
+
+  if (! isdigit (str[k]))
+    return 0;
+
+  /* Do it the hard way so as not to make any assumption about 
+     the relationship of unsigned long (%lu scan format code) and
+     LONGEST. */
+  RU = 0;
+  while (isdigit (str[k]))
+    {
+      RU = RU*10 + (str[k] - '0');
+      k += 1;
+    }
+
+  if (str[k] == 'm') 
+    {
+      if (R != NULL)
+       *R = (- (LONGEST) (RU-1)) - 1;
+      k += 1;
+    }
+  else if (R != NULL)
+    *R = (LONGEST) RU;
+
+  /* NOTE on the above: Technically, C does not say what the results of 
+     - (LONGEST) RU or (LONGEST) -RU are for RU == largest positive
+     number representable as a LONGEST (although either would probably work
+     in most implementations).  When RU>0, the locution in the then branch
+     above is always equivalent to the negative of RU. */
+
+  if (new_k != NULL)
+    *new_k = k;
+  return 1;
+}
+
+/* Assuming that TYPE is a variant part wrapper type (a VARIANTS field), 
+   and FIELD_NUM is a valid field number within it, returns 1 iff VAL is 
+   in the range encoded by field FIELD_NUM of TYPE; otherwise 0. */
+
+int 
+ada_in_variant (val, type, field_num)
+     LONGEST val;
+     struct type *type;
+     int field_num;
+{
+  const char* name = TYPE_FIELD_NAME (type, field_num);
+  int p;
+
+  p = 0;
+  while (1)
+    {
+      switch (name[p]) 
+       {
+       case '\0':
+         return 0;
+       case 'S':
+         {
+           LONGEST W;
+           if (! ada_scan_number (name, p + 1, &W, &p))
+             return 0;
+           if (val == W)
+             return 1;
+           break;
+         }
+       case 'R':
+         {
+           LONGEST L, U;
+           if (! ada_scan_number (name, p + 1, &L, &p)
+               || name[p] != 'T'
+               || ! ada_scan_number (name, p + 1, &U, &p))
+             return 0;
+           if (val >= L && val <= U)
+             return 1;
+           break;
+         }
+       case 'O':
+         return 1;
+       default:
+         return 0;
+       }
+    }
+}
+
+/* Given a value ARG1 (offset by OFFSET bytes)
+   of a struct or union type ARG_TYPE,
+   extract and return the value of one of its (non-static) fields.
+   FIELDNO says which field.   Differs from value_primitive_field only
+   in that it can handle packed values of arbitrary type. */
+
+struct value*
+ada_value_primitive_field (arg1, offset, fieldno, arg_type)
+     struct value* arg1;
+     int offset;
+     int fieldno;
+     struct type *arg_type;
+{
+  struct value* v;
+  struct type *type;
+
+  CHECK_TYPEDEF (arg_type);
+  type = TYPE_FIELD_TYPE (arg_type, fieldno);
+
+  /* Handle packed fields */
+
+  if (TYPE_FIELD_BITSIZE (arg_type, fieldno) != 0)
+    {
+      int bit_pos = TYPE_FIELD_BITPOS (arg_type, fieldno);
+      int bit_size = TYPE_FIELD_BITSIZE (arg_type, fieldno);
+      
+      return ada_value_primitive_packed_val (arg1, VALUE_CONTENTS (arg1),
+                                            offset + bit_pos/8, bit_pos % 8,
+                                            bit_size, type);
+    }
+  else
+    return value_primitive_field (arg1, offset, fieldno, arg_type);
+}
+
+
+/* Look for a field NAME in ARG. Adjust the address of ARG by OFFSET bytes,
+   and search in it assuming it has (class) type TYPE.
+   If found, return value, else return NULL.
+
+   Searches recursively through wrapper fields (e.g., '_parent'). */
+
+struct value*
+ada_search_struct_field (name, arg, offset, type)
+     char *name;
+     struct value* arg;
+     int offset;
+     struct type *type;
+{
+  int i;
+  CHECK_TYPEDEF (type);
+
+  for (i = TYPE_NFIELDS (type)-1; i >= 0; i -= 1)
+    {
+      char *t_field_name = TYPE_FIELD_NAME (type, i);
+
+      if (t_field_name == NULL)
+       continue;
+
+      else if (field_name_match (t_field_name, name))
+         return ada_value_primitive_field (arg, offset, i, type);
+
+      else if (ada_is_wrapper_field (type, i))
+       {
+         struct value* v = 
+           ada_search_struct_field (name, arg, 
+                                    offset + TYPE_FIELD_BITPOS (type, i) / 8, 
+                                    TYPE_FIELD_TYPE (type, i));
+         if (v != NULL)
+           return v;
+       }
+
+      else if (ada_is_variant_part (type, i))
+       {
+         int j;
+         struct type *field_type = check_typedef (TYPE_FIELD_TYPE (type, i));
+         int var_offset = offset + TYPE_FIELD_BITPOS (type, i) / 8;
+
+         for (j = TYPE_NFIELDS (field_type) - 1; j >= 0; j -= 1)
+           {
+             struct value* v = 
+               ada_search_struct_field (name, arg, 
+                                        var_offset 
+                                        + TYPE_FIELD_BITPOS (field_type, j)/8,
+                                        TYPE_FIELD_TYPE (field_type, j));
+             if (v != NULL)
+               return v;
+           }
+       }
+    }
+  return NULL;
+}
+  
+/* Given ARG, a value of type (pointer to a)* structure/union,
+   extract the component named NAME from the ultimate target structure/union
+   and return it as a value with its appropriate type.
+
+   The routine searches for NAME among all members of the structure itself 
+   and (recursively) among all members of any wrapper members 
+   (e.g., '_parent').
+
+   ERR is a name (for use in error messages) that identifies the class 
+   of entity that ARG is supposed to be. */
+
+struct value*
+ada_value_struct_elt (arg, name, err)
+     struct value* arg;
+     char *name;
+     char *err;
+{
+  struct type *t;
+  struct value* v;
+
+  arg = ada_coerce_ref (arg);
+  t = check_typedef (VALUE_TYPE (arg));
+
+  /* Follow pointers until we get to a non-pointer.  */
+
+  while (TYPE_CODE (t) == TYPE_CODE_PTR || TYPE_CODE (t) == TYPE_CODE_REF)
+    {
+      arg = ada_value_ind (arg);
+      t = check_typedef (VALUE_TYPE (arg));
+    }
+
+  if (   TYPE_CODE (t) != TYPE_CODE_STRUCT
+      && TYPE_CODE (t) != TYPE_CODE_UNION)
+    error ("Attempt to extract a component of a value that is not a %s.", err);
+
+  v = ada_search_struct_field (name, arg, 0, t);
+  if (v == NULL)
+    error ("There is no member named %s.", name);
+
+  return v;
+}
+
+/* Given a type TYPE, look up the type of the component of type named NAME.
+   If DISPP is non-null, add its byte displacement from the beginning of a 
+   structure (pointed to by a value) of type TYPE to *DISPP (does not 
+   work for packed fields).
+
+   Matches any field whose name has NAME as a prefix, possibly
+   followed by "___". 
+
+   TYPE can be either a struct or union, or a pointer or reference to 
+   a struct or union.  If it is a pointer or reference, its target 
+   type is automatically used.
+
+   Looks recursively into variant clauses and parent types.
+
+   If NOERR is nonzero, return NULL if NAME is not suitably defined. */
+
+struct type *
+ada_lookup_struct_elt_type (type, name, noerr, dispp)
+     struct type *type;
+     char *name;
+     int noerr;
+     int *dispp;
+{
+  int i;
+
+  if (name == NULL)
+    goto BadName;
+
+  while (1)
+    {
+      CHECK_TYPEDEF (type);
+      if (TYPE_CODE (type) != TYPE_CODE_PTR
+         && TYPE_CODE (type) != TYPE_CODE_REF)
+       break;
+      type = TYPE_TARGET_TYPE (type);
+    }
+
+  if (TYPE_CODE (type) != TYPE_CODE_STRUCT &&
+      TYPE_CODE (type) != TYPE_CODE_UNION)
+    {
+      target_terminal_ours ();
+      gdb_flush (gdb_stdout);
+      fprintf_unfiltered (gdb_stderr, "Type ");
+      type_print (type, "", gdb_stderr, -1);
+      error (" is not a structure or union type");
+    }
+
+  type = to_static_fixed_type (type);
+
+  for (i = 0; i < TYPE_NFIELDS (type); i += 1)
+    {
+      char *t_field_name = TYPE_FIELD_NAME (type, i);
+      struct type *t;
+      int disp;
+  
+      if (t_field_name == NULL)
+       continue;
+
+      else if (field_name_match (t_field_name, name))
+       {
+         if (dispp != NULL) 
+           *dispp += TYPE_FIELD_BITPOS (type, i) / 8;
+         return check_typedef (TYPE_FIELD_TYPE (type, i));
+       }
+
+      else if (ada_is_wrapper_field (type, i))
+       {
+         disp = 0;
+         t = ada_lookup_struct_elt_type (TYPE_FIELD_TYPE (type, i), name, 
+                                         1, &disp);
+         if (t != NULL)
+           {
+             if (dispp != NULL)
+               *dispp += disp + TYPE_FIELD_BITPOS (type, i) / 8;
+             return t;
+           }
+       }
+
+      else if (ada_is_variant_part (type, i))
+       {
+         int j;
+         struct type *field_type = check_typedef (TYPE_FIELD_TYPE (type, i));
+
+         for (j = TYPE_NFIELDS (field_type) - 1; j >= 0; j -= 1)
+           {
+             disp = 0;
+             t = ada_lookup_struct_elt_type (TYPE_FIELD_TYPE (field_type, j),
+                                             name, 1, &disp);
+             if (t != NULL)
+               {
+                 if (dispp != NULL) 
+                   *dispp += disp + TYPE_FIELD_BITPOS (type, i) / 8;
+                 return t;
+               }
+           }
+       }
+
+    }
+
+BadName:
+  if (! noerr)
+    {
+      target_terminal_ours ();
+      gdb_flush (gdb_stdout);
+      fprintf_unfiltered (gdb_stderr, "Type ");
+      type_print (type, "", gdb_stderr, -1);
+      fprintf_unfiltered (gdb_stderr, " has no component named ");
+      error ("%s", name == NULL ? "<null>" : name);
+    }
+
+  return NULL;
+}
+
+/* Assuming that VAR_TYPE is the type of a variant part of a record (a union),
+   within a value of type OUTER_TYPE that is stored in GDB at
+   OUTER_VALADDR, determine which variant clause (field number in VAR_TYPE, 
+   numbering from 0) is applicable.  Returns -1 if none are. */
+
+int 
+ada_which_variant_applies (var_type, outer_type, outer_valaddr)
+     struct type *var_type;
+     struct type *outer_type;
+     char* outer_valaddr;
+{
+  int others_clause;
+  int i;
+  int disp;
+  struct type* discrim_type;
+  char* discrim_name = ada_variant_discrim_name (var_type);
+  LONGEST discrim_val;
+
+  disp = 0;
+  discrim_type = 
+    ada_lookup_struct_elt_type (outer_type, discrim_name, 1, &disp);
+  if (discrim_type == NULL)
+    return -1;
+  discrim_val = unpack_long (discrim_type, outer_valaddr + disp);
+
+  others_clause = -1;
+  for (i = 0; i < TYPE_NFIELDS (var_type); i += 1)
+    {
+      if (ada_is_others_clause (var_type, i))
+       others_clause = i;
+      else if (ada_in_variant (discrim_val, var_type, i))
+       return i;
+    }
+
+  return others_clause;
+}
+
+
+\f
+                               /* Dynamic-Sized Records */
+
+/* Strategy: The type ostensibly attached to a value with dynamic size
+   (i.e., a size that is not statically recorded in the debugging
+   data) does not accurately reflect the size or layout of the value.
+   Our strategy is to convert these values to values with accurate,
+   conventional types that are constructed on the fly. */
+
+/* There is a subtle and tricky problem here.  In general, we cannot
+   determine the size of dynamic records without its data.  However,
+   the 'struct value' data structure, which GDB uses to represent
+   quantities in the inferior process (the target), requires the size
+   of the type at the time of its allocation in order to reserve space
+   for GDB's internal copy of the data.  That's why the
+   'to_fixed_xxx_type' routines take (target) addresses as parameters,
+   rather than struct value*s.  
+
+   However, GDB's internal history variables ($1, $2, etc.) are
+   struct value*s containing internal copies of the data that are not, in
+   general, the same as the data at their corresponding addresses in
+   the target.  Fortunately, the types we give to these values are all
+   conventional, fixed-size types (as per the strategy described
+   above), so that we don't usually have to perform the
+   'to_fixed_xxx_type' conversions to look at their values.
+   Unfortunately, there is one exception: if one of the internal
+   history variables is an array whose elements are unconstrained
+   records, then we will need to create distinct fixed types for each
+   element selected.  */
+
+/* The upshot of all of this is that many routines take a (type, host
+   address, target address) triple as arguments to represent a value.
+   The host address, if non-null, is supposed to contain an internal
+   copy of the relevant data; otherwise, the program is to consult the
+   target at the target address. */
+
+/* Assuming that VAL0 represents a pointer value, the result of
+   dereferencing it.  Differs from value_ind in its treatment of
+   dynamic-sized types. */
+
+struct value*
+ada_value_ind (val0)
+     struct value* val0;
+{
+  struct value* val = unwrap_value (value_ind (val0));
+  return ada_to_fixed_value (VALUE_TYPE (val), 0,
+                            VALUE_ADDRESS (val) + VALUE_OFFSET (val),
+                            val);
+}
+
+/* The value resulting from dereferencing any "reference to"
+ * qualifiers on VAL0. */
+static struct value* 
+ada_coerce_ref (val0)
+     struct value* val0;
+{
+  if (TYPE_CODE (VALUE_TYPE (val0)) == TYPE_CODE_REF) {
+    struct value* val = val0;
+    COERCE_REF (val);
+    val = unwrap_value (val);
+    return ada_to_fixed_value (VALUE_TYPE (val), 0, 
+                              VALUE_ADDRESS (val) + VALUE_OFFSET (val),
+                              val);
+  } else
+    return val0;
+}
+
+/* Return OFF rounded upward if necessary to a multiple of
+   ALIGNMENT (a power of 2). */
+
+static unsigned int
+align_value (off, alignment)
+     unsigned int off;
+     unsigned int alignment;
+{
+  return (off + alignment - 1) & ~(alignment - 1);
+}
+
+/* Return the additional bit offset required by field F of template
+   type TYPE. */
+
+static unsigned int
+field_offset (type, f)
+     struct type *type;
+     int f;
+{
+  int n = TYPE_FIELD_BITPOS (type, f);
+  /* Kludge (temporary?) to fix problem with dwarf output. */
+  if (n < 0)
+    return (unsigned int) n & 0xffff;
+  else
+    return n;
+}
+
+
+/* Return the bit alignment required for field #F of template type TYPE. */
+
+static unsigned int
+field_alignment (type, f)
+     struct type *type;
+     int f;
+{
+  const char* name = TYPE_FIELD_NAME (type, f);
+  int len = (name == NULL) ? 0 : strlen (name);
+  int align_offset;
+
+  if (len < 8 || ! isdigit (name[len-1]))
+    return TARGET_CHAR_BIT;
+
+  if (isdigit (name[len-2]))
+    align_offset = len - 2;
+  else
+    align_offset = len - 1;
+
+  if (align_offset < 7 || ! STREQN ("___XV", name+align_offset-6, 5))
+    return TARGET_CHAR_BIT;
+
+  return atoi (name+align_offset) * TARGET_CHAR_BIT;
+}
+
+/* Find a type named NAME.  Ignores ambiguity.  */
+struct type*
+ada_find_any_type (name)
+     const char *name;
+{
+  struct symbol* sym;
+
+  sym = standard_lookup (name, VAR_NAMESPACE);
+  if (sym != NULL && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+    return SYMBOL_TYPE (sym);
+
+  sym = standard_lookup (name, STRUCT_NAMESPACE);
+  if (sym != NULL)
+    return SYMBOL_TYPE (sym);
+
+  return NULL;
+}
+
+/* Because of GNAT encoding conventions, several GDB symbols may match a
+   given type name. If the type denoted by TYPE0 is to be preferred to
+   that of TYPE1 for purposes of type printing, return non-zero;
+   otherwise return 0. */
+int
+ada_prefer_type (type0, type1)
+     struct type* type0;
+     struct type* type1;
+{
+  if (type1 == NULL)
+    return 1;
+  else if (type0 == NULL)
+    return 0;
+  else if (TYPE_CODE (type1) == TYPE_CODE_VOID)
+    return 1;
+  else if (TYPE_CODE (type0) == TYPE_CODE_VOID)
+    return 0;
+  else if (ada_is_packed_array_type (type0))
+    return 1;
+  else if (ada_is_array_descriptor (type0) && ! ada_is_array_descriptor (type1))
+    return 1;
+  else if (ada_renaming_type (type0) != NULL 
+          && ada_renaming_type (type1) == NULL)
+    return 1;
+  return 0;
+}
+
+/* The name of TYPE, which is either its TYPE_NAME, or, if that is
+   null, its TYPE_TAG_NAME.  Null if TYPE is null. */
+char*
+ada_type_name (type)
+     struct type* type;
+{
+  if (type == NULL) 
+    return NULL;
+  else if (TYPE_NAME (type) != NULL)
+    return TYPE_NAME (type);
+  else
+    return TYPE_TAG_NAME (type);
+}
+
+/* Find a parallel type to TYPE whose name is formed by appending
+   SUFFIX to the name of TYPE. */
+
+struct type*
+ada_find_parallel_type (type, suffix)
+     struct type *type;
+     const char *suffix;
+{
+  static char* name;
+  static size_t name_len = 0;
+  struct symbol** syms;
+  struct block** blocks;
+  int nsyms;
+  int len;
+  char* typename = ada_type_name (type);
+  
+  if (typename == NULL)
+    return NULL;
+
+  len = strlen (typename);
+
+  GROW_VECT (name, name_len, len+strlen (suffix)+1);
+
+  strcpy (name, typename);
+  strcpy (name + len, suffix);
+
+  return ada_find_any_type (name);
+}
+
+
+/* If TYPE is a variable-size record type, return the corresponding template
+   type describing its fields.  Otherwise, return NULL. */
+
+static struct type*
+dynamic_template_type (type)
+     struct type* type;
+{
+  CHECK_TYPEDEF (type);
+
+  if (type == NULL || TYPE_CODE (type) != TYPE_CODE_STRUCT
+      || ada_type_name (type) == NULL) 
+    return NULL;
+  else 
+    {
+      int len = strlen (ada_type_name (type));
+      if (len > 6 && STREQ (ada_type_name (type) + len - 6, "___XVE"))
+       return type;
+      else
+       return ada_find_parallel_type (type, "___XVE");
+    }
+}
+
+/* Assuming that TEMPL_TYPE is a union or struct type, returns
+   non-zero iff field FIELD_NUM of TEMPL_TYPE has dynamic size. */
+
+static int 
+is_dynamic_field (templ_type, field_num)
+     struct type* templ_type;
+     int field_num;
+{
+  const char *name = TYPE_FIELD_NAME (templ_type, field_num);
+  return name != NULL 
+    && TYPE_CODE (TYPE_FIELD_TYPE (templ_type, field_num)) == TYPE_CODE_PTR
+    && strstr (name, "___XVL") != NULL;
+}
+
+/* Assuming that TYPE is a struct type, returns non-zero iff TYPE
+   contains a variant part. */
+
+static int 
+contains_variant_part (type)
+     struct type* type;
+{
+  int f;
+
+  if (type == NULL || TYPE_CODE (type) != TYPE_CODE_STRUCT
+      || TYPE_NFIELDS (type) <= 0)
+    return 0;
+  return ada_is_variant_part (type, TYPE_NFIELDS (type) - 1);
+}
+
+/* A record type with no fields, . */
+static struct type*
+empty_record (objfile) 
+     struct objfile* objfile;
+{
+  struct type* type = alloc_type (objfile);
+  TYPE_CODE (type) = TYPE_CODE_STRUCT;
+  TYPE_NFIELDS (type) = 0;
+  TYPE_FIELDS (type) = NULL;
+  TYPE_NAME (type) = "<empty>";
+  TYPE_TAG_NAME (type) = NULL;
+  TYPE_FLAGS (type) = 0;
+  TYPE_LENGTH (type) = 0;
+  return type;
+}
+
+/* An ordinary record type (with fixed-length fields) that describes
+   the value of type TYPE at VALADDR or ADDRESS (see comments at 
+   the beginning of this section) VAL according to GNAT conventions.  
+   DVAL0 should describe the (portion of a) record that contains any 
+   necessary discriminants.  It should be NULL if VALUE_TYPE (VAL) is
+   an outer-level type (i.e., as opposed to a branch of a variant.)  A
+   variant field (unless unchecked) is replaced by a particular branch
+   of the variant. */
+/* NOTE: Limitations: For now, we assume that dynamic fields and
+ * variants occupy whole numbers of bytes.  However, they need not be
+ * byte-aligned.  */
+
+static struct type*
+template_to_fixed_record_type (type, valaddr, address, dval0)
+     struct type* type;
+     char* valaddr;
+     CORE_ADDR address;
+     struct value* dval0;
+
+{
+  struct value* mark = value_mark();
+  struct value* dval;
+  struct type* rtype;
+  int nfields, bit_len;
+  long off;
+  int f;
+
+  nfields = TYPE_NFIELDS (type);
+  rtype = alloc_type (TYPE_OBJFILE (type));
+  TYPE_CODE (rtype) = TYPE_CODE_STRUCT;
+  INIT_CPLUS_SPECIFIC (rtype);
+  TYPE_NFIELDS (rtype) = nfields;
+  TYPE_FIELDS (rtype) = (struct field*) 
+    TYPE_ALLOC (rtype, nfields * sizeof (struct field));
+  memset (TYPE_FIELDS (rtype), 0, sizeof (struct field) * nfields);
+  TYPE_NAME (rtype) = ada_type_name (type);
+  TYPE_TAG_NAME (rtype) = NULL;
+  /* FIXME: TYPE_FLAG_FIXED_INSTANCE should be defined in
+     gdbtypes.h */  
+  /*  TYPE_FLAGS (rtype) |= TYPE_FLAG_FIXED_INSTANCE;*/
+
+  off = 0; bit_len = 0;
+  for (f = 0; f < nfields; f += 1)
+    {
+      int fld_bit_len, bit_incr;
+      off = 
+       align_value (off, field_alignment (type, f))+TYPE_FIELD_BITPOS (type,f);
+      /* NOTE: used to use field_offset above, but that causes
+       * problems with really negative bit positions.  So, let's
+       * rediscover why we needed field_offset and fix it properly. */
+      TYPE_FIELD_BITPOS (rtype, f) = off;
+      TYPE_FIELD_BITSIZE (rtype, f) = 0;  
+
+      if (ada_is_variant_part (type, f)) 
+       {
+         struct type *branch_type;
+
+         if (dval0 == NULL)
+           dval = 
+             value_from_contents_and_address (rtype, valaddr, address);
+         else
+           dval = dval0;
+
+         branch_type = 
+           to_fixed_variant_branch_type 
+             (TYPE_FIELD_TYPE (type, f),
+              cond_offset_host (valaddr, off / TARGET_CHAR_BIT),
+              cond_offset_target (address, off / TARGET_CHAR_BIT),
+              dval);
+         if (branch_type == NULL) 
+           TYPE_NFIELDS (rtype) -= 1;
+         else
+           {
+             TYPE_FIELD_TYPE (rtype, f) = branch_type;
+             TYPE_FIELD_NAME (rtype, f) = "S";
+           }
+         bit_incr = 0;
+         fld_bit_len =
+           TYPE_LENGTH (TYPE_FIELD_TYPE (rtype, f)) * TARGET_CHAR_BIT;
+       }
+      else if (is_dynamic_field (type, f))
+       {
+         if (dval0 == NULL)
+           dval = 
+             value_from_contents_and_address (rtype, valaddr, address);
+         else
+           dval = dval0;
+
+         TYPE_FIELD_TYPE (rtype, f) = 
+           ada_to_fixed_type 
+             (ada_get_base_type 
+              (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, f))),
+              cond_offset_host (valaddr, off / TARGET_CHAR_BIT),
+              cond_offset_target (address, off / TARGET_CHAR_BIT),
+              dval);
+         TYPE_FIELD_NAME (rtype, f) = TYPE_FIELD_NAME (type, f);
+         bit_incr = fld_bit_len =
+           TYPE_LENGTH (TYPE_FIELD_TYPE (rtype, f)) * TARGET_CHAR_BIT;
+       }
+      else
+       {
+         TYPE_FIELD_TYPE (rtype, f) = TYPE_FIELD_TYPE (type, f);
+         TYPE_FIELD_NAME (rtype, f) = TYPE_FIELD_NAME (type, f);
+         if (TYPE_FIELD_BITSIZE (type, f) > 0)
+           bit_incr = fld_bit_len = 
+             TYPE_FIELD_BITSIZE (rtype, f) = TYPE_FIELD_BITSIZE (type, f);
+         else
+           bit_incr = fld_bit_len =
+             TYPE_LENGTH (TYPE_FIELD_TYPE (type, f)) * TARGET_CHAR_BIT;
+       }
+      if (off + fld_bit_len > bit_len)
+       bit_len = off + fld_bit_len;
+      off += bit_incr;
+      TYPE_LENGTH (rtype) = bit_len / TARGET_CHAR_BIT;
+    }
+  TYPE_LENGTH (rtype) = align_value (TYPE_LENGTH (rtype), TYPE_LENGTH (type));
+
+  value_free_to_mark (mark);
+  if (TYPE_LENGTH (rtype) > varsize_limit) 
+    error ("record type with dynamic size is larger than varsize-limit");
+  return rtype;
+}
+
+/* As for template_to_fixed_record_type, but uses no run-time values.
+   As a result, this type can only be approximate, but that's OK,
+   since it is used only for type determinations.   Works on both
+   structs and unions.
+   Representation note: to save space, we memoize the result of this
+   function in the TYPE_TARGET_TYPE of the template type. */
+
+static struct type*
+template_to_static_fixed_type (templ_type)
+     struct type* templ_type;
+{
+  struct type *type;
+  int nfields;
+  int f;
+
+  if (TYPE_TARGET_TYPE (templ_type) != NULL)
+    return TYPE_TARGET_TYPE (templ_type);
+
+  nfields = TYPE_NFIELDS (templ_type);
+  TYPE_TARGET_TYPE (templ_type) = type = alloc_type (TYPE_OBJFILE (templ_type));
+  TYPE_CODE (type) = TYPE_CODE (templ_type);
+  INIT_CPLUS_SPECIFIC (type);
+  TYPE_NFIELDS (type) = nfields;
+  TYPE_FIELDS (type) = (struct field*) 
+    TYPE_ALLOC (type, nfields * sizeof (struct field));
+  memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields);
+  TYPE_NAME (type) = ada_type_name (templ_type);
+  TYPE_TAG_NAME (type) = NULL;
+  /* FIXME:  TYPE_FLAG_FIXED_INSTANCE should be defined in gdbtypes.h */  
+  /*  TYPE_FLAGS (type) |= TYPE_FLAG_FIXED_INSTANCE; */
+  TYPE_LENGTH (type) = 0;
+
+  for (f = 0; f < nfields; f += 1)
+    {
+      TYPE_FIELD_BITPOS (type, f) = 0;
+      TYPE_FIELD_BITSIZE (type, f) = 0;  
+
+      if (is_dynamic_field (templ_type, f))
+       {
+         TYPE_FIELD_TYPE (type, f) = 
+           to_static_fixed_type (TYPE_TARGET_TYPE 
+                                 (TYPE_FIELD_TYPE (templ_type, f)));
+         TYPE_FIELD_NAME (type, f) = TYPE_FIELD_NAME (templ_type, f);
+       }
+      else
+       {
+         TYPE_FIELD_TYPE (type, f) = 
+           check_typedef (TYPE_FIELD_TYPE (templ_type, f));
+         TYPE_FIELD_NAME (type, f) = TYPE_FIELD_NAME (templ_type, f);
+       }
+    }
+
+  return type;
+}
+
+/* A revision of TYPE0 -- a non-dynamic-sized record with a variant
+   part -- in which the variant part is replaced with the appropriate
+   branch. */
+static struct type*
+to_record_with_fixed_variant_part (type, valaddr, address, dval)
+     struct type* type;
+     char* valaddr;
+     CORE_ADDR address;
+     struct value* dval;
+{
+  struct value* mark = value_mark();
+  struct type* rtype;
+  struct type *branch_type;
+  int nfields = TYPE_NFIELDS (type);
+
+  if (dval == NULL)
+    return type;
+
+  rtype = alloc_type (TYPE_OBJFILE (type));
+  TYPE_CODE (rtype) = TYPE_CODE_STRUCT;
+  INIT_CPLUS_SPECIFIC (type);
+  TYPE_NFIELDS (rtype) = TYPE_NFIELDS (type);
+  TYPE_FIELDS (rtype) = 
+    (struct field*) TYPE_ALLOC (rtype, nfields * sizeof (struct field));
+  memcpy (TYPE_FIELDS (rtype), TYPE_FIELDS (type), 
+         sizeof (struct field) * nfields);
+  TYPE_NAME (rtype) = ada_type_name (type);
+  TYPE_TAG_NAME (rtype) = NULL;
+  /* FIXME:  TYPE_FLAG_FIXED_INSTANCE should be defined in gdbtypes.h */  
+  /*  TYPE_FLAGS (rtype) |= TYPE_FLAG_FIXED_INSTANCE; */
+  TYPE_LENGTH (rtype) = TYPE_LENGTH (type);
+
+  branch_type = 
+    to_fixed_variant_branch_type 
+      (TYPE_FIELD_TYPE (type, nfields - 1),
+       cond_offset_host (valaddr, 
+                        TYPE_FIELD_BITPOS (type, nfields-1) / TARGET_CHAR_BIT),
+       cond_offset_target (address, 
+                        TYPE_FIELD_BITPOS (type, nfields-1) / TARGET_CHAR_BIT),
+       dval);
+  if (branch_type == NULL) 
+    {
+      TYPE_NFIELDS (rtype) -= 1;
+      TYPE_LENGTH (rtype) -= TYPE_LENGTH (TYPE_FIELD_TYPE (type, nfields - 1));
+    }
+  else
+    {
+      TYPE_FIELD_TYPE (rtype, nfields-1) = branch_type;
+      TYPE_FIELD_NAME (rtype, nfields-1) = "S";
+      TYPE_FIELD_BITSIZE (rtype, nfields-1) = 0;
+      TYPE_LENGTH (rtype) += TYPE_LENGTH (branch_type);
+       - TYPE_LENGTH (TYPE_FIELD_TYPE (type, nfields - 1));
+    }
+  
+  return rtype;
+}
+
+/* An ordinary record type (with fixed-length fields) that describes
+   the value at (TYPE0, VALADDR, ADDRESS) [see explanation at
+   beginning of this section].   Any necessary discriminants' values
+   should be in DVAL, a record value; it should be NULL if the object
+   at ADDR itself contains any necessary  discriminant values.  A
+   variant field (unless unchecked) is replaced by a particular branch
+   of the variant. */ 
+
+static struct type*
+to_fixed_record_type (type0, valaddr, address, dval)
+     struct type* type0;
+     char* valaddr;
+     CORE_ADDR address;
+     struct value* dval;
+{
+  struct type* templ_type;
+
+  /* FIXME:  TYPE_FLAG_FIXED_INSTANCE should be defined in gdbtypes.h */
+  /*  if (TYPE_FLAGS (type0) & TYPE_FLAG_FIXED_INSTANCE)
+    return type0;
+  */
+  templ_type = dynamic_template_type (type0);  
+
+  if (templ_type != NULL)
+    return template_to_fixed_record_type (templ_type, valaddr, address, dval);
+  else if (contains_variant_part (type0))
+    return to_record_with_fixed_variant_part (type0, valaddr, address, dval);
+  else
+    {
+      /* FIXME:  TYPE_FLAG_FIXED_INSTANCE should be defined in gdbtypes.h */      
+      /*      TYPE_FLAGS (type0) |= TYPE_FLAG_FIXED_INSTANCE; */
+      return type0;
+    }
+
+}
+
+/* An ordinary record type (with fixed-length fields) that describes
+   the value at (VAR_TYPE0, VALADDR, ADDRESS), where VAR_TYPE0 is a
+   union type.  Any necessary discriminants' values should be in DVAL,
+   a record value.  That is, this routine selects the appropriate
+   branch of the union at ADDR according to the discriminant value
+   indicated in the union's type name. */
+
+static struct type*
+to_fixed_variant_branch_type (var_type0, valaddr, address, dval)
+     struct type* var_type0;
+     char* valaddr;
+     CORE_ADDR address;
+     struct value* dval;
+{
+  int which;
+  struct type* templ_type;
+  struct type* var_type;
+
+  if (TYPE_CODE (var_type0) == TYPE_CODE_PTR)
+    var_type = TYPE_TARGET_TYPE (var_type0);
+  else 
+    var_type = var_type0;
+
+  templ_type = ada_find_parallel_type (var_type, "___XVU");
+
+  if (templ_type != NULL)
+    var_type = templ_type;
+
+  which = 
+    ada_which_variant_applies (var_type, 
+                              VALUE_TYPE (dval), VALUE_CONTENTS (dval));
+
+  if (which < 0)
+    return empty_record (TYPE_OBJFILE (var_type));
+  else if (is_dynamic_field (var_type, which))
+    return 
+      to_fixed_record_type 
+         (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (var_type, which)),
+         valaddr, address, dval);
+  else if (contains_variant_part (TYPE_FIELD_TYPE (var_type, which)))
+    return 
+      to_fixed_record_type 
+         (TYPE_FIELD_TYPE (var_type, which), valaddr, address, dval);
+  else
+    return TYPE_FIELD_TYPE (var_type, which);
+}
+
+/* Assuming that TYPE0 is an array type describing the type of a value
+   at ADDR, and that DVAL describes a record containing any
+   discriminants used in TYPE0, returns a type for the value that
+   contains no dynamic components (that is, no components whose sizes
+   are determined by run-time quantities).  Unless IGNORE_TOO_BIG is
+   true, gives an error message if the resulting type's size is over
+   varsize_limit.
+*/
+
+static struct type*
+to_fixed_array_type (type0, dval, ignore_too_big)
+     struct type* type0;
+     struct value* dval;
+     int ignore_too_big;
+{
+  struct type* index_type_desc;
+  struct type* result;
+
+  /* FIXME:  TYPE_FLAG_FIXED_INSTANCE should be defined in gdbtypes.h */
+  /*  if (ada_is_packed_array_type (type0)  /* revisit? */ /*
+      || (TYPE_FLAGS (type0) & TYPE_FLAG_FIXED_INSTANCE))
+    return type0;*/
+
+  index_type_desc = ada_find_parallel_type (type0, "___XA");
+  if (index_type_desc == NULL)
+    {
+      struct type *elt_type0 = check_typedef (TYPE_TARGET_TYPE (type0));
+      /* NOTE: elt_type---the fixed version of elt_type0---should never
+       * depend on the contents of the array in properly constructed
+       * debugging data. */       
+      struct type *elt_type = 
+       ada_to_fixed_type (elt_type0, 0, 0, dval);
+
+      if (elt_type0 == elt_type)
+       result = type0;
+      else
+       result = create_array_type (alloc_type (TYPE_OBJFILE (type0)), 
+                                   elt_type, TYPE_INDEX_TYPE (type0));
+    }
+  else
+    {
+      int i;
+      struct type *elt_type0;
+
+      elt_type0 = type0;
+      for (i = TYPE_NFIELDS (index_type_desc); i > 0; i -= 1)
+       elt_type0 = TYPE_TARGET_TYPE (elt_type0);
+
+      /* NOTE: result---the fixed version of elt_type0---should never
+       * depend on the contents of the array in properly constructed
+       * debugging data. */       
+      result = 
+       ada_to_fixed_type (check_typedef (elt_type0), 0, 0, dval);
+      for (i = TYPE_NFIELDS (index_type_desc) - 1; i >= 0; i -= 1)
+       {
+         struct type *range_type = 
+           to_fixed_range_type (TYPE_FIELD_NAME (index_type_desc, i),
+                                dval, TYPE_OBJFILE (type0));
+         result = create_array_type (alloc_type (TYPE_OBJFILE (type0)),
+                                     result, range_type);
+       }
+      if (! ignore_too_big && TYPE_LENGTH (result) > varsize_limit) 
+       error ("array type with dynamic size is larger than varsize-limit");
+    }
+
+/* FIXME:  TYPE_FLAG_FIXED_INSTANCE should be defined in gdbtypes.h */
+/*  TYPE_FLAGS (result) |= TYPE_FLAG_FIXED_INSTANCE; */
+  return result;
+}  
+
+
+/* A standard type (containing no dynamically sized components)
+   corresponding to TYPE for the value (TYPE, VALADDR, ADDRESS)
+   DVAL describes a record containing any discriminants used in TYPE0,
+   and may be NULL if there are none. */
+
+struct type*
+ada_to_fixed_type (type, valaddr, address, dval)
+     struct type* type;
+     char* valaddr;
+     CORE_ADDR address;
+     struct value* dval;
+{
+  CHECK_TYPEDEF (type);
+  switch (TYPE_CODE (type)) {
+  default:
+    return type;
+  case TYPE_CODE_STRUCT:
+    return to_fixed_record_type (type, valaddr, address, NULL);
+  case TYPE_CODE_ARRAY:
+    return to_fixed_array_type (type, dval, 0);
+  case TYPE_CODE_UNION:
+    if (dval == NULL) 
+      return type;
+    else
+      return to_fixed_variant_branch_type (type, valaddr, address, dval);
+  }
+}
+
+/* A standard (static-sized) type corresponding as well as possible to
+   TYPE0, but based on no runtime data. */
+
+static struct type*
+to_static_fixed_type (type0)
+     struct type* type0;
+{
+  struct type* type;
+
+  if (type0 == NULL)
+    return NULL;
+
+  /* FIXME:  TYPE_FLAG_FIXED_INSTANCE should be defined in gdbtypes.h */
+  /*  if (TYPE_FLAGS (type0) & TYPE_FLAG_FIXED_INSTANCE)
+    return type0;
+  */
+  CHECK_TYPEDEF (type0);
+  
+  switch (TYPE_CODE (type0))
+    {
+    default:
+      return type0;
+    case TYPE_CODE_STRUCT:
+      type = dynamic_template_type (type0);
+      if (type != NULL) 
+       return template_to_static_fixed_type (type);
+      return type0;
+    case TYPE_CODE_UNION:
+      type = ada_find_parallel_type (type0, "___XVU");
+      if (type != NULL)
+       return template_to_static_fixed_type (type);
+      return type0;
+    }
+}
+
+/* A static approximation of TYPE with all type wrappers removed. */
+static struct type*
+static_unwrap_type (type)
+     struct type* type;
+{
+  if (ada_is_aligner_type (type))
+    {
+      struct type* type1 = TYPE_FIELD_TYPE (check_typedef (type), 0);
+      if (ada_type_name (type1) == NULL)
+       TYPE_NAME (type1) = ada_type_name (type);
+
+      return static_unwrap_type (type1);
+    }
+  else 
+    {
+      struct type* raw_real_type = ada_get_base_type (type);
+      if (raw_real_type == type) 
+       return type;
+      else
+       return to_static_fixed_type (raw_real_type);
+    }
+}
+
+/* In some cases, incomplete and private types require
+   cross-references that are not resolved as records (for example, 
+      type Foo;
+      type FooP is access Foo;
+      V: FooP;
+      type Foo is array ...;
+   ). In these cases, since there is no mechanism for producing 
+   cross-references to such types, we instead substitute for FooP a
+   stub enumeration type that is nowhere resolved, and whose tag is
+   the name of the actual type.  Call these types "non-record stubs". */
+
+/* A type equivalent to TYPE that is not a non-record stub, if one
+   exists, otherwise TYPE. */
+struct type*
+ada_completed_type (type)
+     struct type* type;
+{
+  CHECK_TYPEDEF (type);
+  if (type == NULL || TYPE_CODE (type) != TYPE_CODE_ENUM
+      || (TYPE_FLAGS (type) & TYPE_FLAG_STUB) == 0
+      || TYPE_TAG_NAME (type) == NULL)
+    return type;
+  else 
+    {
+      char* name = TYPE_TAG_NAME (type);
+      struct type* type1 = ada_find_any_type (name);
+      return (type1 == NULL) ? type : type1;
+    }
+}
+
+/* A value representing the data at VALADDR/ADDRESS as described by
+   type TYPE0, but with a standard (static-sized) type that correctly
+   describes it.  If VAL0 is not NULL and TYPE0 already is a standard
+   type, then return VAL0 [this feature is simply to avoid redundant
+   creation of struct values]. */ 
+
+struct value*
+ada_to_fixed_value (type0, valaddr, address, val0)
+     struct type* type0;
+     char* valaddr;
+     CORE_ADDR address;
+     struct value* val0;
+{
+  struct type* type = ada_to_fixed_type (type0, valaddr, address, NULL);
+  if (type == type0 && val0 != NULL)
+    return val0;
+  else return value_from_contents_and_address (type, valaddr, address);
+}
+
+/* A value representing VAL, but with a standard (static-sized) type 
+   chosen to approximate the real type of VAL as well as possible, but
+   without consulting any runtime values.  For Ada dynamic-sized
+   types, therefore, the type of the result is likely to be inaccurate. */
+
+struct value*
+ada_to_static_fixed_value (val)
+     struct value* val;
+{
+  struct type *type = 
+    to_static_fixed_type (static_unwrap_type (VALUE_TYPE (val)));
+  if (type == VALUE_TYPE (val))
+    return val;
+  else
+    return coerce_unspec_val_to_type (val, 0, type);
+}
+
+
+\f
+
+
+/* Attributes */
+
+/* Table mapping attribute numbers to names */
+/* NOTE: Keep up to date with enum ada_attribute definition in ada-lang.h */
+
+static const char* attribute_names[] = {
+  "<?>",
+
+  "first", 
+  "last",
+  "length",
+  "image",
+  "img",
+  "max",
+  "min",
+  "pos"
+  "tag",
+  "val",
+
+  0
+};
+
+const char*
+ada_attribute_name (n)
+     int n;
+{
+  if (n > 0 && n < (int) ATR_END)
+    return attribute_names[n];
+  else
+    return attribute_names[0];
+}
+
+/* Evaluate the 'POS attribute applied to ARG. */
+
+static struct value*
+value_pos_atr (arg)
+     struct value* arg;
+{
+  struct type *type = VALUE_TYPE (arg);
+
+  if (! discrete_type_p (type))
+    error ("'POS only defined on discrete types");
+
+  if (TYPE_CODE (type) == TYPE_CODE_ENUM)
+    {
+      int i;
+      LONGEST v = value_as_long (arg);
+
+      for (i = 0; i < TYPE_NFIELDS (type); i += 1) 
+       {
+         if (v == TYPE_FIELD_BITPOS (type, i))
+           return value_from_longest (builtin_type_ada_int, i);
+       }
+      error ("enumeration value is invalid: can't find 'POS");
+    }
+  else
+    return value_from_longest (builtin_type_ada_int, value_as_long (arg));
+}
+
+/* Evaluate the TYPE'VAL attribute applied to ARG. */
+
+static struct value*
+value_val_atr (type, arg)
+     struct type *type;
+     struct value* arg;
+{
+  if (! discrete_type_p (type))
+    error ("'VAL only defined on discrete types");
+  if (! integer_type_p (VALUE_TYPE (arg)))
+    error ("'VAL requires integral argument");
+
+  if (TYPE_CODE (type) == TYPE_CODE_ENUM)
+    {
+      long pos = value_as_long (arg);
+      if (pos < 0 || pos >= TYPE_NFIELDS (type))
+       error ("argument to 'VAL out of range");
+      return 
+       value_from_longest (type, TYPE_FIELD_BITPOS (type, pos));
+    }
+  else
+    return value_from_longest (type, value_as_long (arg));
+}
+
+\f
+                               /* Evaluation */
+
+/* True if TYPE appears to be an Ada character type.  
+ * [At the moment, this is true only for Character and Wide_Character;
+ * It is a heuristic test that could stand improvement]. */
+
+int 
+ada_is_character_type (type)
+     struct type* type;
+{
+  const char* name = ada_type_name (type);
+  return 
+    name != NULL
+    && (TYPE_CODE (type) == TYPE_CODE_CHAR 
+       || TYPE_CODE (type) == TYPE_CODE_INT
+       || TYPE_CODE (type) == TYPE_CODE_RANGE)
+    && (STREQ (name, "character") || STREQ (name, "wide_character")
+       || STREQ (name, "unsigned char"));
+}
+
+/* True if TYPE appears to be an Ada string type. */
+
+int
+ada_is_string_type (type)
+     struct type *type;
+{
+  CHECK_TYPEDEF (type);
+  if (type != NULL 
+      && TYPE_CODE (type) != TYPE_CODE_PTR
+      && (ada_is_simple_array (type) || ada_is_array_descriptor (type))
+      && ada_array_arity (type) == 1)
+    {
+      struct type *elttype = ada_array_element_type (type, 1);
+
+      return ada_is_character_type (elttype);
+    }
+  else 
+    return 0;
+}
+
+
+/* True if TYPE is a struct type introduced by the compiler to force the
+   alignment of a value.  Such types have a single field with a
+   distinctive name. */
+
+int
+ada_is_aligner_type (type)
+     struct type *type;
+{
+  CHECK_TYPEDEF (type);
+  return (TYPE_CODE (type) == TYPE_CODE_STRUCT
+         && TYPE_NFIELDS (type) == 1
+         && STREQ (TYPE_FIELD_NAME (type, 0), "F"));
+}
+
+/* If there is an ___XVS-convention type parallel to SUBTYPE, return
+   the parallel type. */
+
+struct type*
+ada_get_base_type (raw_type)
+     struct type* raw_type;
+{
+  struct type* real_type_namer;
+  struct type* raw_real_type;
+  struct type* real_type;
+
+  if (raw_type == NULL || TYPE_CODE (raw_type) != TYPE_CODE_STRUCT)
+    return raw_type;
+
+  real_type_namer = ada_find_parallel_type (raw_type, "___XVS");
+  if (real_type_namer == NULL 
+      || TYPE_CODE (real_type_namer) != TYPE_CODE_STRUCT
+      || TYPE_NFIELDS (real_type_namer) != 1)
+    return raw_type;
+
+  raw_real_type = ada_find_any_type (TYPE_FIELD_NAME (real_type_namer, 0));
+  if (raw_real_type == NULL) 
+    return raw_type;
+  else
+    return raw_real_type;
+}  
+
+/* The type of value designated by TYPE, with all aligners removed. */
+
+struct type*
+ada_aligned_type (type)
+     struct type* type;
+{
+  if (ada_is_aligner_type (type))
+    return ada_aligned_type (TYPE_FIELD_TYPE (type, 0));
+  else
+    return ada_get_base_type (type);
+}
+
+
+/* The address of the aligned value in an object at address VALADDR
+   having type TYPE.  Assumes ada_is_aligner_type (TYPE). */
+
+char*
+ada_aligned_value_addr (type, valaddr)
+     struct type *type;
+     char *valaddr;
+{
+  if (ada_is_aligner_type (type)) 
+    return ada_aligned_value_addr (TYPE_FIELD_TYPE (type, 0),
+                                  valaddr + 
+                                  TYPE_FIELD_BITPOS (type, 0)/TARGET_CHAR_BIT);
+  else
+    return valaddr;
+}
+
+/* The printed representation of an enumeration literal with encoded
+   name NAME. The value is good to the next call of ada_enum_name. */
+const char*
+ada_enum_name (name)
+     const char* name;
+{
+  char* tmp;
+
+  while (1) 
+    {
+      if ((tmp = strstr (name, "__")) != NULL)
+       name = tmp+2;
+      else if ((tmp = strchr (name, '.')) != NULL)
+       name = tmp+1;
+      else
+       break;
+    }
+
+  if (name[0] == 'Q')
+    {
+      static char result[16];
+      int v;
+      if (name[1] == 'U' || name[1] == 'W')
+       {
+         if (sscanf (name+2, "%x", &v) != 1) 
+           return name;
+       }
+      else
+       return name;
+
+      if (isascii (v) && isprint (v))
+       sprintf (result, "'%c'", v);
+      else if (name[1] == 'U')
+       sprintf (result, "[\"%02x\"]", v);
+      else
+       sprintf (result, "[\"%04x\"]", v);
+
+      return result;
+    }
+  else 
+    return name;
+}
+
+static struct value*
+evaluate_subexp (expect_type, exp, pos, noside)
+     struct type *expect_type;
+     struct expression *exp;
+     int *pos;
+     enum noside noside;
+{
+  return (*exp->language_defn->evaluate_exp) (expect_type, exp, pos, noside);
+}
+
+/* Evaluate the subexpression of EXP starting at *POS as for
+   evaluate_type, updating *POS to point just past the evaluated
+   expression. */
+
+static struct value*
+evaluate_subexp_type (exp, pos)
+     struct expression* exp;
+     int* pos;
+{
+  return (*exp->language_defn->evaluate_exp) 
+    (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+}
+
+/* If VAL is wrapped in an aligner or subtype wrapper, return the
+   value it wraps. */ 
+
+static struct value*
+unwrap_value (val)
+     struct value* val;
+{
+  struct type* type = check_typedef (VALUE_TYPE (val));
+  if (ada_is_aligner_type (type))
+    {
+      struct value* v = value_struct_elt (&val, NULL, "F", 
+                                     NULL, "internal structure");
+      struct type* val_type = check_typedef (VALUE_TYPE (v));
+      if (ada_type_name (val_type) == NULL)
+       TYPE_NAME (val_type) = ada_type_name (type);
+
+      return unwrap_value (v);
+    }
+  else 
+    {
+      struct type* raw_real_type = 
+       ada_completed_type (ada_get_base_type (type));
+      
+      if (type == raw_real_type)
+       return val;
+
+      return 
+       coerce_unspec_val_to_type 
+       (val, 0, ada_to_fixed_type (raw_real_type, 0,
+                                   VALUE_ADDRESS (val) + VALUE_OFFSET (val),
+                                   NULL));
+    }
+}
+    
+static struct value*
+cast_to_fixed (type, arg)
+     struct type *type;
+     struct value* arg;
+{
+  LONGEST val;
+
+  if (type == VALUE_TYPE (arg))
+    return arg;
+  else if (ada_is_fixed_point_type (VALUE_TYPE (arg)))
+    val = ada_float_to_fixed (type, 
+                             ada_fixed_to_float (VALUE_TYPE (arg),
+                                                 value_as_long (arg)));
+  else 
+    {
+      DOUBLEST argd = 
+       value_as_double (value_cast (builtin_type_double, value_copy (arg)));
+      val = ada_float_to_fixed (type, argd);
+    }
+
+  return value_from_longest (type, val);
+}
+
+static struct value*
+cast_from_fixed_to_double (arg)
+     struct value* arg;
+{
+  DOUBLEST val = ada_fixed_to_float (VALUE_TYPE (arg),
+                                    value_as_long (arg));
+  return value_from_double (builtin_type_double, val);
+}
+
+/* Coerce VAL as necessary for assignment to an lval of type TYPE, and 
+ * return the converted value. */
+static struct value*
+coerce_for_assign (type, val)
+     struct type* type;
+     struct value* val;
+{
+  struct type* type2 = VALUE_TYPE (val);
+  if (type == type2)
+    return val;
+
+  CHECK_TYPEDEF (type2);
+  CHECK_TYPEDEF (type);
+
+  if (TYPE_CODE (type2) == TYPE_CODE_PTR && TYPE_CODE (type) == TYPE_CODE_ARRAY)
+    {
+      val = ada_value_ind (val);
+      type2 = VALUE_TYPE (val);
+    }
+
+  if (TYPE_CODE (type2) == TYPE_CODE_ARRAY 
+      && TYPE_CODE (type) == TYPE_CODE_ARRAY)
+    {
+      if (TYPE_LENGTH (type2) != TYPE_LENGTH (type)
+         || TYPE_LENGTH (TYPE_TARGET_TYPE (type2))
+            != TYPE_LENGTH (TYPE_TARGET_TYPE (type2)))
+       error ("Incompatible types in assignment");
+      VALUE_TYPE (val) = type;
+    }
+  return val;  
+}
+
+struct value*
+ada_evaluate_subexp (expect_type, exp, pos, noside)
+     struct type *expect_type;
+     struct expression *exp;
+     int *pos;
+     enum noside noside;
+{
+  enum exp_opcode op;
+  enum ada_attribute atr;
+  int tem, tem2, tem3;
+  int pc;
+  struct value *arg1 = NULL, *arg2 = NULL, *arg3;
+  struct type *type;
+  int nargs;
+  struct value* *argvec;
+
+  pc = *pos; *pos += 1;
+  op = exp->elts[pc].opcode;
+
+  switch (op) 
+    {
+    default:
+      *pos -= 1;
+      return unwrap_value (evaluate_subexp_standard (expect_type, exp, pos, noside));
+
+    case UNOP_CAST:
+      (*pos) += 2;
+      type = exp->elts[pc + 1].type;
+      arg1 = evaluate_subexp (type, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (type != check_typedef (VALUE_TYPE (arg1)))
+       {
+         if (ada_is_fixed_point_type (type))
+           arg1 = cast_to_fixed (type, arg1);
+         else if (ada_is_fixed_point_type (VALUE_TYPE (arg1)))
+           arg1 = value_cast (type, cast_from_fixed_to_double (arg1));
+         else if (VALUE_LVAL (arg1) == lval_memory) 
+           {
+             /* This is in case of the really obscure (and undocumented,
+                but apparently expected) case of (Foo) Bar.all, where Bar 
+                is an integer constant and Foo is a dynamic-sized type.
+                If we don't do this, ARG1 will simply be relabeled with
+                TYPE. */
+             if (noside == EVAL_AVOID_SIDE_EFFECTS) 
+               return value_zero (to_static_fixed_type (type), not_lval);
+             arg1 = 
+               ada_to_fixed_value 
+                 (type, 0, VALUE_ADDRESS (arg1) + VALUE_OFFSET (arg1), 0);
+           }
+         else           
+           arg1 = value_cast (type, arg1);     
+       }
+      return arg1;
+
+      /* FIXME:  UNOP_QUAL should be defined in expression.h */
+      /*    case UNOP_QUAL:
+      (*pos) += 2;
+      type = exp->elts[pc + 1].type;
+      return ada_evaluate_subexp (type, exp, pos, noside);
+      */
+    case BINOP_ASSIGN:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      arg2 = evaluate_subexp (VALUE_TYPE (arg1), exp, pos, noside);
+      if (noside == EVAL_SKIP || noside == EVAL_AVOID_SIDE_EFFECTS)
+       return arg1;
+      if (binop_user_defined_p (op, arg1, arg2))
+       return value_x_binop (arg1, arg2, op, OP_NULL, EVAL_NORMAL);
+      else 
+       {
+         if (ada_is_fixed_point_type (VALUE_TYPE (arg1)))
+           arg2 = cast_to_fixed (VALUE_TYPE (arg1), arg2);
+         else if (ada_is_fixed_point_type (VALUE_TYPE (arg2)))
+           error ("Fixed-point values must be assigned to fixed-point variables");
+         else 
+           arg2 = coerce_for_assign (VALUE_TYPE (arg1), arg2);
+         return ada_value_assign (arg1, arg2);
+       }
+
+    case BINOP_ADD:
+      arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+      arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (binop_user_defined_p (op, arg1, arg2))
+       return value_x_binop (arg1, arg2, op, OP_NULL, EVAL_NORMAL);
+      else
+       {
+         if ((ada_is_fixed_point_type (VALUE_TYPE (arg1))
+              || ada_is_fixed_point_type (VALUE_TYPE (arg2)))
+             && VALUE_TYPE (arg1) != VALUE_TYPE (arg2))
+           error ("Operands of fixed-point addition must have the same type");
+         return value_cast (VALUE_TYPE (arg1), value_add (arg1, arg2));
+       }
+
+    case BINOP_SUB:
+      arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
+      arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (binop_user_defined_p (op, arg1, arg2))
+       return value_x_binop (arg1, arg2, op, OP_NULL, EVAL_NORMAL);
+      else
+       {
+         if ((ada_is_fixed_point_type (VALUE_TYPE (arg1))
+              || ada_is_fixed_point_type (VALUE_TYPE (arg2)))
+             && VALUE_TYPE (arg1) != VALUE_TYPE (arg2))
+           error ("Operands of fixed-point subtraction must have the same type");              
+         return value_cast (VALUE_TYPE (arg1), value_sub (arg1, arg2));
+       }
+
+    case BINOP_MUL:
+    case BINOP_DIV:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (binop_user_defined_p (op, arg1, arg2))
+       return value_x_binop (arg1, arg2, op, OP_NULL, EVAL_NORMAL);
+      else
+       if (noside == EVAL_AVOID_SIDE_EFFECTS
+           && (op == BINOP_DIV || op == BINOP_REM || op == BINOP_MOD))
+         return value_zero (VALUE_TYPE (arg1), not_lval);
+      else
+       {
+         if (ada_is_fixed_point_type (VALUE_TYPE (arg1)))
+           arg1 = cast_from_fixed_to_double (arg1);
+         if (ada_is_fixed_point_type (VALUE_TYPE (arg2)))
+           arg2 = cast_from_fixed_to_double (arg2);
+         return value_binop (arg1, arg2, op);
+       }
+
+    case UNOP_NEG:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (unop_user_defined_p (op, arg1))
+       return value_x_unop (arg1, op, EVAL_NORMAL);
+      else if (ada_is_fixed_point_type (VALUE_TYPE (arg1)))
+       return value_cast (VALUE_TYPE (arg1), value_neg (arg1));
+      else
+       return value_neg (arg1);
+
+      /* FIXME:  OP_UNRESOLVED_VALUE should be defined in expression.h */
+      /*    case OP_UNRESOLVED_VALUE:
+      /* Only encountered when an unresolved symbol occurs in a
+         context other than a function call, in which case, it is
+        illegal. *//*
+      (*pos) += 3;
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      else 
+       error ("Unexpected unresolved symbol, %s, during evaluation",
+              ada_demangle (exp->elts[pc + 2].name));
+      */
+    case OP_VAR_VALUE:
+      *pos -= 1;
+      if (noside == EVAL_SKIP)
+       {
+         *pos += 4;
+         goto nosideret;
+       } 
+      else if (noside == EVAL_AVOID_SIDE_EFFECTS)
+       {
+         *pos += 4;
+         return value_zero 
+           (to_static_fixed_type 
+            (static_unwrap_type (SYMBOL_TYPE (exp->elts[pc+2].symbol))),
+            not_lval);
+       }
+      else 
+       {
+         arg1 = unwrap_value (evaluate_subexp_standard (expect_type, exp, pos, 
+                                                        noside));
+         return ada_to_fixed_value (VALUE_TYPE (arg1), 0,
+                                    VALUE_ADDRESS (arg1) + VALUE_OFFSET(arg1),
+                                    arg1);
+       }
+
+    case OP_ARRAY:
+      (*pos) += 3;
+      tem2 = longest_to_int (exp->elts[pc + 1].longconst);
+      tem3 = longest_to_int (exp->elts[pc + 2].longconst);
+      nargs = tem3 - tem2 + 1;
+      type = expect_type ? check_typedef (expect_type) : NULL_TYPE;
+
+      argvec = (struct value* *) alloca (sizeof (struct value*) * (nargs + 1));
+      for (tem = 0; tem == 0 || tem < nargs; tem += 1)
+       /* At least one element gets inserted for the type */
+       {
+         /* Ensure that array expressions are coerced into pointer objects. */
+         argvec[tem] = evaluate_subexp_with_coercion (exp, pos, noside);
+       }
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      return value_array (tem2, tem3, argvec);
+
+    case OP_FUNCALL:
+      (*pos) += 2;
+
+      /* Allocate arg vector, including space for the function to be
+        called in argvec[0] and a terminating NULL */
+      nargs = longest_to_int (exp->elts[pc + 1].longconst);
+      argvec = (struct value* *) alloca (sizeof (struct value*) * (nargs + 2));
+
+      /* FIXME: OP_UNRESOLVED_VALUE should be defined in expression.h */
+      /* FIXME: name should be defined in expresion.h */
+      /*      if (exp->elts[*pos].opcode == OP_UNRESOLVED_VALUE)
+       error ("Unexpected unresolved symbol, %s, during evaluation",
+              ada_demangle (exp->elts[pc + 5].name));
+      */
+      if (0) 
+       {
+         error ("unexpected code path, FIXME");
+       }
+      else
+       {
+         for (tem = 0; tem <= nargs; tem += 1)
+           argvec[tem] = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+         argvec[tem] = 0;
+
+         if (noside == EVAL_SKIP)
+           goto nosideret;
+       }
+
+      if (TYPE_CODE (VALUE_TYPE (argvec[0])) == TYPE_CODE_REF)
+       argvec[0] = value_addr (argvec[0]);
+
+      if (ada_is_packed_array_type (VALUE_TYPE (argvec[0])))
+       argvec[0] = ada_coerce_to_simple_array (argvec[0]);
+
+      type = check_typedef (VALUE_TYPE (argvec[0]));
+      if (TYPE_CODE (type) == TYPE_CODE_PTR)
+       {       
+         switch (TYPE_CODE (check_typedef (TYPE_TARGET_TYPE (type))))
+           {
+           case TYPE_CODE_FUNC:
+             type = check_typedef (TYPE_TARGET_TYPE (type));
+             break;
+           case TYPE_CODE_ARRAY:
+             break;
+           case TYPE_CODE_STRUCT:
+             if (noside != EVAL_AVOID_SIDE_EFFECTS)
+               argvec[0] = ada_value_ind (argvec[0]);
+             type = check_typedef (TYPE_TARGET_TYPE (type));
+             break;
+           default:
+             error ("cannot subscript or call something of type `%s'",
+                    ada_type_name (VALUE_TYPE (argvec[0])));
+             break;
+         }
+       }
+         
+      switch (TYPE_CODE (type))
+       {
+       case TYPE_CODE_FUNC:
+         if (noside == EVAL_AVOID_SIDE_EFFECTS)
+           return allocate_value (TYPE_TARGET_TYPE (type));
+         return call_function_by_hand (argvec[0], nargs, argvec + 1);
+       case TYPE_CODE_STRUCT: 
+         {
+           int arity = ada_array_arity (type);
+           type = ada_array_element_type (type, nargs);
+           if (type == NULL) 
+             error ("cannot subscript or call a record");
+           if (arity != nargs) 
+             error ("wrong number of subscripts; expecting %d", arity);
+           if (noside == EVAL_AVOID_SIDE_EFFECTS) 
+             return allocate_value (ada_aligned_type (type));
+           return unwrap_value (ada_value_subscript (argvec[0], nargs, argvec+1));
+         }
+       case TYPE_CODE_ARRAY:
+         if (noside == EVAL_AVOID_SIDE_EFFECTS)
+           {   
+             type = ada_array_element_type (type, nargs);
+             if (type == NULL)
+               error ("element type of array unknown");
+             else
+               return allocate_value (ada_aligned_type (type));
+           }
+         return 
+           unwrap_value (ada_value_subscript
+                         (ada_coerce_to_simple_array (argvec[0]),
+                          nargs, argvec+1));
+       case TYPE_CODE_PTR: /* Pointer to array */
+         type = to_fixed_array_type (TYPE_TARGET_TYPE (type), NULL, 1);
+         if (noside == EVAL_AVOID_SIDE_EFFECTS)
+           {   
+             type = ada_array_element_type (type, nargs);
+             if (type == NULL)
+               error ("element type of array unknown");
+             else
+               return allocate_value (ada_aligned_type (type));
+           }
+         return 
+           unwrap_value (ada_value_ptr_subscript (argvec[0], type, 
+                                                  nargs, argvec+1));
+
+       default:
+         error ("Internal error in evaluate_subexp");
+       }
+
+    case TERNOP_SLICE:
+      {
+       struct value* array = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+       int lowbound
+         = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside));
+       int upper
+         = value_as_long (evaluate_subexp (NULL_TYPE, exp, pos, noside));
+       if (noside == EVAL_SKIP)
+         goto nosideret;
+        
+        /* If this is a reference to an array, then dereference it */
+        if (TYPE_CODE (VALUE_TYPE (array)) == TYPE_CODE_REF
+            && TYPE_TARGET_TYPE (VALUE_TYPE (array)) != NULL
+            && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (array))) ==
+                 TYPE_CODE_ARRAY
+            && !ada_is_array_descriptor (check_typedef (VALUE_TYPE
+               (array))))
+          {
+            array = ada_coerce_ref (array);
+          }
+
+       if (noside == EVAL_AVOID_SIDE_EFFECTS &&
+           ada_is_array_descriptor (check_typedef (VALUE_TYPE (array))))
+         {
+           /* Try to dereference the array, in case it is an access to array */
+           struct type * arrType = ada_type_of_array (array, 0);
+           if (arrType != NULL)
+             array = value_at_lazy (arrType, 0, NULL); 
+         }
+       if (ada_is_array_descriptor (VALUE_TYPE (array)))
+         array = ada_coerce_to_simple_array (array);
+
+        /* If at this point we have a pointer to an array, it means that
+           it is a pointer to a simple (non-ada) array. We just then
+           dereference it */
+        if (TYPE_CODE (VALUE_TYPE (array)) == TYPE_CODE_PTR
+            && TYPE_TARGET_TYPE (VALUE_TYPE (array)) != NULL
+            && TYPE_CODE (TYPE_TARGET_TYPE (VALUE_TYPE (array))) ==
+                 TYPE_CODE_ARRAY)
+          {
+              array = ada_value_ind (array);
+          }
+        
+       if (noside == EVAL_AVOID_SIDE_EFFECTS)
+         /* The following will get the bounds wrong, but only in contexts
+            where the value is not being requested (FIXME?). */
+         return array;
+       else
+         return value_slice (array, lowbound, upper - lowbound + 1);
+      }
+
+      /* FIXME: UNOP_MBR should be defined in expression.h */
+      /*    case UNOP_MBR:
+      (*pos) += 2;
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      type = exp->elts[pc + 1].type;
+
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+
+      switch (TYPE_CODE (type)) 
+       {
+       default:
+         warning ("Membership test incompletely implemented; always returns true");
+         return value_from_longest (builtin_type_int, (LONGEST) 1);
+         
+       case TYPE_CODE_RANGE:
+         arg2 = value_from_longest (builtin_type_int, 
+                                    (LONGEST) TYPE_LOW_BOUND (type));
+         arg3 = value_from_longest (builtin_type_int, 
+                                    (LONGEST) TYPE_HIGH_BOUND (type));
+         return 
+           value_from_longest (builtin_type_int,
+                               (value_less (arg1,arg3) 
+                                || value_equal (arg1,arg3))
+                               && (value_less (arg2,arg1)
+                                   || value_equal (arg2,arg1)));
+       }
+      */
+      /* FIXME: BINOP_MBR should be defined in expression.h */      
+      /*    case BINOP_MBR:
+      (*pos) += 2;
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+
+      if (noside == EVAL_AVOID_SIDE_EFFECTS)
+       return value_zero (builtin_type_int, not_lval);
+
+      tem = longest_to_int (exp->elts[pc + 1].longconst);
+
+      if (tem < 1 || tem > ada_array_arity (VALUE_TYPE (arg2)))
+       error ("invalid dimension number to '%s", "range");
+
+      arg3 = ada_array_bound (arg2, tem, 1);
+      arg2 = ada_array_bound (arg2, tem, 0);
+
+      return 
+       value_from_longest (builtin_type_int,
+                           (value_less (arg1,arg3) 
+                            || value_equal (arg1,arg3))
+                           && (value_less (arg2,arg1)
+                               || value_equal (arg2,arg1)));
+      */
+      /* FIXME: TERNOP_MBR should be defined in expression.h */
+      /*    case TERNOP_MBR:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      arg3 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+
+      return 
+       value_from_longest (builtin_type_int,
+                           (value_less (arg1,arg3) 
+                            || value_equal (arg1,arg3))
+                           && (value_less (arg2,arg1)
+                               || value_equal (arg2,arg1)));
+      */
+      /* FIXME: OP_ATTRIBUTE should be defined in expression.h */
+      /*    case OP_ATTRIBUTE:
+      *pos += 3;
+      atr = (enum ada_attribute) longest_to_int (exp->elts[pc + 2].longconst);
+      switch (atr) 
+       {
+       default:
+         error ("unexpected attribute encountered");
+
+       case ATR_FIRST:
+       case ATR_LAST:
+       case ATR_LENGTH:
+         {
+           struct type* type_arg;
+           if (exp->elts[*pos].opcode == OP_TYPE)
+             {
+               evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
+               arg1 = NULL;
+               type_arg = exp->elts[pc + 5].type;
+             }
+           else
+             {
+               arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+               type_arg = NULL;
+             }
+
+           if (exp->elts[*pos].opcode != OP_LONG) 
+             error ("illegal operand to '%s", ada_attribute_name (atr));
+           tem = longest_to_int (exp->elts[*pos+2].longconst);
+           *pos += 4;
+
+           if (noside == EVAL_SKIP)
+             goto nosideret;
+
+           if (type_arg == NULL)
+             {
+               arg1 = ada_coerce_ref (arg1);
+
+               if (ada_is_packed_array_type (VALUE_TYPE (arg1)))
+                 arg1 = ada_coerce_to_simple_array (arg1);
+
+               if (tem < 1 || tem > ada_array_arity (VALUE_TYPE (arg1)))
+                 error ("invalid dimension number to '%s", 
+                        ada_attribute_name (atr));
+
+               if (noside == EVAL_AVOID_SIDE_EFFECTS)
+                 {
+                   type = ada_index_type (VALUE_TYPE (arg1), tem);
+                   if (type == NULL) 
+                     error ("attempt to take bound of something that is not an array");
+                   return allocate_value (type);
+                 }
+
+               switch (atr) 
+                 {
+                 default: 
+                   error ("unexpected attribute encountered");
+                 case ATR_FIRST:
+                   return ada_array_bound (arg1, tem, 0);
+                 case ATR_LAST:
+                   return ada_array_bound (arg1, tem, 1);
+                 case ATR_LENGTH:
+                   return ada_array_length (arg1, tem);
+                 }
+             }
+           else if (TYPE_CODE (type_arg) == TYPE_CODE_RANGE
+                    || TYPE_CODE (type_arg) == TYPE_CODE_INT) 
+             {
+               struct type* range_type;
+               char* name = ada_type_name (type_arg);
+               if (name == NULL)
+                 {
+                   if (TYPE_CODE (type_arg) == TYPE_CODE_RANGE) 
+                     range_type = type_arg;
+                   else
+                     error ("unimplemented type attribute");
+                 }
+               else 
+                 range_type = 
+                   to_fixed_range_type (name, NULL, TYPE_OBJFILE (type_arg));
+               switch (atr) 
+                 {
+                 default: 
+                   error ("unexpected attribute encountered");
+                 case ATR_FIRST:
+                   return value_from_longest (TYPE_TARGET_TYPE (range_type),
+                                              TYPE_LOW_BOUND (range_type));
+                 case ATR_LAST:
+                   return value_from_longest (TYPE_TARGET_TYPE (range_type),
+                                              TYPE_HIGH_BOUND (range_type));
+                 }
+             }         
+           else if (TYPE_CODE (type_arg) == TYPE_CODE_ENUM)
+             {
+               switch (atr) 
+                 {
+                 default: 
+                   error ("unexpected attribute encountered");
+                 case ATR_FIRST:
+                   return value_from_longest 
+                     (type_arg, TYPE_FIELD_BITPOS (type_arg, 0));
+                 case ATR_LAST:
+                   return value_from_longest 
+                     (type_arg, 
+                      TYPE_FIELD_BITPOS (type_arg,
+                                         TYPE_NFIELDS (type_arg) - 1));
+                 }
+             }
+           else if (TYPE_CODE (type_arg) == TYPE_CODE_FLT)
+             error ("unimplemented type attribute");
+           else 
+             {
+               LONGEST low, high;
+
+               if (ada_is_packed_array_type (type_arg))
+                 type_arg = decode_packed_array_type (type_arg);
+
+               if (tem < 1 || tem > ada_array_arity (type_arg))
+                 error ("invalid dimension number to '%s", 
+                        ada_attribute_name (atr));
+
+               if (noside == EVAL_AVOID_SIDE_EFFECTS)
+                 {
+                   type = ada_index_type (type_arg, tem);
+                   if (type == NULL) 
+                     error ("attempt to take bound of something that is not an array");
+                   return allocate_value (type);
+                 }
+
+               switch (atr) 
+                 {
+                 default: 
+                   error ("unexpected attribute encountered");
+                 case ATR_FIRST:
+                   low = ada_array_bound_from_type (type_arg, tem, 0, &type);
+                   return value_from_longest (type, low);
+                 case ATR_LAST:
+                   high = ada_array_bound_from_type (type_arg, tem, 1, &type);
+                   return value_from_longest (type, high);
+                 case ATR_LENGTH:
+                   low = ada_array_bound_from_type (type_arg, tem, 0, &type);
+                   high = ada_array_bound_from_type (type_arg, tem, 1, NULL);
+                   return value_from_longest (type, high-low+1);
+                 }
+             }
+         }
+
+       case ATR_TAG:
+         arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+         if (noside == EVAL_SKIP)
+           goto nosideret;
+
+         if (noside == EVAL_AVOID_SIDE_EFFECTS)
+           return      
+             value_zero (ada_tag_type (arg1), not_lval);
+         
+         return ada_value_tag (arg1);
+         
+       case ATR_MIN:
+       case ATR_MAX:
+         evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
+         arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+         arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+         if (noside == EVAL_SKIP)
+           goto nosideret;
+         else if (noside == EVAL_AVOID_SIDE_EFFECTS)
+           return value_zero (VALUE_TYPE (arg1), not_lval);
+         else
+           return value_binop (arg1, arg2, 
+                               atr == ATR_MIN ? BINOP_MIN : BINOP_MAX);
+
+       case ATR_MODULUS:
+         {
+           struct type* type_arg = exp->elts[pc + 5].type;
+           evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
+           *pos += 4;
+
+           if (noside == EVAL_SKIP)
+             goto nosideret;
+
+           if (! ada_is_modular_type (type_arg))
+             error ("'modulus must be applied to modular type");
+
+           return value_from_longest (TYPE_TARGET_TYPE (type_arg),
+                                      ada_modulus (type_arg));
+         }
+         
+
+       case ATR_POS:
+         evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
+         arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+         if (noside == EVAL_SKIP)
+           goto nosideret;
+         else if (noside == EVAL_AVOID_SIDE_EFFECTS)
+           return value_zero (builtin_type_ada_int, not_lval);
+         else 
+           return value_pos_atr (arg1);
+
+       case ATR_SIZE:
+         arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+         if (noside == EVAL_SKIP)
+           goto nosideret;
+         else if (noside == EVAL_AVOID_SIDE_EFFECTS)
+           return value_zero (builtin_type_ada_int, not_lval);
+         else
+           return value_from_longest (builtin_type_ada_int,
+                                      TARGET_CHAR_BIT 
+                                      * TYPE_LENGTH (VALUE_TYPE (arg1)));
+
+       case ATR_VAL:
+         evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
+         arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+         type = exp->elts[pc + 5].type;
+         if (noside == EVAL_SKIP)
+           goto nosideret;
+         else if (noside == EVAL_AVOID_SIDE_EFFECTS)
+           return value_zero (type, not_lval);
+         else 
+           return value_val_atr (type, arg1);
+           }*/
+    case BINOP_EXP:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      arg2 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (binop_user_defined_p (op, arg1, arg2))
+       return unwrap_value (value_x_binop (arg1, arg2, op, OP_NULL,
+         EVAL_NORMAL));
+      else
+       if (noside == EVAL_AVOID_SIDE_EFFECTS)
+         return value_zero (VALUE_TYPE (arg1), not_lval);
+      else
+       return value_binop (arg1, arg2, op);
+
+    case UNOP_PLUS:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (unop_user_defined_p (op, arg1))
+       return unwrap_value (value_x_unop (arg1, op, EVAL_NORMAL));
+      else
+       return arg1;
+
+    case UNOP_ABS:
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (value_less (arg1, value_zero (VALUE_TYPE (arg1), not_lval)))
+       return value_neg (arg1);
+      else
+       return arg1;
+
+    case UNOP_IND:
+      if (expect_type && TYPE_CODE (expect_type) == TYPE_CODE_PTR)
+        expect_type = TYPE_TARGET_TYPE (check_typedef (expect_type));
+      arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      type = check_typedef (VALUE_TYPE (arg1));
+      if (noside == EVAL_AVOID_SIDE_EFFECTS)
+       {
+         if (ada_is_array_descriptor (type))
+           /* GDB allows dereferencing GNAT array descriptors. */
+           {
+             struct type* arrType = ada_type_of_array (arg1, 0); 
+             if (arrType == NULL)
+               error ("Attempt to dereference null array pointer.");
+             return value_at_lazy (arrType, 0, NULL);
+           }
+         else if (TYPE_CODE (type) == TYPE_CODE_PTR
+             || TYPE_CODE (type) == TYPE_CODE_REF
+             /* In C you can dereference an array to get the 1st elt.  */
+             || TYPE_CODE (type) == TYPE_CODE_ARRAY
+             )
+           return 
+             value_zero 
+               (to_static_fixed_type 
+                 (ada_aligned_type (check_typedef (TYPE_TARGET_TYPE (type)))),
+                lval_memory);
+         else if (TYPE_CODE (type) == TYPE_CODE_INT)
+           /* GDB allows dereferencing an int.  */
+           return value_zero (builtin_type_int, lval_memory);
+         else
+           error ("Attempt to take contents of a non-pointer value.");
+       }
+      arg1 = ada_coerce_ref (arg1);
+      type = check_typedef (VALUE_TYPE (arg1));
+         
+      if (ada_is_array_descriptor (type))
+       /* GDB allows dereferencing GNAT array descriptors. */
+       return ada_coerce_to_simple_array (arg1);
+      else
+       return ada_value_ind (arg1);
+
+    case STRUCTOP_STRUCT:
+      tem = longest_to_int (exp->elts[pc + 1].longconst);
+      (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (noside == EVAL_AVOID_SIDE_EFFECTS)
+       return value_zero (ada_aligned_type 
+                          (ada_lookup_struct_elt_type (VALUE_TYPE (arg1),
+                                                       &exp->elts[pc + 2].string,
+                                                       0, NULL)),
+                          lval_memory);
+      else
+       return unwrap_value (ada_value_struct_elt (arg1,
+                                                  &exp->elts[pc + 2].string,
+                                                  "record"));
+    case OP_TYPE:
+      /* The value is not supposed to be used. This is here to make it
+         easier to accommodate expressions that contain types. */
+      (*pos) += 2;
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      else if (noside == EVAL_AVOID_SIDE_EFFECTS)
+       return allocate_value (builtin_type_void);
+      else 
+       error ("Attempt to use a type name as an expression");
+      
+    case STRUCTOP_PTR:
+      tem = longest_to_int (exp->elts[pc + 1].longconst);
+      (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+      arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+       goto nosideret;
+      if (noside == EVAL_AVOID_SIDE_EFFECTS)
+       return value_zero (ada_aligned_type 
+                          (ada_lookup_struct_elt_type (VALUE_TYPE (arg1),
+                                                       &exp->elts[pc + 2].string,
+                                                       0, NULL)),
+                          lval_memory);
+      else
+       return unwrap_value (ada_value_struct_elt (arg1,
+                                                  &exp->elts[pc + 2].string,
+                                                  "record access"));
+    }
+
+nosideret:
+  return value_from_longest (builtin_type_long, (LONGEST) 1);
+}
+
+\f
+                               /* Fixed point */
+
+/* If TYPE encodes an Ada fixed-point type, return the suffix of the
+   type name that encodes the 'small and 'delta information.
+   Otherwise, return NULL. */
+
+static const char*
+fixed_type_info (type)
+     struct type *type;
+{
+  const char* name = ada_type_name (type);
+  enum type_code code = (type == NULL) ? TYPE_CODE_UNDEF : TYPE_CODE (type);
+
+  if ((code == TYPE_CODE_INT || code == TYPE_CODE_RANGE)
+      && name != NULL)
+    {  
+      const char *tail = strstr (name, "___XF_");
+      if (tail == NULL)
+       return NULL;
+      else 
+       return tail + 5;
+    }
+  else if (code == TYPE_CODE_RANGE && TYPE_TARGET_TYPE (type) != type)
+    return fixed_type_info (TYPE_TARGET_TYPE (type));
+  else
+    return NULL;
+}
+
+/* Returns non-zero iff TYPE represents an Ada fixed-point type. */
+
+int
+ada_is_fixed_point_type (type)
+     struct type *type;
+{
+  return fixed_type_info (type) != NULL;
+}
+
+/* Assuming that TYPE is the representation of an Ada fixed-point
+   type, return its delta, or -1 if the type is malformed and the
+   delta cannot be determined. */
+
+DOUBLEST
+ada_delta (type)
+     struct type *type;
+{
+  const char *encoding = fixed_type_info (type);
+  long num, den;
+
+  if (sscanf (encoding, "_%ld_%ld", &num, &den) < 2)
+    return -1.0;
+  else 
+    return (DOUBLEST) num / (DOUBLEST) den;
+}
+
+/* Assuming that ada_is_fixed_point_type (TYPE), return the scaling
+   factor ('SMALL value) associated with the type. */
+
+static DOUBLEST
+scaling_factor (type)
+     struct type *type;
+{
+  const char *encoding = fixed_type_info (type);
+  unsigned long num0, den0, num1, den1;
+  int n;
+  
+  n = sscanf (encoding, "_%lu_%lu_%lu_%lu", &num0, &den0, &num1, &den1);
+
+  if (n < 2)
+    return 1.0;
+  else if (n == 4)
+    return (DOUBLEST) num1 / (DOUBLEST) den1;
+  else 
+    return (DOUBLEST) num0 / (DOUBLEST) den0;
+}
+
+
+/* Assuming that X is the representation of a value of fixed-point
+   type TYPE, return its floating-point equivalent. */
+
+DOUBLEST
+ada_fixed_to_float (type, x)
+     struct type *type;
+     LONGEST x;
+{
+  return (DOUBLEST) x * scaling_factor (type);
+}
+
+/* The representation of a fixed-point value of type TYPE 
+   corresponding to the value X. */
+
+LONGEST
+ada_float_to_fixed (type, x)
+     struct type *type;
+     DOUBLEST x;
+{
+  return (LONGEST) (x / scaling_factor (type) + 0.5);
+}
+
+
+                               /* VAX floating formats */
+
+/* Non-zero iff TYPE represents one of the special VAX floating-point
+   types. */
+int
+ada_is_vax_floating_type (type)
+     struct type* type;
+{
+  int name_len = 
+    (ada_type_name (type) == NULL) ? 0 : strlen (ada_type_name (type));
+  return 
+    name_len > 6
+    && (TYPE_CODE (type) == TYPE_CODE_INT 
+       || TYPE_CODE (type) == TYPE_CODE_RANGE)
+    && STREQN (ada_type_name (type) + name_len - 6, "___XF", 5);
+}
+
+/* The type of special VAX floating-point type this is, assuming
+   ada_is_vax_floating_point */
+int
+ada_vax_float_type_suffix (type)
+     struct type* type;
+{
+  return ada_type_name (type)[strlen (ada_type_name (type))-1];
+}
+
+/* A value representing the special debugging function that outputs 
+   VAX floating-point values of the type represented by TYPE.  Assumes
+   ada_is_vax_floating_type (TYPE). */
+struct value*
+ada_vax_float_print_function (type)
+
+     struct type* type;
+{
+  switch (ada_vax_float_type_suffix (type)) {
+  case 'F':
+    return 
+      get_var_value ("DEBUG_STRING_F", 0);
+  case 'D':
+    return 
+      get_var_value ("DEBUG_STRING_D", 0);
+  case 'G':
+    return 
+      get_var_value ("DEBUG_STRING_G", 0);
+  default:
+    error ("invalid VAX floating-point type");
+  }
+}
+
+\f
+                               /* Range types */
+
+/* Scan STR beginning at position K for a discriminant name, and
+   return the value of that discriminant field of DVAL in *PX.  If
+   PNEW_K is not null, put the position of the character beyond the
+   name scanned in *PNEW_K.  Return 1 if successful; return 0 and do
+   not alter *PX and *PNEW_K if unsuccessful. */
+
+static int
+scan_discrim_bound (str, k, dval, px, pnew_k)
+     char *str;
+     int k;
+     struct value* dval;
+     LONGEST *px;
+     int *pnew_k;
+{
+  static char *bound_buffer = NULL;
+  static size_t bound_buffer_len = 0;
+  char *bound;
+  char *pend;
+  struct value* bound_val;
+
+  if (dval == NULL || str == NULL || str[k] == '\0')
+    return 0;
+
+  pend = strstr (str+k, "__");
+  if (pend == NULL)
+    {
+      bound = str+k;
+      k += strlen (bound);
+    }
+  else 
+    {
+      GROW_VECT (bound_buffer, bound_buffer_len, pend - (str+k) + 1);
+      bound = bound_buffer;
+      strncpy (bound_buffer, str+k, pend-(str+k));
+      bound[pend-(str+k)] = '\0';
+      k = pend-str;
+    }
+  
+  bound_val = 
+    ada_search_struct_field (bound, dval, 0, VALUE_TYPE (dval));
+  if (bound_val == NULL)
+    return 0;
+
+  *px = value_as_long (bound_val);
+  if (pnew_k != NULL)
+    *pnew_k = k;
+  return 1;
+}
+
+/* Value of variable named NAME in the current environment.  If
+   no such variable found, then if ERR_MSG is null, returns 0, and
+   otherwise causes an error with message ERR_MSG. */
+static struct value*
+get_var_value (name, err_msg)
+     char* name;
+     char* err_msg;
+{
+  struct symbol** syms;
+  struct block** blocks;
+  int nsyms;
+
+  nsyms = ada_lookup_symbol_list (name, get_selected_block (NULL), VAR_NAMESPACE,
+                                 &syms, &blocks);
+
+  if (nsyms != 1)
+    {
+      if (err_msg == NULL)
+       return 0;
+      else
+       error ("%s", err_msg);
+    }
+
+  return value_of_variable (syms[0], blocks[0]);
+}
+/* Value of integer variable named NAME in the current environment.  If
+   no such variable found, then if ERR_MSG is null, returns 0, and sets
+   *FLAG to 0.  If successful, sets *FLAG to 1. */
+LONGEST
+get_int_var_value (name, err_msg, flag)
+     char* name;
+     char* err_msg;
+     int* flag;
+{
+  struct value* var_val = get_var_value (name, err_msg);
+  
+  if (var_val == 0)
+    {
+      if (flag != NULL)
+       *flag = 0;
+      return 0;
+    }
+  else
+    {
+      if (flag != NULL)
+       *flag = 1;
+      return value_as_long (var_val);
+    }
+}
+
+/* Return a range type whose base type is that of the range type named
+   NAME in the current environment, and whose bounds are calculated
+   from NAME according to the GNAT range encoding conventions. 
+   Extract discriminant values, if needed, from DVAL.  If a new type
+   must be created, allocate in OBJFILE's space.  The bounds
+   information, in general, is encoded in NAME, the base type given in
+   the named range type. */
+
+static struct type*
+to_fixed_range_type (name, dval, objfile)
+     char *name;
+     struct value *dval;
+     struct objfile *objfile;
+{
+  struct type *raw_type = ada_find_any_type (name);
+  struct type *base_type;
+  LONGEST low, high;
+  char* subtype_info;
+
+  if (raw_type == NULL)
+    base_type = builtin_type_int;
+  else if (TYPE_CODE (raw_type) == TYPE_CODE_RANGE)
+    base_type = TYPE_TARGET_TYPE (raw_type);
+  else
+    base_type = raw_type;
+
+  subtype_info = strstr (name, "___XD");
+  if (subtype_info == NULL)
+    return raw_type;
+  else
+    {
+      static char *name_buf = NULL;
+      static size_t name_len = 0;
+      int prefix_len = subtype_info - name;
+      LONGEST L, U;
+      struct type *type;
+      char *bounds_str;
+      int n;
+
+      GROW_VECT (name_buf, name_len, prefix_len + 5);
+      strncpy (name_buf, name, prefix_len);
+      name_buf[prefix_len] = '\0';
+
+      subtype_info += 5;
+      bounds_str = strchr (subtype_info, '_');
+      n = 1;
+
+      if (*subtype_info == 'L') 
+       {
+         if (! ada_scan_number (bounds_str, n, &L, &n)
+             && ! scan_discrim_bound (bounds_str, n, dval, &L, &n))
+           return raw_type;
+         if (bounds_str[n] == '_')
+           n += 2;
+         else if (bounds_str[n] == '.') /* FIXME? SGI Workshop kludge. */
+           n += 1;
+         subtype_info += 1;
+       }
+      else 
+       {
+         strcpy (name_buf+prefix_len, "___L");
+         L = get_int_var_value (name_buf, "Index bound unknown.", NULL);
+       }
+
+      if (*subtype_info == 'U') 
+       {
+         if (! ada_scan_number (bounds_str, n, &U, &n)
+             && !scan_discrim_bound (bounds_str, n, dval, &U, &n))
+           return raw_type;
+       }
+      else 
+       {
+         strcpy (name_buf+prefix_len, "___U");
+         U = get_int_var_value (name_buf, "Index bound unknown.", NULL);
+       }
+
+      if (objfile == NULL) 
+       objfile = TYPE_OBJFILE (base_type);
+      type = create_range_type (alloc_type (objfile), base_type, L, U);
+      TYPE_NAME (type) = name; 
+      return type;
+    }
+}
+
+/* True iff NAME is the name of a range type. */
+int
+ada_is_range_type_name (name)
+     const char* name;
+{
+  return (name != NULL && strstr (name, "___XD"));
+}        
+
+\f
+                               /* Modular types */
+
+/* True iff TYPE is an Ada modular type. */
+int
+ada_is_modular_type (type)
+     struct type* type;
+{
+  /* FIXME: base_type should be declared in gdbtypes.h, implemented in
+     valarith.c */  
+  struct type* subranged_type; /* = base_type (type);*/
+
+  return (subranged_type != NULL && TYPE_CODE (type) == TYPE_CODE_RANGE
+         && TYPE_CODE (subranged_type) != TYPE_CODE_ENUM
+         && TYPE_UNSIGNED (subranged_type));
+}
+
+/* Assuming ada_is_modular_type (TYPE), the modulus of TYPE. */
+LONGEST
+ada_modulus (type)
+     struct type* type;
+{
+    return TYPE_HIGH_BOUND (type) + 1;
+}
+
+
+\f
+                               /* Operators */
+
+/* Table mapping opcodes into strings for printing operators
+   and precedences of the operators.  */
+
+static const struct op_print ada_op_print_tab[] =
+  {
+    {":=",  BINOP_ASSIGN, PREC_ASSIGN, 1},
+    {"or else", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
+    {"and then", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
+    {"or",  BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
+    {"xor",  BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
+    {"and",  BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
+    {"=", BINOP_EQUAL, PREC_EQUAL, 0},
+    {"/=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
+    {"<=", BINOP_LEQ, PREC_ORDER, 0},
+    {">=", BINOP_GEQ, PREC_ORDER, 0},
+    {">",  BINOP_GTR, PREC_ORDER, 0},
+    {"<",  BINOP_LESS, PREC_ORDER, 0},
+    {">>", BINOP_RSH, PREC_SHIFT, 0},
+    {"<<", BINOP_LSH, PREC_SHIFT, 0},
+    {"+",  BINOP_ADD, PREC_ADD, 0},
+    {"-",  BINOP_SUB, PREC_ADD, 0},
+    {"&",  BINOP_CONCAT, PREC_ADD, 0},
+    {"*",  BINOP_MUL, PREC_MUL, 0},
+    {"/",  BINOP_DIV, PREC_MUL, 0},
+    {"rem",  BINOP_REM, PREC_MUL, 0},
+    {"mod",  BINOP_MOD, PREC_MUL, 0},
+    {"**", BINOP_EXP, PREC_REPEAT, 0 },
+    {"@",  BINOP_REPEAT, PREC_REPEAT, 0},
+    {"-",  UNOP_NEG, PREC_PREFIX, 0},
+    {"+",  UNOP_PLUS, PREC_PREFIX, 0},
+    {"not ",  UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
+    {"not ",  UNOP_COMPLEMENT, PREC_PREFIX, 0},
+    {"abs ",  UNOP_ABS, PREC_PREFIX, 0},
+    {".all",  UNOP_IND, PREC_SUFFIX, 1},  /* FIXME: postfix .ALL */
+    {"'access",  UNOP_ADDR, PREC_SUFFIX, 1}, /* FIXME: postfix 'ACCESS */
+    {NULL, 0, 0, 0}
+};
+\f
+                       /* Assorted Types and Interfaces */
+
+struct type* builtin_type_ada_int;
+struct type* builtin_type_ada_short;
+struct type* builtin_type_ada_long;
+struct type* builtin_type_ada_long_long;
+struct type* builtin_type_ada_char;
+struct type* builtin_type_ada_float;
+struct type* builtin_type_ada_double;
+struct type* builtin_type_ada_long_double;
+struct type* builtin_type_ada_natural;
+struct type* builtin_type_ada_positive;
+struct type* builtin_type_ada_system_address;
+
+struct type ** const (ada_builtin_types[]) = 
+{
+  
+  &builtin_type_ada_int,
+  &builtin_type_ada_long,
+  &builtin_type_ada_short,
+  &builtin_type_ada_char,
+  &builtin_type_ada_float,
+  &builtin_type_ada_double,
+  &builtin_type_ada_long_long,
+  &builtin_type_ada_long_double,
+  &builtin_type_ada_natural,
+  &builtin_type_ada_positive,
+
+  /* The following types are carried over from C for convenience. */
+  &builtin_type_int,
+  &builtin_type_long,
+  &builtin_type_short,
+  &builtin_type_char,
+  &builtin_type_float,
+  &builtin_type_double,
+  &builtin_type_long_long,
+  &builtin_type_void,
+  &builtin_type_signed_char,
+  &builtin_type_unsigned_char,
+  &builtin_type_unsigned_short,
+  &builtin_type_unsigned_int,
+  &builtin_type_unsigned_long,
+  &builtin_type_unsigned_long_long,
+  &builtin_type_long_double,
+  &builtin_type_complex,
+  &builtin_type_double_complex,
+  0
+};
+
+/* Not really used, but needed in the ada_language_defn. */
+static void emit_char (int c, struct ui_file* stream, int quoter) 
+{
+  ada_emit_char (c, stream, quoter, 1);
+}
+
+const struct language_defn ada_language_defn = {
+  "ada",                       /* Language name */
+  /*  language_ada, */
+  language_unknown,
+  /* FIXME: language_ada should be defined in defs.h */
+  ada_builtin_types,
+  range_check_off,
+  type_check_off,
+  case_sensitive_on,           /* Yes, Ada is case-insensitive, but
+                                * that's not quite what this means. */
+  ada_parse,
+  ada_error,
+  ada_evaluate_subexp,
+  ada_printchar,               /* Print a character constant */
+  ada_printstr,                        /* Function to print string constant */
+  emit_char,                   /* Function to print single char (not used) */
+  ada_create_fundamental_type, /* Create fundamental type in this language */
+  ada_print_type,              /* Print a type using appropriate syntax */
+  ada_val_print,               /* Print a value using appropriate syntax */
+  ada_value_print,             /* Print a top-level value */
+  {"",     "",    "",  ""},    /* Binary format info */
+#if 0
+  {"8#%lo#",  "8#",   "o", "#"},       /* Octal format info */
+  {"%ld",   "",    "d", ""},   /* Decimal format info */
+  {"16#%lx#", "16#",  "x", "#"},       /* Hex format info */
+#else
+  /* Copied from c-lang.c. */
+  {"0%lo",  "0",   "o", ""},   /* Octal format info */
+  {"%ld",   "",    "d", ""},   /* Decimal format info */
+  {"0x%lx", "0x",  "x", ""},   /* Hex format info */
+#endif
+  ada_op_print_tab,            /* expression operators for printing */
+  1,                           /* c-style arrays (FIXME?) */
+  0,                           /* String lower bound (FIXME?) */
+  &builtin_type_ada_char,
+  LANG_MAGIC
+};
+
+void
+_initialize_ada_language ()
+{
+  builtin_type_ada_int =
+    init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+              0,
+              "integer", (struct objfile *) NULL);
+  builtin_type_ada_long =
+    init_type (TYPE_CODE_INT, TARGET_LONG_BIT / TARGET_CHAR_BIT,
+              0,
+              "long_integer", (struct objfile *) NULL);
+  builtin_type_ada_short =
+    init_type (TYPE_CODE_INT, TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+              0,
+              "short_integer", (struct objfile *) NULL);
+  builtin_type_ada_char =
+    init_type (TYPE_CODE_INT, TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+              0,
+              "character", (struct objfile *) NULL);
+  builtin_type_ada_float =
+    init_type (TYPE_CODE_FLT, TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+              0,
+              "float", (struct objfile *) NULL);
+  builtin_type_ada_double =
+    init_type (TYPE_CODE_FLT, TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+              0,
+              "long_float", (struct objfile *) NULL);
+  builtin_type_ada_long_long =
+    init_type (TYPE_CODE_INT, TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+              0,
+              "long_long_integer", (struct objfile *) NULL);
+  builtin_type_ada_long_double =
+    init_type (TYPE_CODE_FLT, TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
+              0,
+              "long_long_float", (struct objfile *) NULL);
+  builtin_type_ada_natural =
+    init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+              0,
+              "natural", (struct objfile *) NULL);
+  builtin_type_ada_positive =
+    init_type (TYPE_CODE_INT, TARGET_INT_BIT / TARGET_CHAR_BIT,
+              0,
+              "positive", (struct objfile *) NULL);
+
+
+  builtin_type_ada_system_address = 
+    lookup_pointer_type (init_type (TYPE_CODE_VOID, 1, 0, "void", 
+                                   (struct objfile *) NULL));
+  TYPE_NAME (builtin_type_ada_system_address) = "system__address";
+
+  add_language (&ada_language_defn);
+
+  add_show_from_set 
+    (add_set_cmd ("varsize-limit", class_support, var_uinteger,
+                 (char*) &varsize_limit,
+                 "Set maximum bytes in dynamic-sized object.",
+                 &setlist),
+     &showlist);
+  varsize_limit = 65536;
+
+  add_com ("begin", class_breakpoint, begin_command,
+          "Start the debugged program, stopping at the beginning of the\n\
+main program.  You may specify command-line arguments to give it, as for\n\
+the \"run\" command (q.v.).");
+}
+
+
+/* Create a fundamental Ada type using default reasonable for the current
+   target machine.
+
+   Some object/debugging file formats (DWARF version 1, COFF, etc) do not
+   define fundamental types such as "int" or "double".  Others (stabs or
+   DWARF version 2, etc) do define fundamental types.  For the formats which
+   don't provide fundamental types, gdb can create such types using this
+   function.
+
+   FIXME:  Some compilers distinguish explicitly signed integral types
+   (signed short, signed int, signed long) from "regular" integral types
+   (short, int, long) in the debugging information.  There is some dis-
+   agreement as to how useful this feature is.  In particular, gcc does
+   not support this.  Also, only some debugging formats allow the
+   distinction to be passed on to a debugger.  For now, we always just
+   use "short", "int", or "long" as the type name, for both the implicit
+   and explicitly signed types.  This also makes life easier for the
+   gdb test suite since we don't have to account for the differences
+   in output depending upon what the compiler and debugging format
+   support.  We will probably have to re-examine the issue when gdb
+   starts taking it's fundamental type information directly from the
+   debugging information supplied by the compiler.  fnf@cygnus.com */
+
+static struct type *
+ada_create_fundamental_type (objfile, typeid)
+     struct objfile *objfile;
+     int typeid;
+{
+  struct type *type = NULL;
+
+  switch (typeid)
+    {
+      default:
+       /* FIXME:  For now, if we are asked to produce a type not in this
+          language, create the equivalent of a C integer type with the
+          name "<?type?>".  When all the dust settles from the type
+          reconstruction work, this should probably become an error. */
+       type = init_type (TYPE_CODE_INT,
+                         TARGET_INT_BIT / TARGET_CHAR_BIT,
+                         0, "<?type?>", objfile);
+        warning ("internal error: no Ada fundamental type %d", typeid);
+       break;
+      case FT_VOID:
+       type = init_type (TYPE_CODE_VOID,
+                         TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+                         0, "void", objfile);
+       break;
+      case FT_CHAR:
+       type = init_type (TYPE_CODE_INT,
+                         TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+                         0, "character", objfile);
+       break;
+      case FT_SIGNED_CHAR:
+       type = init_type (TYPE_CODE_INT,
+                         TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+                         0, "signed char", objfile);
+       break;
+      case FT_UNSIGNED_CHAR:
+       type = init_type (TYPE_CODE_INT,
+                         TARGET_CHAR_BIT / TARGET_CHAR_BIT,
+                         TYPE_FLAG_UNSIGNED, "unsigned char", objfile);
+       break;
+      case FT_SHORT:
+       type = init_type (TYPE_CODE_INT,
+                         TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+                         0, "short_integer", objfile);
+       break;
+      case FT_SIGNED_SHORT:
+       type = init_type (TYPE_CODE_INT,
+                         TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+                         0, "short_integer", objfile); 
+       break;
+      case FT_UNSIGNED_SHORT:
+       type = init_type (TYPE_CODE_INT,
+                         TARGET_SHORT_BIT / TARGET_CHAR_BIT,
+                         TYPE_FLAG_UNSIGNED, "unsigned short", objfile);
+       break;
+      case FT_INTEGER:
+       type = init_type (TYPE_CODE_INT,
+                         TARGET_INT_BIT / TARGET_CHAR_BIT,
+                         0, "integer", objfile);
+       break;
+      case FT_SIGNED_INTEGER:
+       type = init_type (TYPE_CODE_INT,
+                         TARGET_INT_BIT / TARGET_CHAR_BIT,
+                         0, "integer", objfile); /* FIXME -fnf */
+       break;
+      case FT_UNSIGNED_INTEGER:
+       type = init_type (TYPE_CODE_INT,
+                         TARGET_INT_BIT / TARGET_CHAR_BIT,
+                         TYPE_FLAG_UNSIGNED, "unsigned int", objfile);
+       break;
+      case FT_LONG:
+       type = init_type (TYPE_CODE_INT,
+                         TARGET_LONG_BIT / TARGET_CHAR_BIT,
+                         0, "long_integer", objfile);
+       break;
+      case FT_SIGNED_LONG:
+       type = init_type (TYPE_CODE_INT,
+                         TARGET_LONG_BIT / TARGET_CHAR_BIT,
+                         0, "long_integer", objfile);
+       break;
+      case FT_UNSIGNED_LONG:
+       type = init_type (TYPE_CODE_INT,
+                         TARGET_LONG_BIT / TARGET_CHAR_BIT,
+                         TYPE_FLAG_UNSIGNED, "unsigned long", objfile);
+       break;
+      case FT_LONG_LONG:
+       type = init_type (TYPE_CODE_INT,
+                         TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+                         0, "long_long_integer", objfile);
+       break;
+      case FT_SIGNED_LONG_LONG:
+       type = init_type (TYPE_CODE_INT,
+                         TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+                         0, "long_long_integer", objfile);
+       break;
+      case FT_UNSIGNED_LONG_LONG:
+       type = init_type (TYPE_CODE_INT,
+                         TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
+                         TYPE_FLAG_UNSIGNED, "unsigned long long", objfile);
+       break;
+      case FT_FLOAT:
+       type = init_type (TYPE_CODE_FLT,
+                         TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
+                         0, "float", objfile);
+       break;
+      case FT_DBL_PREC_FLOAT:
+       type = init_type (TYPE_CODE_FLT,
+                         TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
+                         0, "long_float", objfile);
+       break;
+      case FT_EXT_PREC_FLOAT:
+       type = init_type (TYPE_CODE_FLT,
+                         TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
+                         0, "long_long_float", objfile);
+       break;
+      }
+  return (type);
+}
+
+void ada_dump_symtab (struct symtab* s)
+{
+  int i;
+  fprintf (stderr, "New symtab: [\n");
+  fprintf (stderr, "  Name: %s/%s;\n", 
+          s->dirname ? s->dirname : "?", 
+          s->filename ? s->filename : "?");
+  fprintf (stderr, "  Format: %s;\n", s->debugformat);
+  if (s->linetable != NULL)
+    {
+      fprintf (stderr, "  Line table (section %d):\n", s->block_line_section);
+      for (i = 0; i < s->linetable->nitems; i += 1)
+       {
+         struct linetable_entry* e = s->linetable->item + i;
+         fprintf (stderr, "    %4ld: %8lx\n", (long) e->line, (long) e->pc);
+       }
+    }
+  fprintf (stderr, "]\n");
+}
+
diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h
new file mode 100644 (file)
index 0000000..e5353f8
--- /dev/null
@@ -0,0 +1,365 @@
+/* Ada language support definitions for GDB, the GNU debugger.
+   Copyright 1992, 1997 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#if !defined (ADA_LANG_H)
+#define ADA_LANG_H 1
+
+#include "value.h"
+#include "gdbtypes.h"
+
+/* A macro to reorder the bytes of an address depending on the endiannes
+   of the target */
+#define EXTRACT_ADDRESS(x) ((void *) extract_address (&(x), sizeof (x)))
+/* A macro to reorder the bytes of an int depending on the endiannes
+   of the target */
+#define EXTRACT_INT(x) ((int) extract_signed_integer (&(x), sizeof (x)))
+
+/* Chain of cleanups for arguments of OP_UNRESOLVED_VALUE names.  Created in
+   yyparse and freed in ada_resolve. */
+extern struct cleanup* unresolved_names;
+
+/* Corresponding mangled/demangled names and opcodes for Ada user-definable 
+   operators. */
+struct ada_opname_map {
+  const char* mangled;
+  const char* demangled;
+  enum exp_opcode op;
+};
+
+/* Table of Ada operators in mangled and demangled forms. */
+/* Defined in ada-lang.c */
+extern const struct ada_opname_map ada_opname_table[];
+
+/* The maximum number of tasks known to the Ada runtime */
+extern const int MAX_NUMBER_OF_KNOWN_TASKS;
+
+/* Identifiers for Ada attributes that need special processing.  Be sure 
+   to update the table attribute_names in ada-lang.c whenever you change this.
+   */
+
+enum ada_attribute {
+  /* Invalid attribute for error checking. */
+  ATR_INVALID,
+
+  ATR_FIRST,
+  ATR_LAST,
+  ATR_LENGTH,
+  ATR_IMAGE,
+  ATR_IMG,
+  ATR_MAX,
+  ATR_MIN,
+  ATR_MODULUS,
+  ATR_POS,
+  ATR_SIZE,
+  ATR_TAG,
+  ATR_VAL,
+
+  /* Dummy last attribute. */
+  ATR_END
+};
+
+enum task_states {
+  Unactivated,
+  Runnable,
+  Terminated,
+  Activator_Sleep,
+  Acceptor_Sleep,
+  Entry_Caller_Sleep,
+  Async_Select_Sleep,
+  Delay_Sleep,
+  Master_Completion_Sleep,
+  Master_Phase_2_Sleep
+};
+
+extern char *ada_task_states[];
+
+typedef struct {
+  char *P_ARRAY;
+  int *P_BOUNDS;
+} fat_string;
+
+typedef struct entry_call {
+  void *self;
+} *entry_call_link;
+
+struct task_fields
+{
+  int entry_num;
+#if (defined (VXWORKS_TARGET) || !defined (i386)) \
+    && !(defined (VXWORKS_TARGET) && defined (M68K_TARGET))
+  int pad1;
+#endif
+  char state;
+#if (defined (VXWORKS_TARGET) && defined (M68K_TARGET))
+  char pad_8bits;
+#endif
+  void *parent;
+  int priority;
+  int current_priority;
+  fat_string image;
+  entry_call_link call;
+#if (defined (sun) && defined (__SVR4)) && !defined (VXWORKS_TARGET)
+  int pad2;
+  unsigned thread;
+  unsigned lwp;
+#else
+  void *thread;
+  void *lwp;
+#endif
+}
+#if (defined (VXWORKS_TARGET) && defined (M68K_TARGET))
+__attribute__ ((packed))
+#endif
+;
+
+struct task_entry
+{
+  void *task_id;
+  int task_num;
+  int known_tasks_index;
+  struct task_entry *next_task;
+  void *thread;
+  void *lwp;
+  int stack_per;
+};
+
+extern struct type* builtin_type_ada_int;
+extern struct type* builtin_type_ada_short;
+extern struct type* builtin_type_ada_long;
+extern struct type* builtin_type_ada_long_long;
+extern struct type* builtin_type_ada_char;
+extern struct type* builtin_type_ada_float;
+extern struct type* builtin_type_ada_double;
+extern struct type* builtin_type_ada_long_double;
+extern struct type* builtin_type_ada_natural;
+extern struct type* builtin_type_ada_positive;
+extern struct type* builtin_type_ada_system_address;
+
+/* Assuming V points to an array of S objects,  make sure that it contains at 
+   least M objects, updating V and S as necessary. */
+
+#define GROW_VECT(v, s, m)                                             \
+   if ((s) < (m)) grow_vect ((void**) &(v), &(s), (m), sizeof(*(v)));
+
+extern void grow_vect (void**, size_t*, size_t, int);
+
+extern int ada_parse (void);   /* Defined in ada-exp.y */
+
+extern void ada_error (char *);        /* Defined in ada-exp.y */
+
+                       /* Defined in ada-typeprint.c */ 
+extern void ada_print_type (struct type*, char*, struct ui_file*, int, int);
+
+extern int ada_val_print (struct type*, char*, int, CORE_ADDR, 
+                         struct ui_file*, int, int, int, enum val_prettyprint);
+
+extern int ada_value_print (struct value*, struct ui_file*, int, 
+                           enum val_prettyprint);
+
+                               /* Defined in ada-lang.c */
+
+extern struct value* value_from_contents_and_address (struct type*, char*, CORE_ADDR);
+
+extern void ada_emit_char (int, struct ui_file *, int, int);
+
+extern void ada_printchar (int, struct ui_file*);
+
+extern void ada_printstr (struct ui_file*, char *, unsigned int, int, int);
+
+extern void ada_convert_actuals (struct value*, int, struct value**, CORE_ADDR*);
+
+extern struct value* ada_value_subscript (struct value*, int, struct value**);
+
+extern struct type* ada_array_element_type (struct type*, int);
+
+extern int ada_array_arity (struct type*);
+
+struct type* ada_type_of_array (struct value*, int);
+
+extern struct value* ada_coerce_to_simple_array (struct value*);
+
+extern struct value* ada_coerce_to_simple_array_ptr (struct value*);
+
+extern int ada_is_simple_array (struct type*);
+
+extern int ada_is_array_descriptor (struct type*);
+
+extern int ada_is_bogus_array_descriptor (struct type*);
+
+extern struct type* ada_index_type (struct type*, int);
+
+extern struct value* ada_array_bound (struct value*, int, int);
+
+extern int ada_lookup_symbol_list (const char*, struct block*, namespace_enum,
+                                  struct symbol***, struct block***);
+
+extern char*  ada_fold_name (const char*);
+
+extern struct symbol* ada_lookup_symbol (const char*, struct block*, namespace_enum);
+
+extern struct minimal_symbol* ada_lookup_minimal_symbol (const char*);
+
+extern void ada_resolve (struct expression**, struct type*);
+
+extern int ada_resolve_function (struct symbol**, struct block**, int, 
+                                struct value**, int, const char*, struct type*);
+
+extern void ada_fill_in_ada_prototype (struct symbol*);
+
+extern int user_select_syms (struct symbol**, struct block**, int, int);
+
+extern int get_selections (int*, int, int, int, char*);
+
+extern char* ada_start_decode_line_1 (char*);
+
+extern struct symtabs_and_lines ada_finish_decode_line_1 (char**, struct symtab*, int, char***);
+
+extern int ada_scan_number (const char*, int, LONGEST*, int*);
+
+extern struct type* ada_parent_type (struct type*);
+
+extern int ada_is_ignored_field (struct type*, int);
+
+extern int ada_is_packed_array_type (struct type*);
+
+extern struct value* ada_value_primitive_packed_val (struct value*, char*, long, int,
+                                                int, struct type*);
+
+extern struct type* ada_coerce_to_simple_array_type (struct type*);
+
+extern int ada_is_character_type (struct type*);
+
+extern int ada_is_string_type (struct type*);
+
+extern int  ada_is_tagged_type (struct type*);
+
+extern struct type* ada_tag_type (struct value*);
+
+extern struct value* ada_value_tag (struct value*);
+
+extern int ada_is_parent_field (struct type*, int);
+
+extern int ada_is_wrapper_field (struct type*, int);
+
+extern int ada_is_variant_part (struct type*, int);
+
+extern struct type* ada_variant_discrim_type (struct type*, struct type*);
+
+extern int ada_is_others_clause (struct type*, int);
+
+extern int ada_in_variant (LONGEST, struct type*, int);
+
+extern char* ada_variant_discrim_name (struct type*);
+
+extern struct type* ada_lookup_struct_elt_type (struct type*, char*, int, int*);
+
+extern struct value* ada_value_struct_elt (struct value*, char*, char*);
+
+extern struct value* ada_search_struct_field (char*, struct value*, int, struct type*);
+
+extern int ada_is_aligner_type (struct type*);
+
+extern struct type* ada_aligned_type (struct type*);
+
+extern char* ada_aligned_value_addr (struct type*, char*);
+
+extern const char* ada_attribute_name (int);
+
+extern int ada_is_fixed_point_type (struct type*);
+
+extern DOUBLEST ada_delta (struct type*);
+
+extern DOUBLEST ada_fixed_to_float (struct type *, LONGEST);
+
+extern LONGEST ada_float_to_fixed (struct type*, DOUBLEST);
+
+extern int ada_is_vax_floating_type (struct type*);
+
+extern int ada_vax_float_type_suffix (struct type*);
+
+extern struct value* ada_vax_float_print_function (struct type*);
+
+extern struct type* ada_system_address_type (void);
+
+extern int  ada_which_variant_applies (struct type*, struct type*, char*);
+
+extern struct value* ada_to_fixed_value (struct type*, char*, CORE_ADDR, struct value*);
+
+extern struct type* ada_to_fixed_type (struct type*, char*, CORE_ADDR, struct value*);
+
+extern int ada_name_prefix_len (const char*);
+
+extern char* ada_type_name (struct type*);
+
+extern struct type* ada_find_parallel_type (struct type*, const char *suffix);
+
+extern LONGEST get_int_var_value (char*, char*, int* );
+
+extern struct type* ada_find_any_type (const char *name);
+
+extern int ada_prefer_type (struct type*, struct type*);
+
+extern struct type* ada_get_base_type (struct type*);
+
+extern struct type* ada_completed_type (struct type*);
+
+extern char*  ada_mangle (const char*);
+
+extern const char* ada_enum_name (const char*);
+
+extern int ada_is_modular_type (struct type*);
+
+extern LONGEST ada_modulus (struct type*);
+
+extern struct value* ada_value_ind (struct value*);
+
+extern void ada_print_scalar (struct type*, LONGEST, struct ui_file*);
+
+extern int ada_is_range_type_name (const char*);
+
+extern const char* ada_renaming_type (struct type*);
+
+extern int ada_is_object_renaming (struct symbol*);
+
+extern const char* ada_simple_renamed_entity (struct symbol*);
+
+extern char* ada_breakpoint_rewrite (char*, int*);
+
+/* Tasking-related: ada-tasks.c */
+
+extern int valid_task_id (int);
+
+extern int get_current_task (void); 
+
+extern void init_task_list (void);
+
+extern void* get_self_id (void);
+
+extern int get_current_task (void);
+
+extern int get_entry_number (void*);
+
+extern void ada_report_exception_break (struct breakpoint *);
+
+extern int ada_maybe_exception_partial_symbol (struct partial_symbol* sym);
+
+extern int ada_is_exception_sym (struct symbol* sym);
+
+
+#endif
diff --git a/gdb/ada-lex.c b/gdb/ada-lex.c
new file mode 100644 (file)
index 0000000..9538f76
--- /dev/null
@@ -0,0 +1,3174 @@
+/* A lexical scanner generated by flex */
+
+/* Scanner skeleton version:
+ * $Header$
+ * $FreeBSD: src/usr.bin/lex/flex.skl,v 1.4 1999/10/27 07:56:44 obrien Exp $
+ */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else  /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator).  This
+ * avoids problems with code like:
+ *
+ *     if ( condition_holds )
+ *             yyless( 5 );
+ *     else
+ *             do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+       do \
+               { \
+               /* Undo effects of setting up yytext. */ \
+               *yy_cp = yy_hold_char; \
+               YY_RESTORE_YY_MORE_OFFSET \
+               yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+               YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+               } \
+       while ( 0 )
+
+#define unput(c) yyunput( c, yytext_ptr )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+
+struct yy_buffer_state
+       {
+       FILE *yy_input_file;
+
+       char *yy_ch_buf;                /* input buffer */
+       char *yy_buf_pos;               /* current position in input buffer */
+
+       /* Size of input buffer in bytes, not including room for EOB
+        * characters.
+        */
+       yy_size_t yy_buf_size;
+
+       /* Number of characters read into yy_ch_buf, not including EOB
+        * characters.
+        */
+       int yy_n_chars;
+
+       /* Whether we "own" the buffer - i.e., we know we created it,
+        * and can realloc() it to grow it, and should free() it to
+        * delete it.
+        */
+       int yy_is_our_buffer;
+
+       /* Whether this is an "interactive" input source; if so, and
+        * if we're using stdio for input, then we want to use getc()
+        * instead of fread(), to make sure we stop fetching input after
+        * each newline.
+        */
+       int yy_is_interactive;
+
+       /* Whether we're considered to be at the beginning of a line.
+        * If so, '^' rules will be active on the next match, otherwise
+        * not.
+        */
+       int yy_at_bol;
+
+       /* Whether to try to fill the input buffer when we reach the
+        * end of it.
+        */
+       int yy_fill_buffer;
+
+       int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+       /* When an EOF's been seen but there's still some text to process
+        * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+        * shouldn't try reading from the input source any more.  We might
+        * still have a bunch of tokens to match, though, because of
+        * possible backing-up.
+        *
+        * When we actually see the EOF, we change the status to "new"
+        * (via yyrestart()), so that the user can continue scanning by
+        * just pointing yyin at a new input file.
+        */
+#define YY_BUFFER_EOF_PENDING 2
+       };
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars;         /* number of characters read into yy_ch_buf */
+
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1;                /* whether we need to initialize */
+static int yy_start = 0;       /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO(( FILE *input_file ));
+
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+static void yy_flex_free YY_PROTO(( void * ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+       { \
+       if ( ! yy_current_buffer ) \
+               yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+       yy_current_buffer->yy_is_interactive = is_interactive; \
+       }
+
+#define yy_set_bol(at_bol) \
+       { \
+       if ( ! yy_current_buffer ) \
+               yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+       yy_current_buffer->yy_at_bol = at_bol; \
+       }
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+
+#define YY_USES_REJECT
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+typedef int yy_state_type;
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+       yytext_ptr = yy_bp; \
+       yyleng = (int) (yy_cp - yy_bp); \
+       yy_hold_char = *yy_cp; \
+       *yy_cp = '\0'; \
+       yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 57
+#define YY_END_OF_BUFFER 58
+static yyconst short int yy_acclist[386] =
+    {   0,
+       58,   56,   57,    1,   56,   57,    1,   57,   15,   56,
+       57,   53,   56,   57,   41,   56,   57,   56,   57,   43,
+       56,   57,   44,   56,   57,   41,   56,   57,   42,   56,
+       57,   41,   56,   57,   41,   56,   57,   41,   56,   57,
+        4,   56,   57,    4,   56,   57,   41,   56,   57,   41,
+       56,   57,   41,   56,   57,   41,   56,   57,   50,   56,
+       57,   47,   56,   57,   47,   56,   57,   47,   56,   57,
+       47,   56,   57,   47,   56,   57,   47,   56,   57,   47,
+       56,   57,   47,   56,   57,   47,   56,   57,   47,   56,
+       57,    1,   56,   57,   56,   57,   16,   56,   57,   53,
+
+       56,   57,   41,   56,   57,   56,   57,   43,   56,   57,
+       44,   56,   57,   41,   56,   57,   42,   56,   57,   41,
+       56,   57,   41,   56,   57,   41,   56,   57,    4,   56,
+       57,    4,   56,   57,   41,   56,   57,   41,   56,   57,
+       41,   56,   57,   41,   56,   57,   50,   56,   57,   41,
+       56,   57,   47,   56,   57,   47,   56,   57,   47,   56,
+       57,   47,   56,   57,   47,   56,   57,   47,   56,   57,
+       47,   56,   57,   47,   56,   57,   47,   56,   57,   47,
+       56,   57,   56,   57,   40,   56,   57,   51,   55,   54,
+       55,   55,   35,    2,   34,   46,   46,   37,    4,   36,
+
+       38,   33,   39,   47,   47,   47,   47,   47,   19,   47,
+       23,   47,   47,   47,   47,   47,   28,   47,   47,   47,
+       47,   16,   51,   55,   54,   55,   55,   16,   35,    2,
+       34,   46,   46,   37,    4,   36,   38,   33,   39,   16,
+       47,   47,   47,   47,   47,   19,   47,   23,   47,   47,
+       47,   47,   47,   28,   47,   47,   47,   47,16398,   52,
+       55,   12,   12,   32,    2,   46,   46,    9,    3,    7,
+       47,   47,   49,   20,   47,   21,   47,   47,   24,   47,
+       25,   47,   26,   47,   47,   29,   47,   47,   31,   47,
+       52,   55,   16,   32,    2,    2,   16,    2,   46,   46,
+
+        9,    3,    7,   47,   16,   47,   49,   20,   47,   21,
+       47,   47,   24,   47,   25,   47,   26,   47,   47,   29,
+       47,   47,   31,   47, 8206,   46,   45,   46,    6,    9,
+        3,   47,   22,   47,   27,   47,   30,   47,    2,   16,
+       46,   45,   46,    6,    9,    3,   47,   22,   47,   27,
+       47,   30,   47,   48,   47,   48,    2,    2,   18,   47,
+        5,   11,    8,   18,    2,    2,    5,   11,    8,   17,
+        5,    8,   17,    2,   18,    2,    5,    8,   13,    2,
+       17,   10,   10,   10,   10
+    } ;
+
+static yyconst short int yy_accept[364] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    2,    4,    7,
+        9,   12,   15,   18,   20,   23,   26,   29,   32,   35,
+       38,   41,   44,   47,   50,   53,   56,   59,   62,   65,
+       68,   71,   74,   77,   80,   83,   86,   89,   92,   95,
+       97,  100,  103,  106,  108,  111,  114,  117,  120,  123,
+      126,  129,  132,  135,  138,  141,  144,  147,  150,  153,
+      156,  159,  162,  165,  168,  171,  174,  177,  180,  183,
+      185,  188,  188,  188,  188,  188,  188,  188,  188,  188,
+      188,  188,  188,  190,  192,  193,  193,  193,  193,  193,
+      193,  193,  193,  194,  195,  195,  196,  196,  197,  198,
+
+      199,  199,  199,  200,  200,  200,  201,  202,  202,  203,
+      204,  204,  204,  205,  205,  206,  206,  207,  208,  209,
+      211,  213,  214,  215,  216,  217,  219,  220,  221,  222,
+      222,  223,  223,  225,  227,  228,  228,  228,  229,  229,
+      229,  230,  231,  231,  232,  232,  233,  234,  235,  235,
+      235,  236,  236,  236,  237,  238,  238,  239,  240,  241,
+      241,  242,  242,  243,  243,  244,  245,  246,  248,  250,
+      251,  252,  253,  254,  256,  257,  258,  259,  259,  260,
+      260,  260,  260,  260,  260,  260,  262,  262,  263,  264,
+      264,  265,  266,  266,  267,  268,  268,  269,  269,  270,
+
+      271,  271,  272,  272,  272,  272,  273,  274,  276,  278,
+      279,  281,  283,  285,  286,  288,  289,  291,  293,  293,
+      294,  295,  296,  298,  299,  299,  300,  301,  301,  302,
+      302,  303,  304,  304,  305,  305,  305,  305,  306,  306,
+      307,  308,  310,  312,  313,  315,  317,  319,  320,  322,
+      323,  325,  325,  326,  326,  326,  326,  326,  327,  329,
+      330,  330,  330,  331,  331,  332,  332,  332,  332,  332,
+      332,  332,  332,  332,  332,  332,  332,  332,  333,  335,
+      337,  339,  339,  339,  339,  339,  341,  341,  342,  344,
+      345,  345,  345,  346,  346,  347,  347,  347,  347,  348,
+
+      350,  352,  354,  355,  355,  355,  355,  355,  356,  356,
+      356,  356,  356,  356,  356,  356,  357,  357,  357,  358,
+      359,  359,  359,  359,  360,  360,  360,  361,  361,  361,
+      362,  363,  363,  364,  365,  365,  366,  367,  367,  368,
+      369,  369,  370,  371,  371,  372,  372,  373,  374,  376,
+      377,  378,  378,  379,  380,  380,  382,  382,  383,  384,
+      385,  386,  386
+    } ;
+
+static yyconst int yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    4,    5,    6,    7,    8,    5,    9,   10,   11,
+       12,   13,   14,   15,   16,   17,   18,   19,   20,   20,
+       20,   20,   20,   20,   20,   20,   20,   21,   22,   23,
+       24,   25,    5,   26,   30,   31,   32,   33,   34,   35,
+       36,   37,   38,   36,   36,   39,   40,   41,   42,   36,
+       36,   43,   44,   45,   46,   36,   47,   48,   36,   36,
+       27,    5,   28,    5,   29,    5,   30,   31,   32,   33,
+
+       34,   35,   36,   37,   38,   36,   36,   39,   40,   41,
+       42,   36,   36,   43,   44,   45,   46,   36,   47,   48,
+       36,   36,   26,   22,   26,    5,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst int yy_meta[49] =
+    {   0,
+        1,    2,    3,    4,    5,    6,    7,    8,    5,    9,
+        5,    5,    5,    5,    5,    5,   10,    5,   11,   11,
+        9,    5,   12,   13,   14,    5,    5,    5,   15,   16,
+       16,   16,   16,   16,   16,   17,   17,   17,   17,   17,
+       17,   17,   17,   17,   17,   17,   17,   17
+    } ;
+
+static yyconst short int yy_base[385] =
+    {   0,
+        0,    0,   48,    0,   91,   92, 1405, 1771, 1771, 1771,
+       94,   96, 1771,  142, 1771, 1771, 1391, 1771, 1387,  189,
+     1378,  188,  194, 1377, 1376, 1374, 1361, 1771,  222,  242,
+       82,   91,   89,  196,   68,  163,  179,   97,  100,  194,
+        0,  280,  223,  328,  227,  228,  234,  229,  235,  375,
+      242,  418, 1335,  243,  463,  247,  251,  252,  254,  510,
+      168, 1343,  161, 1333,  234, 1331, 1336, 1323, 1316,    0,
+      558, 1340,  127,  258,  420,  422,  398, 1299, 1285, 1258,
+     1266, 1257,  411,  413,    0,  605, 1288, 1287, 1286, 1285,
+      119,  644, 1771,    0,  691, 1771,    0,    0, 1255, 1771,
+
+        0,  421,  690,  429,    0, 1771, 1771, 1244, 1771, 1771,
+      608,  696, 1771,  699,  419, 1247,  420,  422,  582,  583,
+      586,  587,  624,  625,  591,  590,  627,  628,  684,  430,
+     1771,  705,  653, 1256,  710, 1252,  731,    0, 1254,  750,
+      710,  798, 1222,  717,  802,  832, 1199,  720,  875,  730,
+     1189,  732,  892,  733,  795,  924,  796,  797, 1230,  971,
+      800,  997,    0,  876, 1183, 1191, 1176,    0,    0, 1174,
+     1151, 1150, 1097,    0, 1095, 1100, 1089, 1096,  805, 1043,
+     1047, 1043, 1023, 1016, 1010,  439,  808,  883, 1771, 1027,
+     1041,    0,  971,    0,  952,  736,  864,  614,  799,    0,
+
+      965,  976, 1046, 1061,    0, 1061, 1771,  714,  717,  858,
+      774,  789,  859, 1042,  860,  953,  954, 1047, 1086, 1108,
+        0, 1092,    0, 1094, 1140,    0,  950, 1182, 1091, 1110,
+     1199, 1210,    0, 1244,  981,    0,    0,    0, 1243, 1273,
+      890,    0,    0,  949,    0,    0,    0,  943,    0,  935,
+        0, 1120, 1771, 1188,  900, 1303,  895, 1771,    0,  882,
+        0, 1098, 1174,  440, 1177,  909,  421, 1048, 1093, 1102,
+     1169,  846,  818,  814,  822,  779,  792, 1249, 1190, 1191,
+     1192, 1322, 1228,  750, 1331, 1361,    0, 1106,    0, 1229,
+     1378,    0, 1325, 1326, 1349,  726,  725, 1410,    0,    0,
+
+        0,    0, 1771,  722,  839,  713,  644, 1369,  668,  671,
+      663,  615,  617,  576,  591, 1198,  540,  459,  456, 1440,
+     1462, 1483, 1458, 1771,  414,    0, 1517,  249,  794, 1238,
+      237,  258, 1310,    0,  203,  190,  209, 1460, 1477, 1350,
+        0, 1480, 1771,  131, 1328,  726, 1472,    0,    0,   86,
+     1516, 1523, 1522, 1385,  835,    0, 1505, 1511, 1527, 1533,
+     1549, 1771, 1571, 1587, 1592, 1608, 1622, 1639, 1642, 1649,
+       89,  187, 1656, 1672, 1689, 1701, 1707, 1718, 1720, 1736,
+      902,  903, 1743, 1754
+    } ;
+
+static yyconst short int yy_def[385] =
+    {   0,
+      362,    1,  362,    3,    1,    1,  362,  362,  362,  362,
+      362,  363,  362,  362,  362,  362,  362,  362,  362,  364,
+      362,  362,  362,  362,  365,  362,  362,  362,  366,  366,
+       30,   30,   30,   30,   30,   30,   30,   30,  367,  367,
+       11,  362,  367,  362,  367,  367,  367,  367,  367,  362,
+      367,  367,   52,  367,  362,  367,  367,  367,  367,  362,
+       60,   60,   60,   60,   60,   60,   60,   60,   60,   11,
+      362,  362,  362,  362,  362,  362,  362,  362,  362,  362,
+      362,  362,  363,  363,  363,   71,   71,   71,   86,  362,
+       86,   86,  362,  368,  364,  362,  369,  370,  370,  362,
+
+      371,  362,  362,  362,  372,  362,  362,  373,  362,  362,
+      362,  362,  362,  374,   30,  362,   30,   30,   30,   30,
+       30,   30,   30,   30,   30,   30,   30,   30,   30,  367,
+      362,  367,   42,   42,   42,   44,   44,   86,  137,  137,
+      367,  375,   50,  367,   55,  145,  146,  367,  367,  367,
+       52,  367,  149,  367,  367,  362,  367,  367,  376,  367,
+      367,  362,   60,  367,   60,   60,   60,   60,   60,   60,
+       60,   60,   60,   60,   60,   60,   60,   92,  362,  362,
+      362,  362,  362,  362,  362,  363,  362,  362,  362,   86,
+       92,  368,  377,  370,  370,  378,  362,  362,  362,  372,
+
+      373,  362,  374,  362,  379,  380,  362,   30,   30,   30,
+       30,   30,   30,   30,   30,   30,   30,   42,  367,   86,
+      140,  375,  368,  375,  362,  146,  146,  149,  367,  367,
+      367,  149,  156,  367,  362,  381,  162,  204,  145,   60,
+      367,   60,   60,   60,   60,   60,   60,   60,   60,   60,
+       60,  362,  362,  362,  362,   86,  377,  362,  370,  362,
+      382,  378,  362,  362,  362,  362,  362,  362,  362,  362,
+      362,  362,  362,  362,  362,  362,  383,  380,   30,   30,
+       30,  367,  367,   86,   86,  368,  225,  367,  146,  367,
+      149,  228,  367,  367,  367,  362,  362,  362,  240,   60,
+
+       60,   60,  362,   86,  362,  384,  362,  362,  362,  362,
+      362,  362,  362,  362,  383,  367,   86,   86,  368,  368,
+      367,  149,  367,  362,  362,  298,  367,   86,  362,  362,
+      362,  384,  362,   86,   86,  368,  368,  367,  367,  367,
+      322,  367,  362,   86,  362,  362,  362,   86,  368,  368,
+      367,  367,  367,  362,  362,  368,  367,  362,  367,  362,
+      367,    0,  362,  362,  362,  362,  362,  362,  362,  362,
+      362,  362,  362,  362,  362,  362,  362,  362,  362,  362,
+      362,  362,  362,  362
+    } ;
+
+static yyconst short int yy_nxt[1820] =
+    {   0,
+        8,    9,   10,    9,    8,   11,    8,   12,   13,   14,
+       15,   16,   17,   13,   18,   19,   20,   21,   22,   23,
+       24,   13,   25,   26,   27,   28,   13,   13,   29,   30,
+       29,   29,   29,   31,   29,   29,   29,   32,   29,   33,
+       34,   35,   36,   29,   37,   29,   29,   38,    8,    9,
+       10,   39,   40,   41,   40,   42,   43,   44,   45,   46,
+       47,   43,   48,   49,   50,   51,   52,   53,   54,   43,
+       55,   56,   57,   58,   59,   43,   60,   61,   60,   60,
+       60,   62,   60,   60,   60,   63,   60,   64,   65,   66,
+       67,   60,   68,   60,   60,   69,   70,   70,  115,  196,
+
+       71,   71,   72,   83,  196,  131,   73,   72,  115,   72,
+      126,   74,  115,  356,   84,   84,   75,   72,   76,  115,
+      119,  115,  115,   77,  190,  120,  132,  115,  188,  115,
+      122,  121,  179,   78,   79,   80,   81,  115,  129,   72,
+      354,   82,   86,   87,   87,   88,   89,   89,   89,   89,
+       89,   90,   89,   89,   89,   89,   89,   89,   89,   89,
+       89,   89,   89,   89,   89,   89,   89,   89,   91,   89,
+       89,   92,   92,   92,   92,   92,   92,   92,   92,   92,
+       92,   92,   92,   92,   92,   92,   92,   92,   92,   92,
+       95,   95,   95,  115,  101,  168,  127,  200,  165,  131,
+
+      101,  169,  200,  115,  102,   96,  103,  103,  166,  115,
+      102,   97,  103,  103,  350,  128,  103,  349,   99,  115,
+      132,  104,  103,  111,  111,  112,  115,  104,  131,  123,
+      348,  113,  131,  131,  131,  105,  115,  124,  114,  131,
+      131,  125,  116,  111,  111,  112,  141,  131,  131,  132,
+      142,  113,  131,  132,  132,  132,  131,  131,  114,  159,
+      132,  132,  116,  179,  331,  148,  154,  171,  132,  132,
+      346,  157,  117,  132,  158,  172,  344,  132,  132,  173,
+      132,   72,  118,  130,  130,  131,  130,  133,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  134,  134,
+
+      130,  130,  130,  130,  130,  130,  132,  130,  135,  135,
+      135,  135,  135,  135,  135,  135,  135,  135,  135,  135,
+      135,  135,  135,  135,  135,  135,  135,  135,   86,   87,
+       87,  136,  137,  138,  137,  137,  137,  130,  137,  137,
+      137,  137,  137,  137,  137,  137,  137,  137,  137,  137,
+      137,  137,  137,  137,  139,  137,  137,  140,  140,  140,
+      140,  140,  140,  140,  140,  140,  140,  140,  140,  140,
+      140,  140,  140,  140,  140,  140,   95,   95,  143,  130,
+      131,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  144,  130,  130,  130,  130,  130,  145,  130,  130,
+
+      130,  132,  130,  146,  147,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  131,  149,  179,  308,  179,  180,  186,
+      186,   84,   84,  266,  150,  131,  151,  151,  181,  197,
+      197,  343,  198,   72,  132,   72,  151,  199,  199,  115,
+      115,  152,  115,  307,  209,  307,  132,  186,  186,  115,
+      115,  336,  115,  208,  335,  153,  130,  130,  131,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  155,  130,  130,  132,
+      130,  156,  156,  156,  156,  156,  156,  156,  156,  156,
+
+      156,  156,  156,  156,  156,  156,  156,  156,  156,  156,
+      156,  111,  111,  160,  130,  131,  130,  130,  130,  161,
+      130,  130,  130,  130,  130,  130,  162,  130,  163,  163,
+      164,  130,  130,  130,  130,  130,  132,  130,  163,  163,
+      163,  163,  163,  163,  163,  163,  163,  163,  163,  163,
+      163,  163,  163,  163,  163,  163,  163,  163,   86,   87,
+       87,   87,   86,   86,   86,   86,   86,  334,   86,   86,
+       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
+       86,   86,   86,   86,   86,   86,   86,  178,  178,  178,
+      178,  178,  178,  178,  178,  178,  178,  178,  178,  178,
+
+      178,  178,  178,  178,  178,  178,   86,   86,   86,  111,
+      111,  111,  115,  115,  187,  308,  115,  115,  266,  211,
+      115,  115,  115,  115,  114,  210,  115,  115,  116,  214,
+      115,  115,  199,  199,   86,   86,   86,   86,   86,   86,
+       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
+       86,   86,   86,  188,  115,  115,  266,  115,  115,  266,
+      135,  216,  333,  333,  115,  115,  215,  115,  115,  213,
+      212,  218,  218,  191,  191,  191,  191,  191,  191,  191,
+      191,  191,  191,  191,  191,  191,  191,  191,  191,  191,
+      191,  191,   95,   95,   95,  266,  101,  111,  111,  112,
+
+      203,  203,  203,  266,  204,  113,  102,  362,  103,  103,
+      159,  266,  114,   97,  115,  131,  116,  135,  103,  331,
+       99,  205,  131,  104,  115,  131,  217,  328,  135,  135,
+      325,  132,   86,   86,  137,  131,  132,  131,  131,  355,
+      219,  355,  260,  132,  115,  230,  132,  115,  229,  229,
+      231,  231,  261,  324,  115,  317,  132,  115,  132,  132,
+      137,  137,  137,  137,  137,  137,  137,  137,  137,  137,
+      137,  137,  137,  137,  137,  137,  137,  137,  137,  221,
+      221,  221,  221,  221,  221,  221,  221,  221,  221,  221,
+      221,  221,  221,  221,  221,  221,  221,  221,  192,  192,
+
+      131,  131,  131,  223,  115,  131,  252,  252,  252,  254,
+      254,  254,  330,  330,  115,  253,  308,  265,  265,  115,
+      314,  132,  132,  132,  224,  130,  132,  265,  255,  115,
+      225,  225,  225,  225,  225,  225,  225,  225,  225,  225,
+      225,  225,  225,  225,  225,  225,  225,  225,  225,  225,
+      226,  226,  329,  358,  358,  313,  266,  330,  330,  312,
+      226,  226,  226,  226,  226,  226,  226,  226,  226,  226,
+      226,  226,  226,  226,  226,  226,  226,  226,  226,  226,
+      131,  131,  263,  263,  254,  254,  254,  311,  115,  115,
+      115,  279,  263,  228,  228,  131,  241,  264,  115,  115,
+
+      115,  132,  132,  255,  228,  228,  228,  228,  228,  228,
+      232,  232,  297,  306,  308,  305,  132,  297,  306,  258,
+      303,  232,  232,  232,  232,  232,  232,  130,  130,  131,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  233,  233,  130,  130,  130,  130,  234,  130,
+      132,  130,  233,  233,  233,  233,  233,  233,  233,  233,
+      233,  233,  233,  233,  233,  233,  233,  233,  233,  233,
+      233,  233,  111,  111,  160,  302,  131,  111,  111,  112,
+      161,  301,  300,  115,  115,  113,  296,  162,  289,  202,
+      259,  164,  114,  281,  115,  258,  116,  132,  203,  203,
+
+      237,  130,  238,  130,  130,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  239,
+      130,  130,  130,  132,  130,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  256,  256,  203,  203,  203,
+      187,  204,   72,  308,  135,   72,  256,  256,  256,  256,
+      256,  256,  111,  111,  112,  218,  218,   72,  205,  266,
+      113,  266,  115,  267,  266,   72,  266,  114,  268,   72,
+      280,  116,  115,  269,  266,  270,   72,  254,  254,  282,
+      271,  131,  192,  192,  192,  192,  131,  223,  308,  286,
+
+      272,  273,  274,  275,  260,  187,  283,  308,  276,  293,
+      293,  131,  132,  284,  261,  131,  266,  132,  224,  293,
+      224,  252,  252,  252,  294,  266,  285,  285,  231,  231,
+      253,  251,  132,  250,  249,  248,  132,  285,  285,  285,
+      285,  285,  285,  130,  130,  131,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  287,  287,
+      130,  130,  130,  130,  288,  130,  132,  130,  287,  287,
+      287,  287,  287,  287,  287,  287,  287,  287,  287,  287,
+      287,  287,  287,  287,  287,  287,  287,  287,  290,  254,
+      254,  254,  263,  263,  247,  265,  265,  246,  291,  309,
+
+      292,  292,  263,  131,  131,  265,  245,  264,  255,  310,
+      292,  292,  292,  292,  292,  292,  292,  295,  295,  244,
+      115,  115,  115,  243,  132,  132,  242,  295,  232,  232,
+      115,  115,  115,  131,  131,  235,  130,  227,  130,  232,
+      232,  232,  232,  232,  232,  111,  111,  160,  316,  131,
+      111,  111,  112,  161,  132,  132,  345,  345,  113,  220,
+      162,  219,  321,  135,  164,  114,  345,  207,  202,  116,
+      132,  298,  298,  298,  298,  298,  298,  298,  298,  298,
+      298,  298,  298,  298,  298,  298,  298,  298,  298,  298,
+      298,  299,  299,  195,  189,  188,  188,  187,  185,  184,
+
+       72,  299,  299,  299,  299,  299,  299,  299,  299,  299,
+      299,  299,  299,  299,  299,  299,  299,  299,  299,  299,
+      299,  304,  304,  254,  254,  282,  183,  131,  347,  347,
+      131,  131,  304,  304,  304,  304,  304,  304,  347,  323,
+      182,  323,  283,  293,  293,  179,  345,  345,  132,  318,
+      318,  132,  132,  293,  131,  131,  345,  177,  294,  176,
+      318,  318,  318,  318,  318,  318,  319,  295,  295,  175,
+      111,  111,  112,  174,  170,  132,  132,  295,  113,  320,
+      320,  167,  130,  352,  110,  114,  254,  254,  254,  116,
+      320,  320,  320,  320,  320,  320,  322,  322,  109,  107,
+
+      106,  100,   94,   93,  362,  255,  362,  322,  322,  322,
+      322,  322,  322,  130,  130,  131,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  326,  326,
+      130,  130,  130,  130,  327,  130,  132,  130,  326,  326,
+      326,  326,  326,  326,  326,  326,  326,  326,  326,  326,
+      326,  326,  326,  326,  326,  326,  326,  326,  337,  337,
+      362,  362,  362,  131,  362,  131,  362,  131,  362,  337,
+      337,  337,  337,  337,  337,  338,  342,  342,  339,  339,
+      339,  339,  131,  362,  132,  131,  132,  362,  132,  340,
+      347,  347,  362,  362,  362,  351,  351,  362,  353,  353,
+
+      347,  341,  341,  132,  362,  351,  132,  362,  353,  362,
+      131,  341,  341,  341,  341,  341,  341,  341,  111,  111,
+      160,  131,  131,  359,  359,  362,  161,  131,  131,  360,
+      360,  132,  131,  162,  351,  351,  357,  164,  357,  360,
+      353,  353,  132,  132,  351,  361,  361,  362,  132,  132,
+      353,  360,  360,  132,  131,  361,  362,  362,  362,  362,
+      362,  360,  362,  362,  362,  362,  362,  361,  361,  362,
+      362,  362,  362,  362,  362,  132,  362,  361,   85,  362,
+      362,   85,  362,  362,  362,   85,   85,   85,   98,   98,
+       98,  362,  362,  362,  362,  362,   98,  362,   98,  362,
+
+      362,   98,   98,   98,  108,  362,  108,  108,  108,  115,
+      115,  115,  362,  362,  362,  362,  115,  115,  115,  362,
+      362,  362,  115,  115,  115,  130,  130,  130,  130,  130,
+      130,  130,  130,  130,  130,  130,  130,  130,  130,  192,
+      192,  362,  192,  192,  192,  192,  192,  192,  192,  192,
+      192,  192,  192,  192,  192,  192,  193,  193,  193,  194,
+      362,  362,  362,  194,  194,  194,  201,  362,  362,  201,
+      201,  201,  201,  206,  206,  206,  362,  206,  362,  362,
+      362,  362,  362,  206,  362,  362,  206,  206,  206,  222,
+      222,  362,  222,  222,  222,  222,  222,  222,  222,  222,
+
+      222,  222,  222,  222,  222,  222,  236,  362,  362,  362,
+      362,  236,  362,  362,  362,  362,  236,  257,  362,  362,
+      257,  257,  257,  257,  262,  362,  362,  262,  262,  362,
+      362,  362,  262,  262,  277,  277,  277,  278,  278,  278,
+      362,  362,  362,  362,  278,  278,  278,  362,  362,  362,
+      278,  278,  278,  315,  362,  362,  315,  315,  315,  315,
+      332,  362,  362,  362,  332,  362,  362,  362,  332,  332,
+        7,  362,  362,  362,  362,  362,  362,  362,  362,  362,
+      362,  362,  362,  362,  362,  362,  362,  362,  362,  362,
+      362,  362,  362,  362,  362,  362,  362,  362,  362,  362,
+
+      362,  362,  362,  362,  362,  362,  362,  362,  362,  362,
+      362,  362,  362,  362,  362,  362,  362,  362,  362
+    } ;
+
+static yyconst short int yy_chk[1820] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
+        3,    3,    3,    3,    3,    3,    5,    6,   35,  371,
+
+        5,    6,   11,   12,  371,   39,   11,   11,   35,   11,
+       35,   11,   31,  350,   12,   12,   11,   11,   11,   33,
+       31,   32,   31,   11,   91,   32,   39,   38,   91,   33,
+       33,   32,   73,   11,   11,   11,   11,   38,   38,   73,
+      344,   11,   14,   14,   14,   14,   14,   14,   14,   14,
+       14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
+       14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
+       14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
+       14,   14,   14,   14,   14,   14,   14,   14,   14,   14,
+       20,   20,   20,   36,   22,   63,   36,  372,   61,   40,
+
+       23,   63,  372,   36,   22,   20,   22,   22,   61,   37,
+       23,   20,   23,   23,  337,   37,   22,  336,   20,   37,
+       40,   22,   23,   29,   29,   29,   34,   23,   43,   34,
+      335,   29,   45,   46,   48,   22,   34,   34,   29,   47,
+       49,   34,   29,   30,   30,   30,   47,   51,   54,   43,
+       49,   30,   56,   45,   46,   48,   57,   58,   30,   59,
+       47,   49,   30,   74,  332,   51,   54,   65,   51,   54,
+      331,   56,   30,   56,   57,   65,  328,   57,   58,   65,
+       59,   74,   30,   42,   42,   42,   42,   42,   42,   42,
+       42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+
+       42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+       42,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+       42,   42,   42,   42,   42,   42,   42,   42,   44,   44,
+       44,   44,   44,   44,   44,   44,   44,   44,   44,   44,
+       44,   44,   44,   44,   44,   44,   44,   44,   44,   44,
+       44,   44,   44,   44,   44,   44,   44,   44,   44,   44,
+       44,   44,   44,   44,   44,   44,   44,   44,   44,   44,
+       44,   44,   44,   44,   44,   44,   50,   50,   50,   50,
+       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
+       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
+
+       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
+       50,   50,   50,   50,   50,   50,   50,   50,   50,   50,
+       50,   50,   50,   52,   52,   75,  267,   76,   77,   83,
+       83,   84,   84,  267,   52,  130,   52,   52,   77,  102,
+      102,  325,  104,   75,   52,   76,   52,  104,  104,  115,
+      117,   52,  118,  264,  118,  264,  130,  186,  186,  115,
+      117,  319,  118,  117,  318,   52,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+
+       55,   55,   55,   55,   55,   55,   55,   55,   55,   55,
+       55,   60,   60,   60,   60,   60,   60,   60,   60,   60,
+       60,   60,   60,   60,   60,   60,   60,   60,   60,   60,
+       60,   60,   60,   60,   60,   60,   60,   60,   60,   60,
+       60,   60,   60,   60,   60,   60,   60,   60,   60,   60,
+       60,   60,   60,   60,   60,   60,   60,   60,   71,   71,
+       71,   71,   71,   71,   71,   71,   71,  317,   71,   71,
+       71,   71,   71,   71,   71,   71,   71,   71,   71,   71,
+       71,   71,   71,   71,   71,   71,   71,   71,   71,   71,
+       71,   71,   71,   71,   71,   71,   71,   71,   71,   71,
+
+       71,   71,   71,   71,   71,   71,   86,   86,   86,  111,
+      111,  111,  119,  120,   86,  315,  121,  122,  314,  122,
+      126,  125,  119,  120,  111,  119,  121,  122,  111,  125,
+      126,  125,  198,  198,   86,   86,   86,   86,   86,   86,
+       86,   86,   86,   86,   86,   86,   86,   86,   86,   86,
+       86,   86,   86,   92,  123,  124,  313,  127,  128,  312,
+      133,  128,  307,  307,  123,  124,  127,  127,  128,  124,
+      123,  133,  133,   92,   92,   92,   92,   92,   92,   92,
+       92,   92,   92,   92,   92,   92,   92,   92,   92,   92,
+       92,   92,   95,   95,   95,  311,  103,  112,  112,  112,
+
+      114,  114,  114,  310,  114,  112,  103,   95,  103,  103,
+      132,  309,  112,   95,  129,  141,  112,  135,  103,  306,
+       95,  114,  144,  103,  129,  148,  129,  304,  135,  135,
+      297,  132,  137,  137,  137,  150,  141,  152,  154,  346,
+      137,  346,  196,  144,  208,  152,  148,  209,  150,  150,
+      152,  152,  196,  296,  208,  284,  150,  209,  152,  154,
+      137,  137,  137,  137,  137,  137,  137,  137,  137,  137,
+      137,  137,  137,  137,  137,  137,  137,  137,  137,  140,
+      140,  140,  140,  140,  140,  140,  140,  140,  140,  140,
+      140,  140,  140,  140,  140,  140,  140,  140,  142,  142,
+
+      155,  157,  158,  142,  211,  161,  179,  179,  179,  187,
+      187,  187,  329,  329,  211,  179,  277,  199,  199,  212,
+      276,  155,  157,  158,  142,  145,  161,  199,  187,  212,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      145,  145,  145,  145,  145,  145,  145,  145,  145,  145,
+      146,  146,  305,  355,  355,  275,  274,  305,  305,  273,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      146,  146,  146,  146,  146,  146,  146,  146,  146,  146,
+      149,  164,  197,  197,  188,  188,  188,  272,  210,  213,
+      215,  210,  197,  149,  149,  241,  164,  197,  210,  213,
+
+      215,  149,  164,  188,  149,  149,  149,  149,  149,  149,
+      153,  153,  381,  382,  266,  260,  241,  381,  382,  257,
+      255,  153,  153,  153,  153,  153,  153,  156,  156,  156,
+      156,  156,  156,  156,  156,  156,  156,  156,  156,  156,
+      156,  156,  156,  156,  156,  156,  156,  156,  156,  156,
+      156,  156,  156,  156,  156,  156,  156,  156,  156,  156,
+      156,  156,  156,  156,  156,  156,  156,  156,  156,  156,
+      156,  156,  160,  160,  160,  250,  160,  202,  202,  202,
+      160,  248,  244,  216,  217,  202,  235,  160,  227,  201,
+      195,  160,  202,  216,  217,  193,  202,  160,  162,  162,
+
+      162,  162,  162,  162,  162,  162,  162,  162,  162,  162,
+      162,  162,  162,  162,  162,  162,  162,  162,  162,  162,
+      162,  162,  162,  162,  162,  162,  162,  162,  162,  162,
+      162,  162,  162,  162,  162,  162,  162,  162,  162,  162,
+      162,  162,  162,  162,  162,  190,  190,  203,  203,  203,
+      191,  203,  185,  268,  218,  184,  190,  190,  190,  190,
+      190,  190,  206,  206,  206,  218,  218,  183,  203,  204,
+      206,  268,  214,  204,  204,  182,  204,  206,  204,  181,
+      214,  206,  214,  204,  204,  204,  180,  219,  219,  219,
+      204,  219,  222,  222,  224,  224,  229,  222,  269,  224,
+
+      204,  204,  204,  204,  262,  178,  219,  270,  204,  229,
+      229,  288,  219,  220,  262,  230,  269,  229,  222,  229,
+      224,  252,  252,  252,  229,  270,  220,  220,  230,  230,
+      252,  177,  288,  176,  175,  173,  230,  220,  220,  220,
+      220,  220,  220,  225,  225,  225,  225,  225,  225,  225,
+      225,  225,  225,  225,  225,  225,  225,  225,  225,  225,
+      225,  225,  225,  225,  225,  225,  225,  225,  225,  225,
+      225,  225,  225,  225,  225,  225,  225,  225,  225,  225,
+      225,  225,  225,  225,  225,  225,  225,  225,  228,  254,
+      254,  254,  263,  263,  172,  265,  265,  171,  228,  271,
+
+      228,  228,  263,  316,  231,  265,  170,  263,  254,  271,
+      228,  228,  228,  228,  228,  228,  228,  231,  231,  167,
+      279,  280,  281,  166,  316,  231,  165,  231,  232,  232,
+      279,  280,  281,  283,  290,  159,  151,  147,  143,  232,
+      232,  232,  232,  232,  232,  234,  234,  234,  283,  234,
+      278,  278,  278,  234,  283,  290,  330,  330,  278,  139,
+      234,  136,  290,  134,  234,  278,  330,  116,  108,  278,
+      234,  239,  239,  239,  239,  239,  239,  239,  239,  239,
+      239,  239,  239,  239,  239,  239,  239,  239,  239,  239,
+      239,  240,  240,   99,   90,   89,   88,   87,   82,   81,
+
+       80,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  240,  240,  240,  240,  240,  240,  240,  240,  240,
+      240,  256,  256,  282,  282,  282,   79,  282,  333,  333,
+      293,  294,  256,  256,  256,  256,  256,  256,  333,  294,
+       78,  294,  282,  293,  293,   72,  345,  345,  282,  285,
+      285,  293,  294,  293,  295,  340,  345,   69,  293,   68,
+      285,  285,  285,  285,  285,  285,  286,  295,  295,   67,
+      308,  308,  308,   66,   64,  295,  340,  295,  308,  286,
+      286,   62,   53,  340,   27,  308,  354,  354,  354,  308,
+      286,  286,  286,  286,  286,  286,  291,  291,   26,   25,
+
+       24,   21,   19,   17,    7,  354,    0,  291,  291,  291,
+      291,  291,  291,  298,  298,  298,  298,  298,  298,  298,
+      298,  298,  298,  298,  298,  298,  298,  298,  298,  298,
+      298,  298,  298,  298,  298,  298,  298,  298,  298,  298,
+      298,  298,  298,  298,  298,  298,  298,  298,  298,  298,
+      298,  298,  298,  298,  298,  298,  298,  298,  320,  320,
+        0,    0,    0,  323,    0,  338,    0,  321,    0,  320,
+      320,  320,  320,  320,  320,  321,  323,  323,  338,  338,
+      321,  321,  339,    0,  323,  342,  338,    0,  321,  322,
+      347,  347,    0,    0,    0,  339,  339,    0,  342,  342,
+
+      347,  322,  322,  339,    0,  339,  342,    0,  342,    0,
+      357,  322,  322,  322,  322,  322,  322,  322,  327,  327,
+      327,  351,  327,  357,  357,    0,  327,  353,  352,  358,
+      358,  357,  359,  327,  351,  351,  352,  327,  352,  358,
+      353,  353,  351,  327,  351,  359,  359,    0,  353,  352,
+      353,  360,  360,  359,  361,  359,    0,    0,    0,    0,
+        0,  360,    0,    0,    0,    0,    0,  361,  361,    0,
+        0,    0,    0,    0,    0,  361,    0,  361,  363,    0,
+        0,  363,    0,    0,    0,  363,  363,  363,  364,  364,
+      364,    0,    0,    0,    0,    0,  364,    0,  364,    0,
+
+        0,  364,  364,  364,  365,    0,  365,  365,  365,  366,
+      366,  366,    0,    0,    0,    0,  366,  366,  366,    0,
+        0,    0,  366,  366,  366,  367,  367,  367,  367,  367,
+      367,  367,  367,  367,  367,  367,  367,  367,  367,  368,
+      368,    0,  368,  368,  368,  368,  368,  368,  368,  368,
+      368,  368,  368,  368,  368,  368,  369,  369,  369,  370,
+        0,    0,    0,  370,  370,  370,  373,    0,    0,  373,
+      373,  373,  373,  374,  374,  374,    0,  374,    0,    0,
+        0,    0,    0,  374,    0,    0,  374,  374,  374,  375,
+      375,    0,  375,  375,  375,  375,  375,  375,  375,  375,
+
+      375,  375,  375,  375,  375,  375,  376,    0,    0,    0,
+        0,  376,    0,    0,    0,    0,  376,  377,    0,    0,
+      377,  377,  377,  377,  378,    0,    0,  378,  378,    0,
+        0,    0,  378,  378,  379,  379,  379,  380,  380,  380,
+        0,    0,    0,    0,  380,  380,  380,    0,    0,    0,
+      380,  380,  380,  383,    0,    0,  383,  383,  383,  383,
+      384,    0,    0,    0,  384,    0,    0,    0,  384,  384,
+      362,  362,  362,  362,  362,  362,  362,  362,  362,  362,
+      362,  362,  362,  362,  362,  362,  362,  362,  362,  362,
+      362,  362,  362,  362,  362,  362,  362,  362,  362,  362,
+
+      362,  362,  362,  362,  362,  362,  362,  362,  362,  362,
+      362,  362,  362,  362,  362,  362,  362,  362,  362
+    } ;
+
+static yy_state_type yy_state_buf[YY_BUF_SIZE + 2], *yy_state_ptr;
+static char *yy_full_match;
+static int yy_lp;
+static int yy_looking_for_trail_begin = 0;
+static int yy_full_lp;
+static int *yy_full_state;
+#define YY_TRAILING_MASK 0x2000
+#define YY_TRAILING_HEAD_MASK 0x4000
+#define REJECT \
+{ \
+*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ \
+yy_cp = yy_full_match; /* restore poss. backed-over text */ \
+yy_lp = yy_full_lp; /* restore orig. accepting pos. */ \
+yy_state_ptr = yy_full_state; /* restore orig. state */ \
+yy_current_state = *yy_state_ptr; /* restore curr. state */ \
+++yy_lp; \
+goto find_rule; \
+}
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "./ada-lex.l"
+#define INITIAL 0
+/* FLEX lexer for Ada expressions, for GDB.
+   Copyright (C) 1994, 1997, 2000
+   Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+/*----------------------------------------------------------------------*/
+/* The converted version of this file is to be included in ada-exp.y, */
+/* the Ada parser for gdb.  The function yylex obtains characters from */
+/* the global pointer lexptr.  It returns a syntactic category for */
+/* each successive token and places a semantic value into yylval */
+/* (ada-lval), defined by the parser.   */
+/* Run flex with (at least) the -i option (case-insensitive), and the -I */
+/* option (interactive---no unnecessary lookahead).  */
+#line 48 "./ada-lex.l"
+#define NUMERAL_WIDTH 256
+#define LONGEST_SIGN ((ULONGEST) 1 << (sizeof(LONGEST) * HOST_CHAR_BIT - 1))
+
+/* Temporary staging for numeric literals. */
+static char numbuf[NUMERAL_WIDTH]; 
+ static void canonicalizeNumeral (char* s1, const char*);
+static int processInt (const char*, const char*, const char*);
+static int processReal (const char*);
+static int processId (const char*, int);
+static int processAttribute (const char*);
+static int find_dot_all (const char*);
+
+#undef YY_DECL
+#define YY_DECL static int yylex ( void ) 
+
+#undef YY_INPUT
+#define YY_INPUT(BUF, RESULT, MAX_SIZE) \
+    if ( *lexptr == '\000' ) \
+      (RESULT) = YY_NULL; \
+    else \
+      { \
+        *(BUF) = *lexptr; \
+        (RESULT) = 1; \
+       lexptr += 1; \
+      }
+
+static char *tempbuf = NULL;
+static int tempbufsize = 0;
+static int tempbuf_len;
+static struct block* left_block_context;
+
+static void resize_tempbuf (unsigned int);
+
+static void block_lookup (char*, char*);
+
+static int name_lookup (char*, char*, int*);
+
+static int find_dot_all (const char*);
+
+#define IN_STRING 1
+#define BEFORE_QUAL_QUOTE 2
+
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO(( void ));
+#else
+extern int yywrap YY_PROTO(( void ));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO(( int c, char *buf_ptr ));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PROTO(( yyconst char * ));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO(( int new_state ));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO(( void ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO(( void ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines.  This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+       if ( yy_current_buffer->yy_is_interactive ) \
+               { \
+               int c = '*', n; \
+               for ( n = 0; n < max_size && \
+                            (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+                       buf[n] = (char) c; \
+               if ( c == '\n' ) \
+                       buf[n++] = (char) c; \
+               if ( c == EOF && ferror( yyin ) ) \
+                       YY_FATAL_ERROR( "input in flex scanner failed" ); \
+               result = n; \
+               } \
+       else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \
+                 && ferror( yyin ) ) \
+               YY_FATAL_ERROR( "input in flex scanner failed" );
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( void ))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+       YY_USER_ACTION
+
+YY_DECL
+       {
+       register yy_state_type yy_current_state;
+       register char *yy_cp, *yy_bp;
+       register int yy_act;
+
+#line 91 "./ada-lex.l"
+
+
+
+       if ( yy_init )
+               {
+               yy_init = 0;
+
+#ifdef YY_USER_INIT
+               YY_USER_INIT;
+#endif
+
+               if ( ! yy_start )
+                       yy_start = 1;   /* first start state */
+
+               if ( ! yyin )
+                       yyin = stdin;
+
+               if ( ! yyout )
+                       yyout = stdout;
+
+               if ( ! yy_current_buffer )
+                       yy_current_buffer =
+                               yy_create_buffer( yyin, YY_BUF_SIZE );
+
+               yy_load_buffer_state();
+               }
+
+       while ( 1 )             /* loops until end-of-file is reached */
+               {
+               yy_cp = yy_c_buf_p;
+
+               /* Support of yytext. */
+               *yy_cp = yy_hold_char;
+
+               /* yy_bp points to the position in yy_ch_buf of the start of
+                * the current run.
+                */
+               yy_bp = yy_cp;
+
+               yy_current_state = yy_start;
+               yy_state_ptr = yy_state_buf;
+               *yy_state_ptr++ = yy_current_state;
+yy_match:
+               do
+                       {
+                       register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+                       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+                               {
+                               yy_current_state = (int) yy_def[yy_current_state];
+                               if ( yy_current_state >= 363 )
+                                       yy_c = yy_meta[(unsigned int) yy_c];
+                               }
+                       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+                       *yy_state_ptr++ = yy_current_state;
+                       ++yy_cp;
+                       }
+               while ( yy_base[yy_current_state] != 1771 );
+
+yy_find_action:
+               yy_current_state = *--yy_state_ptr;
+               yy_lp = yy_accept[yy_current_state];
+find_rule: /* we branch to this label when backing up */
+               for ( ; ; ) /* until we find what rule we matched */
+                       {
+                       if ( yy_lp && yy_lp < yy_accept[yy_current_state + 1] )
+                               {
+                               yy_act = yy_acclist[yy_lp];
+                               if ( yy_act & YY_TRAILING_HEAD_MASK ||
+                                    yy_looking_for_trail_begin )
+                                       {
+                                       if ( yy_act == yy_looking_for_trail_begin )
+                                               {
+                                               yy_looking_for_trail_begin = 0;
+                                               yy_act &= ~YY_TRAILING_HEAD_MASK;
+                                               break;
+                                               }
+                                       }
+                               else if ( yy_act & YY_TRAILING_MASK )
+                                       {
+                                       yy_looking_for_trail_begin = yy_act & ~YY_TRAILING_MASK;
+                                       yy_looking_for_trail_begin |= YY_TRAILING_HEAD_MASK;
+                                       }
+                               else
+                                       {
+                                       yy_full_match = yy_cp;
+                                       yy_full_state = yy_state_ptr;
+                                       yy_full_lp = yy_lp;
+                                       break;
+                                       }
+                               ++yy_lp;
+                               goto find_rule;
+                               }
+                       --yy_cp;
+                       yy_current_state = *--yy_state_ptr;
+                       yy_lp = yy_accept[yy_current_state];
+                       }
+
+               YY_DO_BEFORE_ACTION;
+
+
+do_action:     /* This label is used only to access EOF actions. */
+
+
+               switch ( yy_act )
+       { /* beginning of action switch */
+case 1:
+YY_RULE_SETUP
+#line 93 "./ada-lex.l"
+{ }
+       YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 95 "./ada-lex.l"
+{ yyterminate(); }
+       YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 97 "./ada-lex.l"
+{ 
+                  canonicalizeNumeral (numbuf, yytext); 
+                  return processInt (NULL, numbuf, strrchr(numbuf, 'e')+1);
+                }
+       YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 102 "./ada-lex.l"
+{ 
+                  canonicalizeNumeral (numbuf, yytext); 
+                  return processInt (NULL, numbuf, NULL);
+                }
+       YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 107 "./ada-lex.l"
+{
+                  canonicalizeNumeral (numbuf, yytext);
+                  return processInt (numbuf,
+                                     strchr (numbuf, '#') + 1, 
+                                     strrchr(numbuf, '#') + 1);
+                }
+       YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 114 "./ada-lex.l"
+{
+                  canonicalizeNumeral (numbuf, yytext);
+                  return processInt (numbuf, strchr (numbuf, '#') + 1, NULL);
+                }
+       YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 119 "./ada-lex.l"
+{
+                 canonicalizeNumeral (numbuf, yytext+2);
+                 return processInt ("16#", numbuf, NULL);
+               }
+       YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 125 "./ada-lex.l"
+{
+                  canonicalizeNumeral (numbuf, yytext); 
+                  return processReal (numbuf);
+               }
+       YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 130 "./ada-lex.l"
+{
+                  canonicalizeNumeral (numbuf, yytext); 
+                  return processReal (numbuf);
+               }
+       YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 135 "./ada-lex.l"
+{
+                   error ("Based real literals not implemented yet.");
+               }
+       YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 139 "./ada-lex.l"
+{
+                   error ("Based real literals not implemented yet.");
+               }
+       YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 143 "./ada-lex.l"
+{
+                  yylval.typed_val.type = builtin_type_ada_char;
+                  yylval.typed_val.val = yytext[1];
+                  return CHARLIT;
+               }
+       YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 149 "./ada-lex.l"
+{
+                   int v;
+                   yylval.typed_val.type = builtin_type_ada_char;
+                  sscanf (yytext+3, "%2x", &v);
+                  yylval.typed_val.val = v;
+                  return CHARLIT;
+               }
+       YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 157 "./ada-lex.l"
+{ return processId (yytext, yyleng); }
+       YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 159 "./ada-lex.l"
+{ 
+                  tempbuf_len = 0;
+                  BEGIN IN_STRING;
+               }
+       YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 164 "./ada-lex.l"
+{
+                  resize_tempbuf (yyleng+tempbuf_len);
+                  strncpy (tempbuf+tempbuf_len, yytext, yyleng-1);
+                  tempbuf_len += yyleng-1;
+                  yylval.sval.ptr = tempbuf;
+                  yylval.sval.length = tempbuf_len;
+                  BEGIN INITIAL;
+                  return STRING;
+               }
+       YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 174 "./ada-lex.l"
+{
+                  int n;
+                  resize_tempbuf (yyleng-5+tempbuf_len+1);
+                  strncpy (tempbuf+tempbuf_len, yytext, yyleng-6);
+                  sscanf(yytext+yyleng-4, "%2x", &n);
+                  tempbuf[yyleng-6+tempbuf_len] = (char) n;
+                  tempbuf_len += yyleng-5;
+               }
+       YY_BREAK
+case 18:
+YY_RULE_SETUP
+#line 183 "./ada-lex.l"
+{
+                  int n;
+                  resize_tempbuf (yyleng-4+tempbuf_len+1);
+                  strncpy (tempbuf+tempbuf_len, yytext, yyleng-6);
+                  tempbuf[yyleng-5+tempbuf_len] = '"';
+                  tempbuf_len += yyleng-4;
+               }
+       YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 191 "./ada-lex.l"
+{ 
+                 while (*lexptr != 'i' && *lexptr != 'I') 
+                   lexptr -= 1; 
+                 yyrestart(NULL); 
+                 return 0;
+               }
+       YY_BREAK
+/* ADA KEYWORDS */
+case 20:
+YY_RULE_SETUP
+#line 200 "./ada-lex.l"
+{ return ABS; }
+       YY_BREAK
+case 21:
+YY_RULE_SETUP
+#line 201 "./ada-lex.l"
+{ return _AND_; }
+       YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 202 "./ada-lex.l"
+{ return ELSE; }
+       YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 203 "./ada-lex.l"
+{ return IN; }
+       YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 204 "./ada-lex.l"
+{ return MOD; }
+       YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 205 "./ada-lex.l"
+{ return NEW; }
+       YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 206 "./ada-lex.l"
+{ return NOT; }
+       YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 207 "./ada-lex.l"
+{ return NULL_PTR; }
+       YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 208 "./ada-lex.l"
+{ return OR; }
+       YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 209 "./ada-lex.l"
+{ return REM; }
+       YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 210 "./ada-lex.l"
+{ return THEN; }
+       YY_BREAK
+case 31:
+YY_RULE_SETUP
+#line 211 "./ada-lex.l"
+{ return XOR; }
+       YY_BREAK
+/* ATTRIBUTES */
+case 32:
+YY_RULE_SETUP
+#line 215 "./ada-lex.l"
+{ return processAttribute (yytext+1); }
+       YY_BREAK
+/* PUNCTUATION */
+case 33:
+YY_RULE_SETUP
+#line 219 "./ada-lex.l"
+{ return ARROW; }
+       YY_BREAK
+case 34:
+YY_RULE_SETUP
+#line 220 "./ada-lex.l"
+{ return DOTDOT; }
+       YY_BREAK
+case 35:
+YY_RULE_SETUP
+#line 221 "./ada-lex.l"
+{ return STARSTAR; }
+       YY_BREAK
+case 36:
+YY_RULE_SETUP
+#line 222 "./ada-lex.l"
+{ return ASSIGN; }
+       YY_BREAK
+case 37:
+YY_RULE_SETUP
+#line 223 "./ada-lex.l"
+{ return NOTEQUAL; }
+       YY_BREAK
+case 38:
+YY_RULE_SETUP
+#line 224 "./ada-lex.l"
+{ return LEQ; }
+       YY_BREAK
+case 39:
+YY_RULE_SETUP
+#line 225 "./ada-lex.l"
+{ return GEQ; }
+       YY_BREAK
+case 40:
+YY_RULE_SETUP
+#line 227 "./ada-lex.l"
+{ BEGIN INITIAL; return '\''; }
+       YY_BREAK
+case 41:
+YY_RULE_SETUP
+#line 229 "./ada-lex.l"
+{ return yytext[0]; }
+       YY_BREAK
+case 42:
+YY_RULE_SETUP
+#line 231 "./ada-lex.l"
+{ if (paren_depth == 0 && comma_terminates)
+                   {
+                     lexptr -= 1;
+                     yyrestart(NULL);
+                     return 0;
+                   }
+                 else 
+                   return ',';
+               }
+       YY_BREAK
+case 43:
+YY_RULE_SETUP
+#line 241 "./ada-lex.l"
+{ paren_depth += 1; return '('; }
+       YY_BREAK
+case 44:
+YY_RULE_SETUP
+#line 242 "./ada-lex.l"
+{ if (paren_depth == 0) 
+                   {
+                     lexptr -= 1;
+                     yyrestart(NULL);
+                     return 0;
+                   }
+                 else 
+                   {
+                     paren_depth -= 1; 
+                     return ')';
+                   }
+               }
+       YY_BREAK
+case 45:
+YY_RULE_SETUP
+#line 255 "./ada-lex.l"
+{ return DOT_ALL; }
+       YY_BREAK
+case 46:
+YY_RULE_SETUP
+#line 257 "./ada-lex.l"
+{ 
+                 processId (yytext+1, yyleng-1);
+                 return DOT_ID; 
+               }
+       YY_BREAK
+case 47:
+YY_RULE_SETUP
+#line 262 "./ada-lex.l"
+{ 
+                  int all_posn = find_dot_all (yytext);
+                 int token_type, segments, k;
+                 int quote_follows;
+
+                  if (all_posn == -1 && yytext[yyleng-1] == '\'') 
+                   {
+                     quote_follows = 1;
+                     do { 
+                       yyless (yyleng-1); 
+                     } while (yytext[yyleng-1] == ' ');
+                   }
+                 else
+                   quote_follows = 0;                  
+                   
+                  if (all_posn >= 0)
+                   yyless (all_posn);
+                  processId(yytext, yyleng);
+                  segments = name_lookup (ada_mangle (yylval.ssym.stoken.ptr),
+                                         yylval.ssym.stoken.ptr, &token_type);
+                 left_block_context = NULL;
+                 for (k = yyleng; segments > 0 && k > 0; k -= 1)
+                    {
+                     if (yytext[k-1] == '.')
+                       segments -= 1;
+                     quote_follows = 0;
+                   }
+                 if (k <= 0)
+                   error ("confused by name %s", yytext);
+                 yyless (k);
+                 if (quote_follows) 
+                   BEGIN BEFORE_QUAL_QUOTE;
+                 return token_type;
+                }
+       YY_BREAK
+/* GDB EXPRESSION CONSTRUCTS  */
+case 48:
+YY_RULE_SETUP
+#line 300 "./ada-lex.l"
+{
+                  processId(yytext, yyleng-2);
+                  block_lookup (yylval.ssym.stoken.ptr, yylval.ssym.stoken.ptr);
+                  return BLOCKNAME;
+               }
+       YY_BREAK
+case 49:
+YY_RULE_SETUP
+#line 306 "./ada-lex.l"
+{ 
+                  processId(yytext, yyleng-2);
+                  block_lookup (ada_mangle (yylval.ssym.stoken.ptr),
+                                yylval.ssym.stoken.ptr);
+                  return BLOCKNAME;
+               }
+       YY_BREAK
+case 50:
+YY_RULE_SETUP
+#line 313 "./ada-lex.l"
+{ return yytext[0]; }
+       YY_BREAK
+case 51:
+YY_RULE_SETUP
+#line 315 "./ada-lex.l"
+{ yylval.lval = -1; return LAST; }
+       YY_BREAK
+case 52:
+YY_RULE_SETUP
+#line 316 "./ada-lex.l"
+{ yylval.lval = -atoi(yytext+2); return LAST; }
+       YY_BREAK
+case 53:
+YY_RULE_SETUP
+#line 317 "./ada-lex.l"
+{ yylval.lval = 0; return LAST; }
+       YY_BREAK
+case 54:
+YY_RULE_SETUP
+#line 318 "./ada-lex.l"
+{ yylval.lval = atoi(yytext+1); return LAST; }
+       YY_BREAK
+/* REGISTERS AND GDB CONVENIENCE VARIABLES */
+case 55:
+YY_RULE_SETUP
+#line 323 "./ada-lex.l"
+{
+                 int c;
+                 for (c = 0; c < NUM_REGS; c++)
+                   if (REGISTER_NAME (c) &&
+                        strcmp (yytext + 1, REGISTER_NAME (c)) == 0)
+                     {
+                       yylval.lval = c;
+                       return REGNAME;
+                     }
+                 yylval.sval.ptr = yytext;
+                 yylval.sval.length = yyleng;
+                 yylval.ivar = 
+                   lookup_internalvar (copy_name (yylval.sval) + 1);
+                 return INTERNAL_VARIABLE;
+               }
+       YY_BREAK
+/* CATCH-ALL ERROR CASE */
+case 56:
+YY_RULE_SETUP
+#line 341 "./ada-lex.l"
+{ error ("Invalid character '%s' in expression.", yytext); }
+       YY_BREAK
+case 57:
+YY_RULE_SETUP
+#line 342 "./ada-lex.l"
+YY_FATAL_ERROR( "flex scanner jammed" );
+       YY_BREAK
+                       case YY_STATE_EOF(INITIAL):
+                       case YY_STATE_EOF(IN_STRING):
+                       case YY_STATE_EOF(BEFORE_QUAL_QUOTE):
+                               yyterminate();
+
+       case YY_END_OF_BUFFER:
+               {
+               /* Amount of text matched not including the EOB char. */
+               int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+
+               /* Undo the effects of YY_DO_BEFORE_ACTION. */
+               *yy_cp = yy_hold_char;
+               YY_RESTORE_YY_MORE_OFFSET
+
+               if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+                       {
+                       /* We're scanning a new file or input source.  It's
+                        * possible that this happened because the user
+                        * just pointed yyin at a new source and called
+                        * yylex().  If so, then we have to assure
+                        * consistency between yy_current_buffer and our
+                        * globals.  Here is the right place to do so, because
+                        * this is the first action (other than possibly a
+                        * back-up) that will match for the new input source.
+                        */
+                       yy_n_chars = yy_current_buffer->yy_n_chars;
+                       yy_current_buffer->yy_input_file = yyin;
+                       yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+                       }
+
+               /* Note that here we test for yy_c_buf_p "<=" to the position
+                * of the first EOB in the buffer, since yy_c_buf_p will
+                * already have been incremented past the NUL character
+                * (since all states make transitions on EOB to the
+                * end-of-buffer state).  Contrast this with the test
+                * in input().
+                */
+               if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+                       { /* This was really a NUL. */
+                       yy_state_type yy_next_state;
+
+                       yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+                       yy_current_state = yy_get_previous_state();
+
+                       /* Okay, we're now positioned to make the NUL
+                        * transition.  We couldn't have
+                        * yy_get_previous_state() go ahead and do it
+                        * for us because it doesn't know how to deal
+                        * with the possibility of jamming (and we don't
+                        * want to build jamming into it because then it
+                        * will run more slowly).
+                        */
+
+                       yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+                       yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+                       if ( yy_next_state )
+                               {
+                               /* Consume the NUL. */
+                               yy_cp = ++yy_c_buf_p;
+                               yy_current_state = yy_next_state;
+                               goto yy_match;
+                               }
+
+                       else
+                               {
+                               yy_cp = yy_c_buf_p;
+                               goto yy_find_action;
+                               }
+                       }
+
+               else switch ( yy_get_next_buffer() )
+                       {
+                       case EOB_ACT_END_OF_FILE:
+                               {
+                               yy_did_buffer_switch_on_eof = 0;
+
+                               if ( yywrap() )
+                                       {
+                                       /* Note: because we've taken care in
+                                        * yy_get_next_buffer() to have set up
+                                        * yytext, we can now set up
+                                        * yy_c_buf_p so that if some total
+                                        * hoser (like flex itself) wants to
+                                        * call the scanner after we return the
+                                        * YY_NULL, it'll still work - another
+                                        * YY_NULL will get returned.
+                                        */
+                                       yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+                                       yy_act = YY_STATE_EOF(YY_START);
+                                       goto do_action;
+                                       }
+
+                               else
+                                       {
+                                       if ( ! yy_did_buffer_switch_on_eof )
+                                               YY_NEW_FILE;
+                                       }
+                               break;
+                               }
+
+                       case EOB_ACT_CONTINUE_SCAN:
+                               yy_c_buf_p =
+                                       yytext_ptr + yy_amount_of_matched_text;
+
+                               yy_current_state = yy_get_previous_state();
+
+                               yy_cp = yy_c_buf_p;
+                               yy_bp = yytext_ptr + YY_MORE_ADJ;
+                               goto yy_match;
+
+                       case EOB_ACT_LAST_MATCH:
+                               yy_c_buf_p =
+                               &yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+                               yy_current_state = yy_get_previous_state();
+
+                               yy_cp = yy_c_buf_p;
+                               yy_bp = yytext_ptr + YY_MORE_ADJ;
+                               goto yy_find_action;
+                       }
+               break;
+               }
+
+       default:
+               YY_FATAL_ERROR(
+                       "fatal flex scanner internal error--no action found" );
+       } /* end of action switch */
+               } /* end of scanning one token */
+       } /* end of yylex */
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *     EOB_ACT_LAST_MATCH -
+ *     EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *     EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+       {
+       register char *dest = yy_current_buffer->yy_ch_buf;
+       register char *source = yytext_ptr;
+       register int number_to_move, i;
+       int ret_val;
+
+       if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+               YY_FATAL_ERROR(
+               "fatal flex scanner internal error--end of buffer missed" );
+
+       if ( yy_current_buffer->yy_fill_buffer == 0 )
+               { /* Don't try to fill the buffer, so this is an EOF. */
+               if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+                       {
+                       /* We matched a single character, the EOB, so
+                        * treat this as a final EOF.
+                        */
+                       return EOB_ACT_END_OF_FILE;
+                       }
+
+               else
+                       {
+                       /* We matched some text prior to the EOB, first
+                        * process it.
+                        */
+                       return EOB_ACT_LAST_MATCH;
+                       }
+               }
+
+       /* Try to read more data. */
+
+       /* First move last chars to start of buffer. */
+       number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+
+       for ( i = 0; i < number_to_move; ++i )
+               *(dest++) = *(source++);
+
+       if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+               /* don't do the read, it's not guaranteed to return an EOF,
+                * just force an EOF
+                */
+               yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+       else
+               {
+               int num_to_read =
+                       yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+               while ( num_to_read <= 0 )
+                       { /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+                       YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+                       /* just a shorter name for the current buffer */
+                       YY_BUFFER_STATE b = yy_current_buffer;
+
+                       int yy_c_buf_p_offset =
+                               (int) (yy_c_buf_p - b->yy_ch_buf);
+
+                       if ( b->yy_is_our_buffer )
+                               {
+                               int new_size = b->yy_buf_size * 2;
+
+                               if ( new_size <= 0 )
+                                       b->yy_buf_size += b->yy_buf_size / 8;
+                               else
+                                       b->yy_buf_size *= 2;
+
+                               b->yy_ch_buf = (char *)
+                                       /* Include room in for 2 EOB chars. */
+                                       yy_flex_realloc( (void *) b->yy_ch_buf,
+                                                        b->yy_buf_size + 2 );
+                               }
+                       else
+                               /* Can't grow it, we don't own it. */
+                               b->yy_ch_buf = 0;
+
+                       if ( ! b->yy_ch_buf )
+                               YY_FATAL_ERROR(
+                               "fatal error - scanner input buffer overflow" );
+
+                       yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+                       num_to_read = yy_current_buffer->yy_buf_size -
+                                               number_to_move - 1;
+#endif
+                       }
+
+               if ( num_to_read > YY_READ_BUF_SIZE )
+                       num_to_read = YY_READ_BUF_SIZE;
+
+               /* Read in more data. */
+               YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+                       yy_n_chars, num_to_read );
+
+               yy_current_buffer->yy_n_chars = yy_n_chars;
+               }
+
+       if ( yy_n_chars == 0 )
+               {
+               if ( number_to_move == YY_MORE_ADJ )
+                       {
+                       ret_val = EOB_ACT_END_OF_FILE;
+                       yyrestart( yyin );
+                       }
+
+               else
+                       {
+                       ret_val = EOB_ACT_LAST_MATCH;
+                       yy_current_buffer->yy_buffer_status =
+                               YY_BUFFER_EOF_PENDING;
+                       }
+               }
+
+       else
+               ret_val = EOB_ACT_CONTINUE_SCAN;
+
+       yy_n_chars += number_to_move;
+       yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+       yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+       yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+       return ret_val;
+       }
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type yy_get_previous_state()
+       {
+       register yy_state_type yy_current_state;
+       register char *yy_cp;
+
+       yy_current_state = yy_start;
+       yy_state_ptr = yy_state_buf;
+       *yy_state_ptr++ = yy_current_state;
+
+       for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+               {
+               register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+               while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+                       {
+                       yy_current_state = (int) yy_def[yy_current_state];
+                       if ( yy_current_state >= 363 )
+                               yy_c = yy_meta[(unsigned int) yy_c];
+                       }
+               yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+               *yy_state_ptr++ = yy_current_state;
+               }
+
+       return yy_current_state;
+       }
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *     next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+yy_state_type yy_current_state;
+#endif
+       {
+       register int yy_is_jam;
+
+       register YY_CHAR yy_c = 1;
+       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+               {
+               yy_current_state = (int) yy_def[yy_current_state];
+               if ( yy_current_state >= 363 )
+                       yy_c = yy_meta[(unsigned int) yy_c];
+               }
+       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+       yy_is_jam = (yy_current_state == 362);
+       if ( ! yy_is_jam )
+               *yy_state_ptr++ = yy_current_state;
+
+       return yy_is_jam ? 0 : yy_current_state;
+       }
+
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void yyunput( int c, register char *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+int c;
+register char *yy_bp;
+#endif
+       {
+       register char *yy_cp = yy_c_buf_p;
+
+       /* undo effects of setting up yytext */
+       *yy_cp = yy_hold_char;
+
+       if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+               { /* need to shift things up to make room */
+               /* +2 for EOB chars. */
+               register int number_to_move = yy_n_chars + 2;
+               register char *dest = &yy_current_buffer->yy_ch_buf[
+                                       yy_current_buffer->yy_buf_size + 2];
+               register char *source =
+                               &yy_current_buffer->yy_ch_buf[number_to_move];
+
+               while ( source > yy_current_buffer->yy_ch_buf )
+                       *--dest = *--source;
+
+               yy_cp += (int) (dest - source);
+               yy_bp += (int) (dest - source);
+               yy_current_buffer->yy_n_chars =
+                       yy_n_chars = yy_current_buffer->yy_buf_size;
+
+               if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+                       YY_FATAL_ERROR( "flex scanner push-back overflow" );
+               }
+
+       *--yy_cp = (char) c;
+
+
+       yytext_ptr = yy_bp;
+       yy_hold_char = *yy_cp;
+       yy_c_buf_p = yy_cp;
+       }
+#endif /* ifndef YY_NO_UNPUT */
+
+
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+       {
+       int c;
+
+       *yy_c_buf_p = yy_hold_char;
+
+       if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+               {
+               /* yy_c_buf_p now points to the character we want to return.
+                * If this occurs *before* the EOB characters, then it's a
+                * valid NUL; if not, then we've hit the end of the buffer.
+                */
+               if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+                       /* This was really a NUL. */
+                       *yy_c_buf_p = '\0';
+
+               else
+                       { /* need more input */
+                       int offset = yy_c_buf_p - yytext_ptr;
+                       ++yy_c_buf_p;
+
+                       switch ( yy_get_next_buffer() )
+                               {
+                               case EOB_ACT_LAST_MATCH:
+                                       /* This happens because yy_g_n_b()
+                                        * sees that we've accumulated a
+                                        * token and flags that we need to
+                                        * try matching the token before
+                                        * proceeding.  But for input(),
+                                        * there's no matching to consider.
+                                        * So convert the EOB_ACT_LAST_MATCH
+                                        * to EOB_ACT_END_OF_FILE.
+                                        */
+
+                                       /* Reset buffer status. */
+                                       yyrestart( yyin );
+
+                                       /* fall through */
+
+                               case EOB_ACT_END_OF_FILE:
+                                       {
+                                       if ( yywrap() )
+                                               return EOF;
+
+                                       if ( ! yy_did_buffer_switch_on_eof )
+                                               YY_NEW_FILE;
+#ifdef __cplusplus
+                                       return yyinput();
+#else
+                                       return input();
+#endif
+                                       }
+
+                               case EOB_ACT_CONTINUE_SCAN:
+                                       yy_c_buf_p = yytext_ptr + offset;
+                                       break;
+                               }
+                       }
+               }
+
+       c = *(unsigned char *) yy_c_buf_p;      /* cast for 8-bit char's */
+       *yy_c_buf_p = '\0';     /* preserve yytext */
+       yy_hold_char = *++yy_c_buf_p;
+
+
+       return c;
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+       {
+       if ( ! yy_current_buffer )
+               yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+       yy_init_buffer( yy_current_buffer, input_file );
+       yy_load_buffer_state();
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+       {
+       if ( yy_current_buffer == new_buffer )
+               return;
+
+       if ( yy_current_buffer )
+               {
+               /* Flush out information for old buffer. */
+               *yy_c_buf_p = yy_hold_char;
+               yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+               yy_current_buffer->yy_n_chars = yy_n_chars;
+               }
+
+       yy_current_buffer = new_buffer;
+       yy_load_buffer_state();
+
+       /* We don't actually know whether we did this switch during
+        * EOF (yywrap()) processing, but the only time this flag
+        * is looked at is after yywrap() is called, so it's safe
+        * to go ahead and always set it.
+        */
+       yy_did_buffer_switch_on_eof = 1;
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+       {
+       yy_n_chars = yy_current_buffer->yy_n_chars;
+       yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+       yyin = yy_current_buffer->yy_input_file;
+       yy_hold_char = *yy_c_buf_p;
+       }
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+       {
+       YY_BUFFER_STATE b;
+
+       b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+       if ( ! b )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+       b->yy_buf_size = size;
+
+       /* yy_ch_buf has to be 2 characters longer than the size given because
+        * we need to put in 2 end-of-buffer characters.
+        */
+       b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+       if ( ! b->yy_ch_buf )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+       b->yy_is_our_buffer = 1;
+
+       yy_init_buffer( b, file );
+
+       return b;
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+       {
+       if ( ! b )
+               return;
+
+       if ( b == yy_current_buffer )
+               yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+       if ( b->yy_is_our_buffer )
+               yy_flex_free( (void *) b->yy_ch_buf );
+
+       yy_flex_free( (void *) b );
+       }
+
+
+#ifndef YY_ALWAYS_INTERACTIVE
+#ifndef YY_NEVER_INTERACTIVE
+extern int isatty YY_PROTO(( int ));
+#endif
+#endif
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+       {
+       yy_flush_buffer( b );
+
+       b->yy_input_file = file;
+       b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+       b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+       b->yy_is_interactive = 0;
+#else
+       b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yy_flush_buffer( YY_BUFFER_STATE b )
+#else
+void yy_flush_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+       {
+       if ( ! b )
+               return;
+
+       b->yy_n_chars = 0;
+
+       /* We always need two end-of-buffer characters.  The first causes
+        * a transition to the end-of-buffer state.  The second causes
+        * a jam in that state.
+        */
+       b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+       b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+       b->yy_buf_pos = &b->yy_ch_buf[0];
+
+       b->yy_at_bol = 1;
+       b->yy_buffer_status = YY_BUFFER_NEW;
+
+       if ( b == yy_current_buffer )
+               yy_load_buffer_state();
+       }
+
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+#else
+YY_BUFFER_STATE yy_scan_buffer( base, size )
+char *base;
+yy_size_t size;
+#endif
+       {
+       YY_BUFFER_STATE b;
+
+       if ( size < 2 ||
+            base[size-2] != YY_END_OF_BUFFER_CHAR ||
+            base[size-1] != YY_END_OF_BUFFER_CHAR )
+               /* They forgot to leave room for the EOB's. */
+               return 0;
+
+       b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+       if ( ! b )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+       b->yy_buf_size = size - 2;      /* "- 2" to take care of EOB's */
+       b->yy_buf_pos = b->yy_ch_buf = base;
+       b->yy_is_our_buffer = 0;
+       b->yy_input_file = 0;
+       b->yy_n_chars = b->yy_buf_size;
+       b->yy_is_interactive = 0;
+       b->yy_at_bol = 1;
+       b->yy_fill_buffer = 0;
+       b->yy_buffer_status = YY_BUFFER_NEW;
+
+       yy_switch_to_buffer( b );
+
+       return b;
+       }
+#endif
+
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
+#else
+YY_BUFFER_STATE yy_scan_string( yy_str )
+yyconst char *yy_str;
+#endif
+       {
+       int len;
+       for ( len = 0; yy_str[len]; ++len )
+               ;
+
+       return yy_scan_bytes( yy_str, len );
+       }
+#endif
+
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+#else
+YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+yyconst char *bytes;
+int len;
+#endif
+       {
+       YY_BUFFER_STATE b;
+       char *buf;
+       yy_size_t n;
+       int i;
+
+       /* Get memory for full buffer, including space for trailing EOB's. */
+       n = len + 2;
+       buf = (char *) yy_flex_alloc( n );
+       if ( ! buf )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+       for ( i = 0; i < len; ++i )
+               buf[i] = bytes[i];
+
+       buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+       b = yy_scan_buffer( buf, n );
+       if ( ! b )
+               YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+       /* It's okay to grow etc. this buffer, and we should throw it
+        * away when we're done.
+        */
+       b->yy_is_our_buffer = 1;
+
+       return b;
+       }
+#endif
+
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void yy_push_state( int new_state )
+#else
+static void yy_push_state( new_state )
+int new_state;
+#endif
+       {
+       if ( yy_start_stack_ptr >= yy_start_stack_depth )
+               {
+               yy_size_t new_size;
+
+               yy_start_stack_depth += YY_START_STACK_INCR;
+               new_size = yy_start_stack_depth * sizeof( int );
+
+               if ( ! yy_start_stack )
+                       yy_start_stack = (int *) yy_flex_alloc( new_size );
+
+               else
+                       yy_start_stack = (int *) yy_flex_realloc(
+                                       (void *) yy_start_stack, new_size );
+
+               if ( ! yy_start_stack )
+                       YY_FATAL_ERROR(
+                       "out of memory expanding start-condition stack" );
+               }
+
+       yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+       BEGIN(new_state);
+       }
+#endif
+
+
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state()
+       {
+       if ( --yy_start_stack_ptr < 0 )
+               YY_FATAL_ERROR( "start-condition stack underflow" );
+
+       BEGIN(yy_start_stack[yy_start_stack_ptr]);
+       }
+#endif
+
+
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state()
+       {
+       return yy_start_stack[yy_start_stack_ptr - 1];
+       }
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void yy_fatal_error( yyconst char msg[] )
+#else
+static void yy_fatal_error( msg )
+char msg[];
+#endif
+       {
+       (void) fprintf( stderr, "%s\n", msg );
+       exit( YY_EXIT_FAILURE );
+       }
+
+
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+       do \
+               { \
+               /* Undo effects of setting up yytext. */ \
+               yytext[yyleng] = yy_hold_char; \
+               yy_c_buf_p = yytext + n; \
+               yy_hold_char = *yy_c_buf_p; \
+               *yy_c_buf_p = '\0'; \
+               yyleng = n; \
+               } \
+       while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+#else
+static void yy_flex_strncpy( s1, s2, n )
+char *s1;
+yyconst char *s2;
+int n;
+#endif
+       {
+       register int i;
+       for ( i = 0; i < n; ++i )
+               s1[i] = s2[i];
+       }
+#endif
+
+#ifdef YY_NEED_STRLEN
+#ifdef YY_USE_PROTOS
+static int yy_flex_strlen( yyconst char *s )
+#else
+static int yy_flex_strlen( s )
+yyconst char *s;
+#endif
+       {
+       register int n;
+       for ( n = 0; s[n]; ++n )
+               ;
+
+       return n;
+       }
+#endif
+
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_alloc( yy_size_t size )
+#else
+static void *yy_flex_alloc( size )
+yy_size_t size;
+#endif
+       {
+       return (void *) malloc( size );
+       }
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_realloc( void *ptr, yy_size_t size )
+#else
+static void *yy_flex_realloc( ptr, size )
+void *ptr;
+yy_size_t size;
+#endif
+       {
+       /* The cast to (char *) in the following accommodates both
+        * implementations that use char* generic pointers, and those
+        * that use void* generic pointers.  It works with the latter
+        * because both ANSI C and C++ allow castless assignment from
+        * any pointer type to void*, and deal with argument conversions
+        * as though doing an assignment.
+        */
+       return (void *) realloc( (char *) ptr, size );
+       }
+
+#ifdef YY_USE_PROTOS
+static void yy_flex_free( void *ptr )
+#else
+static void yy_flex_free( ptr )
+void *ptr;
+#endif
+       {
+       free( ptr );
+       }
+
+#if YY_MAIN
+int main()
+       {
+       yylex();
+       return 0;
+       }
+#endif
+#line 342 "./ada-lex.l"
+
+
+#include <ctype.h>
+#include <string.h>
+
+/* Initialize the lexer for processing new expression */
+void
+lexer_init (FILE* inp)
+{
+  BEGIN INITIAL;
+  yyrestart (inp);
+}
+
+
+/* Make sure that tempbuf points at an array at least N characters long. */
+
+static void
+resize_tempbuf (n)
+     unsigned int n;
+{
+  if (tempbufsize < n)
+    {
+      tempbufsize = (n+63) & ~63;
+      tempbuf = (char*) xrealloc (tempbuf, tempbufsize);
+    }
+}
+/* Copy S2 to S1, removing all underscores, and downcasing all letters. */
+
+static void
+canonicalizeNumeral (s1,s2)
+     char* s1;
+     const char* s2;
+{
+  for (; *s2 != '\000'; s2 += 1) 
+    {
+      if (*s2 != '_')
+       {
+         *s1 = tolower(*s2);
+         s1 += 1;
+       }
+    }
+  s1[0] = '\000';
+}
+
+#define HIGH_BYTE_POSN ((sizeof (ULONGEST) - 1) * HOST_CHAR_BIT)
+
+/* True (non-zero) iff DIGIT is a valid digit in radix BASE, 
+   where 2 <= BASE <= 16.  */
+
+static int
+is_digit_in_base (digit, base)
+     unsigned char digit;
+     int base;
+{
+  if (!isxdigit (digit))
+    return 0;
+  if (base <= 10)
+    return (isdigit (digit) && digit < base + '0');
+  else 
+    return (isdigit (digit) || tolower (digit) < base - 10 + 'a');
+}
+
+static int
+digit_to_int (c)
+     unsigned char c;
+{
+  if (isdigit (c))
+    return c - '0';
+  else
+    return tolower (c) - 'a' + 10;
+}
+
+/* As for strtoul, but for ULONGEST results. */
+ULONGEST
+strtoulst (num, trailer, base)
+     const char *num;
+     const char **trailer;
+     int base;
+{
+  unsigned int high_part;
+  ULONGEST result;
+  int i;
+  unsigned char lim;
+
+  if (base < 2 || base > 16)
+    {
+      errno = EINVAL;
+      return 0;
+    }
+  lim = base - 1 + '0';
+
+  result = high_part = 0;
+  for (i = 0; is_digit_in_base (num[i], base); i += 1)
+    {
+      result = result*base + digit_to_int (num[i]);
+      high_part = high_part*base + (unsigned int) (result >> HIGH_BYTE_POSN);
+      result &= ((ULONGEST) 1 << HIGH_BYTE_POSN) - 1;
+      if (high_part > 0xff) 
+       {
+         errno = ERANGE;
+         result = high_part = 0;
+         break;
+       }
+    }
+
+  if (trailer != NULL)
+    *trailer = &num[i];
+
+  return result + ((ULONGEST) high_part << HIGH_BYTE_POSN);
+}
+
+
+
+/* Interprets the prefix of NUM that consists of digits of the given BASE
+   as an integer of that BASE, with the string EXP as an exponent.
+   Puts value in yylval, and returns INT, if the string is valid.  Causes
+   an error if the number is improperly formated.   BASE, if NULL, defaults 
+   to "10", and EXP to "1". The EXP does not contain a leading 'e' or 'E'. */
+
+static int
+processInt (base0, num0, exp0)
+     const char* num0;
+     const char* base0;
+     const char* exp0;
+{
+  ULONGEST result;
+  long exp;
+  int base;
+
+  char* trailer;
+
+  if (base0 == NULL)
+    base = 10;
+  else
+    {  
+      base = strtol (base0, (char**) NULL, 10);
+      if (base < 2 || base > 16)
+       error ("Invalid base: %d.", base);
+    }
+
+  if (exp0 == NULL)
+    exp = 0;
+  else
+    exp = strtol(exp0, (char**) NULL, 10);
+
+  errno = 0;
+  result = strtoulst (num0, &trailer, base);
+  if (errno == ERANGE)
+    error ("Integer literal out of range");
+  if (isxdigit(*trailer))
+    error ("Invalid digit `%c' in based literal", *trailer);
+
+  while (exp > 0) 
+    {
+      if (result > (ULONG_MAX / base))
+       error ("Integer literal out of range");
+      result *= base;
+      exp -= 1;
+    }
+    
+  if ((result >> (TARGET_INT_BIT-1)) == 0)
+    yylval.typed_val.type = builtin_type_ada_int;
+  else if ((result >> (TARGET_LONG_BIT-1)) == 0)
+    yylval.typed_val.type = builtin_type_ada_long;
+  else if (((result >> (TARGET_LONG_BIT-1)) >> 1) == 0)
+    {
+      /* We have a number representable as an unsigned integer quantity.
+         For consistency with the C treatment, we will treat it as an 
+        anonymous modular (unsigned) quantity.  Alas, the types are such
+        that we need to store .val as a signed quantity.  Sorry 
+         for the mess, but C doesn't officially guarantee that a simple
+         assignment does the trick (no, it doesn't; read the reference manual).
+       */
+      yylval.typed_val.type = builtin_type_unsigned_long;
+      if (result & LONGEST_SIGN)
+       yylval.typed_val.val = 
+         (LONGEST) (result & ~LONGEST_SIGN) 
+         - (LONGEST_SIGN>>1) - (LONGEST_SIGN>>1);
+      else
+       yylval.typed_val.val = (LONGEST) result;
+      return INT;
+    }
+  else 
+    yylval.typed_val.type = builtin_type_ada_long_long;
+
+  yylval.typed_val.val = (LONGEST) result;
+  return INT;
+}
+
+static int
+processReal (num0)
+     const char* num0;
+{
+  if (sizeof (DOUBLEST) <= sizeof (float))
+    sscanf (num0, "%g", &yylval.typed_val_float.dval);
+  else if (sizeof (DOUBLEST) <= sizeof (double))
+    sscanf (num0, "%lg", &yylval.typed_val_float.dval);
+  else
+    {
+#ifdef PRINTF_HAS_LONG_DOUBLE
+      sscanf (num0, "%Lg", &yylval.typed_val_float.dval);
+#else
+      /* Scan it into a double, then convert and assign it to the 
+        long double.  This at least wins with values representable 
+        in the range of doubles. */
+      double temp;
+      sscanf (num0, "%lg", &temp);
+      yylval.typed_val_float.dval = temp;
+#endif
+    }
+
+  yylval.typed_val_float.type = builtin_type_ada_float;
+  if (sizeof(DOUBLEST) >= TARGET_DOUBLE_BIT / TARGET_CHAR_BIT)
+    yylval.typed_val_float.type = builtin_type_ada_double;
+  if (sizeof(DOUBLEST) >= TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT)
+    yylval.typed_val_float.type = builtin_type_ada_long_double;
+
+  return FLOAT;
+}
+
+static int
+processId (name0, len)
+     const char *name0;
+     int len;
+{
+  char* name = xmalloc (len + 11);
+  int i0, i;
+  
+/*  add_name_string_cleanup (name); */
+/* FIXME: add_name_string_cleanup should be defined in parse.c */
+  while (len > 0 && isspace (name0[len-1]))
+    len -= 1;
+  i = i0 = 0;
+  while (i0 < len) 
+    {
+      if (isalnum (name0[i0]))
+       {
+         name[i] = tolower (name0[i0]);
+         i += 1; i0 += 1;
+       }
+      else switch (name0[i0]) 
+       {
+       default:
+         name[i] = name0[i0];
+         i += 1; i0 += 1;
+         break;
+       case ' ': case '\t':
+         i0 += 1;
+         break;
+       case '\'':
+         i0 += 1;
+         while (i0 < len && name0[i0] != '\'')
+           {
+             name[i] = name0[i0];
+             i += 1; i0 += 1;
+           }
+         i0 += 1;
+         break;
+       case '<':
+         i0 += 1;
+         while (i0 < len && name0[i0] != '>')
+           {
+             name[i] = name0[i0];
+             i += 1; i0 += 1;
+           }
+         i0 += 1;
+         break;
+       }
+    }
+  name[i] = '\000';
+
+  yylval.ssym.sym = NULL;
+  yylval.ssym.stoken.ptr = name;
+  yylval.ssym.stoken.length = i;
+  return NAME;
+}
+
+static void 
+block_lookup (name, err_name)
+     char* name;
+     char* err_name;
+{
+  struct symbol** syms;
+  struct block** blocks;
+  int nsyms;
+  struct symtab *symtab;
+  nsyms = ada_lookup_symbol_list (name, left_block_context,
+                                 VAR_NAMESPACE, &syms, &blocks);
+  if (left_block_context == NULL &&
+      (nsyms == 0 || SYMBOL_CLASS (syms[0]) != LOC_BLOCK))
+    symtab = lookup_symtab (name);
+  else
+    symtab = NULL;
+
+  if (symtab != NULL)
+    left_block_context = yylval.bval =
+      BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
+  else if (nsyms == 0 || SYMBOL_CLASS (syms[0]) != LOC_BLOCK)
+    {
+      if (left_block_context == NULL)
+       error ("No file or function \"%s\".", err_name);
+      else
+       error ("No function \"%s\" in specified context.", err_name);
+    }
+  else 
+    {
+      left_block_context = yylval.bval = SYMBOL_BLOCK_VALUE (syms[0]); 
+      if (nsyms > 1)
+       warning ("Function name \"%s\" ambiguous here", err_name);
+    }
+}
+
+/* Look up NAME0 (assumed to be mangled) as a name in VAR_NAMESPACE,
+   setting *TOKEN_TYPE to NAME or TYPENAME, depending on what is
+   found.  Try first the entire name, then the name without the last 
+   segment (i.e., after the last .id), etc., and return the number of
+   segments that had to be removed to get a match.  Calls error if no
+   matches are found, using ERR_NAME in any error message.  When
+   exactly one symbol match is found, it is placed in yylval. */
+static int
+name_lookup (name0, err_name, token_type)
+     char* name0;
+     char* err_name;
+     int* token_type;
+{
+  struct symbol** syms;
+  struct block** blocks;
+  struct type* type;
+  int len0 = strlen (name0);
+  char* name = savestring (name0, len0);
+  int nsyms;
+  int segments;
+/*  add_name_string_cleanup (name);*/
+/* FIXME: add_name_string_cleanup should be defined in parse.c */
+  yylval.ssym.stoken.ptr = name;
+  yylval.ssym.stoken.length = strlen (name);
+  for (segments = 0; ; segments += 1)
+    {
+      struct type* preferred_type;
+      int i, preferred_index;
+
+      if (left_block_context == NULL) 
+       nsyms = ada_lookup_symbol_list (name, expression_context_block, 
+                                       VAR_NAMESPACE, &syms, &blocks);
+      else
+       nsyms = ada_lookup_symbol_list (name, left_block_context, 
+                                       VAR_NAMESPACE, &syms, &blocks);
+
+      /* Check for a type definition. */
+
+      /* Look for a symbol that doesn't denote void.  This is (I think) a */
+      /* temporary kludge to get around problems in GNAT output. */
+      preferred_index = -1; preferred_type = NULL;
+      for (i = 0; i < nsyms; i += 1)
+       switch (SYMBOL_CLASS (syms[i])) 
+         {
+         case LOC_TYPEDEF:
+           if (ada_prefer_type (SYMBOL_TYPE (syms[i]), preferred_type))
+             {
+               preferred_index = i;
+               preferred_type = SYMBOL_TYPE (syms[i]);
+             }
+           break;
+         case LOC_REGISTER:
+         case LOC_ARG:
+         case LOC_REF_ARG:
+         case LOC_REGPARM:
+         case LOC_REGPARM_ADDR:
+         case LOC_LOCAL:
+         case LOC_LOCAL_ARG:
+         case LOC_BASEREG:
+         case LOC_BASEREG_ARG:
+           goto NotType;
+         default:
+           break;
+         }
+      if (preferred_type != NULL)
+       {
+/*       if (TYPE_CODE (preferred_type) == TYPE_CODE_VOID)
+           error ("`%s' matches only void type name(s)", 
+                  ada_demangle (name));
+*/
+/* FIXME: ada_demangle should be defined in defs.h, and is located in ada-lang.c */
+/*       else*/ if (ada_is_object_renaming (syms[preferred_index]))
+           {
+             yylval.ssym.sym = syms[preferred_index];
+             *token_type = OBJECT_RENAMING;
+             return segments;
+           } 
+         else if (ada_renaming_type (SYMBOL_TYPE (syms[preferred_index])) 
+                   != NULL)
+           {
+             int result;
+             const char* renaming = 
+               ada_simple_renamed_entity (syms[preferred_index]);
+             char* new_name = xmalloc (strlen (renaming) + len0 
+                                       - yylval.ssym.stoken.length + 1);
+/*           add_name_string_cleanup (new_name);*/
+/* FIXME: add_name_string_cleanup should be defined in parse.c */
+             strcpy (new_name, renaming);
+             strcat (new_name, name0 + yylval.ssym.stoken.length);
+             result = name_lookup (new_name, err_name, token_type);
+             if (result > segments) 
+               error ("Confused by renamed symbol.");
+             return result;
+           }
+         else if (segments == 0)
+           {
+             yylval.tval = preferred_type;
+             *token_type = TYPENAME;
+             return 0;
+           } 
+       }
+
+      if (segments == 0)
+       {
+         type = lookup_primitive_typename (name);
+         if (type == NULL && STREQ ("system__address", name))
+           type = builtin_type_ada_system_address;
+         if (type != NULL)
+           {
+             yylval.tval = type;
+             *token_type = TYPENAME;
+             return 0;
+           }
+       }
+
+    NotType:
+      if (nsyms == 1) 
+       {
+         *token_type = NAME;
+         yylval.ssym.sym = syms[0];
+         yylval.ssym.msym = NULL;
+         yylval.ssym.block = blocks[0];
+         return segments;
+       }
+      else if (nsyms == 0) {
+       int i;
+       yylval.ssym.msym = ada_lookup_minimal_symbol (name);
+       if (yylval.ssym.msym != NULL)
+         {
+           yylval.ssym.sym = NULL;
+           yylval.ssym.block = NULL;
+            *token_type = NAME;
+           return segments;
+         }
+
+       for (i = yylval.ssym.stoken.length - 1; i > 0; i -= 1)
+         {
+            if (name[i] == '.')
+             { 
+               name[i] = '\0';
+               yylval.ssym.stoken.length = i;
+               break;
+             }
+           else if (name[i] == '_' && name[i-1] == '_')
+             {
+               i -= 1;
+               name[i] = '\0';
+               yylval.ssym.stoken.length = i;
+               break;
+             }
+         }
+       if (i <= 0) 
+         {
+           if (!have_full_symbols () && !have_partial_symbols ()
+               && left_block_context == NULL)
+             error ("No symbol table is loaded.  Use the \"file\" command.");
+           if (left_block_context == NULL)
+             error ("No definition of \"%s\" in current context.", 
+                    err_name);
+           else
+             error ("No definition of \"%s\" in specified context.", 
+                    err_name);
+         }
+      }
+      else 
+       {
+         *token_type = NAME;
+         yylval.ssym.sym = NULL;
+         yylval.ssym.msym = NULL;
+         if (left_block_context == NULL)
+           yylval.ssym.block = expression_context_block;
+         else
+           yylval.ssym.block = left_block_context;
+         return segments;
+       }
+    }
+}
+
+/* Returns the position within STR of the '.' in a
+   '.{WHITE}*all' component of a dotted name, or -1 if there is none. */
+static int
+find_dot_all (str)
+     const char* str;
+{
+  int i;
+  for (i = 0; str[i] != '\000'; i += 1)
+    {
+      if (str[i] == '.')
+       {
+         int i0 = i;
+         do 
+           i += 1;
+         while (isspace (str[i]));
+         if (strcmp (str+i, "all") == 0
+             && ! isalnum (str[i+3]) && str[i+3] != '_')
+           return i0;
+       }
+    }
+  return -1;
+}    
+
+/* Returns non-zero iff string SUBSEQ matches a subsequence of STR, ignoring
+   case. */
+
+static int
+subseqMatch (subseq, str)
+     const char* subseq;
+     const char* str;
+{
+  if (subseq[0] == '\0')
+    return 1;
+  else if (str[0] == '\0')
+    return 0;
+  else if (tolower (subseq[0]) == tolower (str[0]))
+    return subseqMatch (subseq+1, str+1) || subseqMatch (subseq, str+1);
+  else
+    return subseqMatch (subseq, str+1);
+}
+  
+
+static struct { const char* name; int code; } 
+attributes[] = {
+  { "address", TICK_ADDRESS },
+  { "unchecked_access", TICK_ACCESS },
+  { "unrestricted_access", TICK_ACCESS },
+  { "access", TICK_ACCESS },
+  { "first", TICK_FIRST },
+  { "last", TICK_LAST },
+  { "length", TICK_LENGTH },
+  { "max", TICK_MAX },
+  { "min", TICK_MIN },
+  { "modulus", TICK_MODULUS },
+  { "pos", TICK_POS },
+  { "range", TICK_RANGE },
+  { "size", TICK_SIZE },
+  { "tag", TICK_TAG },
+  { "val", TICK_VAL },
+  { NULL, -1 }
+};
+
+/* Return the syntactic code corresponding to the attribute name or
+   abbreviation STR.  */
+
+static int
+processAttribute (str)
+     const char* str;
+{
+  int i, k;
+
+  for (i = 0; attributes[i].code != -1; i += 1)
+    if (strcasecmp (str, attributes[i].name) == 0)
+      return attributes[i].code;
+
+  for (i = 0, k = -1; attributes[i].code != -1; i += 1)
+    if (subseqMatch (str, attributes[i].name)) 
+      {
+       if (k == -1)
+         k = i;
+       else 
+         error ("ambiguous attribute name: `%s'", str);
+      }
+  if (k == -1)
+    error ("unrecognized attribute: `%s'", str);
+
+  return attributes[k].code;
+}
+
+int
+yywrap()
+{
+  return 1;
+}
diff --git a/gdb/ada-lex.l b/gdb/ada-lex.l
new file mode 100644 (file)
index 0000000..2252d52
--- /dev/null
@@ -0,0 +1,928 @@
+/* FLEX lexer for Ada expressions, for GDB.
+   Copyright (C) 1994, 1997, 2000
+   Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/*----------------------------------------------------------------------*/
+
+/* The converted version of this file is to be included in ada-exp.y, */
+/* the Ada parser for gdb.  The function yylex obtains characters from */
+/* the global pointer lexptr.  It returns a syntactic category for */
+/* each successive token and places a semantic value into yylval */
+/* (ada-lval), defined by the parser.   */
+
+/* Run flex with (at least) the -i option (case-insensitive), and the -I */
+/* option (interactive---no unnecessary lookahead).  */
+
+DIG    [0-9]
+NUM10  ({DIG}({DIG}|_)*)
+HEXDIG [0-9a-f]
+NUM16  ({HEXDIG}({HEXDIG}|_)*)
+OCTDIG [0-7]
+LETTER [a-z_]
+ID     ({LETTER}({LETTER}|{DIG})*|"<"{LETTER}({LETTER}|{DIG})*">")
+WHITE  [ \t\n]
+TICK   ("'"{WHITE}*)
+GRAPHIC [a-z0-9 #&'()*+,-./:;<>=_|!$%?@\[\]\\^`{}~]
+OPER    ([-+*/=<>&]|"<="|">="|"**"|"/="|"and"|"or"|"xor"|"not"|"mod"|"rem"|"abs")
+
+EXP    (e[+-]{NUM10})
+POSEXP  (e"+"?{NUM10})
+
+%{
+#define NUMERAL_WIDTH 256
+#define LONGEST_SIGN ((ULONGEST) 1 << (sizeof(LONGEST) * HOST_CHAR_BIT - 1))
+
+/* Temporary staging for numeric literals. */
+static char numbuf[NUMERAL_WIDTH]; 
+ static void canonicalizeNumeral (char* s1, const char*);
+static int processInt (const char*, const char*, const char*);
+static int processReal (const char*);
+static int processId (const char*, int);
+static int processAttribute (const char*);
+static int find_dot_all (const char*);
+
+#undef YY_DECL
+#define YY_DECL static int yylex ( void ) 
+
+#undef YY_INPUT
+#define YY_INPUT(BUF, RESULT, MAX_SIZE) \
+    if ( *lexptr == '\000' ) \
+      (RESULT) = YY_NULL; \
+    else \
+      { \
+        *(BUF) = *lexptr; \
+        (RESULT) = 1; \
+       lexptr += 1; \
+      }
+
+static char *tempbuf = NULL;
+static int tempbufsize = 0;
+static int tempbuf_len;
+static struct block* left_block_context;
+
+static void resize_tempbuf (unsigned int);
+
+static void block_lookup (char*, char*);
+
+static int name_lookup (char*, char*, int*);
+
+static int find_dot_all (const char*);
+
+%}
+
+%s IN_STRING BEFORE_QUAL_QUOTE
+
+%%
+
+{WHITE}                 { }
+
+"--".*          { yyterminate(); }
+
+{NUM10}{POSEXP}  { 
+                  canonicalizeNumeral (numbuf, yytext); 
+                  return processInt (NULL, numbuf, strrchr(numbuf, 'e')+1);
+                }
+
+{NUM10}          { 
+                  canonicalizeNumeral (numbuf, yytext); 
+                  return processInt (NULL, numbuf, NULL);
+                }
+
+{NUM10}"#"{HEXDIG}({HEXDIG}|_)*"#"{POSEXP} {
+                  canonicalizeNumeral (numbuf, yytext);
+                  return processInt (numbuf,
+                                     strchr (numbuf, '#') + 1, 
+                                     strrchr(numbuf, '#') + 1);
+                }
+
+{NUM10}"#"{HEXDIG}({HEXDIG}|_)*"#" {
+                  canonicalizeNumeral (numbuf, yytext);
+                  return processInt (numbuf, strchr (numbuf, '#') + 1, NULL);
+                }
+
+"0x"{HEXDIG}+  {
+                 canonicalizeNumeral (numbuf, yytext+2);
+                 return processInt ("16#", numbuf, NULL);
+               }
+
+
+{NUM10}"."{NUM10}{EXP} {
+                  canonicalizeNumeral (numbuf, yytext); 
+                  return processReal (numbuf);
+               }
+
+{NUM10}"."{NUM10} {
+                  canonicalizeNumeral (numbuf, yytext); 
+                  return processReal (numbuf);
+               }
+
+{NUM10}"#"{NUM16}"."{NUM16}"#"{EXP} {
+                   error ("Based real literals not implemented yet.");
+               }
+
+{NUM10}"#"{NUM16}"."{NUM16}"#" {
+                   error ("Based real literals not implemented yet.");
+               }
+
+<INITIAL>"'"({GRAPHIC}|\")"'" {
+                  yylval.typed_val.type = builtin_type_ada_char;
+                  yylval.typed_val.val = yytext[1];
+                  return CHARLIT;
+               }
+
+<INITIAL>"'[\""{HEXDIG}{2}"\"]'"   {
+                   int v;
+                   yylval.typed_val.type = builtin_type_ada_char;
+                  sscanf (yytext+3, "%2x", &v);
+                  yylval.typed_val.val = v;
+                  return CHARLIT;
+               }
+
+\"{OPER}\"/{WHITE}*"(" { return processId (yytext, yyleng); }
+
+<INITIAL>\"    { 
+                  tempbuf_len = 0;
+                  BEGIN IN_STRING;
+               }
+
+<IN_STRING>{GRAPHIC}*\"  {
+                  resize_tempbuf (yyleng+tempbuf_len);
+                  strncpy (tempbuf+tempbuf_len, yytext, yyleng-1);
+                  tempbuf_len += yyleng-1;
+                  yylval.sval.ptr = tempbuf;
+                  yylval.sval.length = tempbuf_len;
+                  BEGIN INITIAL;
+                  return STRING;
+               }
+
+<IN_STRING>{GRAPHIC}*"[\""{HEXDIG}{2}"\"]" {
+                  int n;
+                  resize_tempbuf (yyleng-5+tempbuf_len+1);
+                  strncpy (tempbuf+tempbuf_len, yytext, yyleng-6);
+                  sscanf(yytext+yyleng-4, "%2x", &n);
+                  tempbuf[yyleng-6+tempbuf_len] = (char) n;
+                  tempbuf_len += yyleng-5;
+               }
+
+<IN_STRING>{GRAPHIC}*"[\"\"\"]" {
+                  int n;
+                  resize_tempbuf (yyleng-4+tempbuf_len+1);
+                  strncpy (tempbuf+tempbuf_len, yytext, yyleng-6);
+                  tempbuf[yyleng-5+tempbuf_len] = '"';
+                  tempbuf_len += yyleng-4;
+               }
+
+if             { 
+                 while (*lexptr != 'i' && *lexptr != 'I') 
+                   lexptr -= 1; 
+                 yyrestart(NULL); 
+                 return 0;
+               }
+
+       /* ADA KEYWORDS */
+
+abs            { return ABS; }
+and            { return _AND_; }
+else           { return ELSE; }
+in             { return IN; }
+mod            { return MOD; }
+new            { return NEW; }
+not            { return NOT; }
+null           { return NULL_PTR; }
+or             { return OR; }
+rem            { return REM; }
+then           { return THEN; }
+xor            { return XOR; }
+
+        /* ATTRIBUTES */
+
+{TICK}[a-zA-Z][a-zA-Z]+ { return processAttribute (yytext+1); }
+
+       /* PUNCTUATION */
+
+"=>"           { return ARROW; }
+".."           { return DOTDOT; }
+"**"           { return STARSTAR; }
+":="           { return ASSIGN; }
+"/="           { return NOTEQUAL; }
+"<="           { return LEQ; }
+">="           { return GEQ; }
+
+<BEFORE_QUAL_QUOTE>"'" { BEGIN INITIAL; return '\''; }
+
+[-&*+./:<>=|;\[\]] { return yytext[0]; }
+
+","            { if (paren_depth == 0 && comma_terminates)
+                   {
+                     lexptr -= 1;
+                     yyrestart(NULL);
+                     return 0;
+                   }
+                 else 
+                   return ',';
+               }
+
+"("            { paren_depth += 1; return '('; }
+")"            { if (paren_depth == 0) 
+                   {
+                     lexptr -= 1;
+                     yyrestart(NULL);
+                     return 0;
+                   }
+                 else 
+                   {
+                     paren_depth -= 1; 
+                     return ')';
+                   }
+               }
+
+"."{WHITE}*all  { return DOT_ALL; }
+
+"."{WHITE}*{ID} { 
+                 processId (yytext+1, yyleng-1);
+                 return DOT_ID; 
+               }
+
+{ID}({WHITE}*"."{WHITE}*({ID}|\"{OPER}\"))*(" "*"'")?  { 
+                  int all_posn = find_dot_all (yytext);
+                 int token_type, segments, k;
+                 int quote_follows;
+
+                  if (all_posn == -1 && yytext[yyleng-1] == '\'') 
+                   {
+                     quote_follows = 1;
+                     do { 
+                       yyless (yyleng-1); 
+                     } while (yytext[yyleng-1] == ' ');
+                   }
+                 else
+                   quote_follows = 0;                  
+                   
+                  if (all_posn >= 0)
+                   yyless (all_posn);
+                  processId(yytext, yyleng);
+                  segments = name_lookup (ada_mangle (yylval.ssym.stoken.ptr),
+                                         yylval.ssym.stoken.ptr, &token_type);
+                 left_block_context = NULL;
+                 for (k = yyleng; segments > 0 && k > 0; k -= 1)
+                    {
+                     if (yytext[k-1] == '.')
+                       segments -= 1;
+                     quote_follows = 0;
+                   }
+                 if (k <= 0)
+                   error ("confused by name %s", yytext);
+                 yyless (k);
+                 if (quote_follows) 
+                   BEGIN BEFORE_QUAL_QUOTE;
+                 return token_type;
+                }
+
+       /* GDB EXPRESSION CONSTRUCTS  */
+
+
+"'"[^']+"'"{WHITE}*:: {
+                  processId(yytext, yyleng-2);
+                  block_lookup (yylval.ssym.stoken.ptr, yylval.ssym.stoken.ptr);
+                  return BLOCKNAME;
+               }
+
+{ID}({WHITE}*"."{WHITE}*({ID}|\"{OPER}\"))*{WHITE}*::  { 
+                  processId(yytext, yyleng-2);
+                  block_lookup (ada_mangle (yylval.ssym.stoken.ptr),
+                                yylval.ssym.stoken.ptr);
+                  return BLOCKNAME;
+               }
+
+[{}@]          { return yytext[0]; }
+
+"$$"           { yylval.lval = -1; return LAST; }
+"$$"{DIG}+     { yylval.lval = -atoi(yytext+2); return LAST; }
+"$"            { yylval.lval = 0; return LAST; }
+"$"{DIG}+      { yylval.lval = atoi(yytext+1); return LAST; }
+
+
+       /* REGISTERS AND GDB CONVENIENCE VARIABLES */
+
+"$"({LETTER}|{DIG}|"$")+  {
+                 int c;
+                 for (c = 0; c < NUM_REGS; c++)
+                   if (REGISTER_NAME (c) &&
+                        strcmp (yytext + 1, REGISTER_NAME (c)) == 0)
+                     {
+                       yylval.lval = c;
+                       return REGNAME;
+                     }
+                 yylval.sval.ptr = yytext;
+                 yylval.sval.length = yyleng;
+                 yylval.ivar = 
+                   lookup_internalvar (copy_name (yylval.sval) + 1);
+                 return INTERNAL_VARIABLE;
+               }
+
+       /* CATCH-ALL ERROR CASE */
+
+.              { error ("Invalid character '%s' in expression.", yytext); }
+%%
+
+#include <ctype.h>
+#include <string.h>
+
+/* Initialize the lexer for processing new expression */
+void
+lexer_init (FILE* inp)
+{
+  BEGIN INITIAL;
+  yyrestart (inp);
+}
+
+
+/* Make sure that tempbuf points at an array at least N characters long. */
+
+static void
+resize_tempbuf (n)
+     unsigned int n;
+{
+  if (tempbufsize < n)
+    {
+      tempbufsize = (n+63) & ~63;
+      tempbuf = (char*) xrealloc (tempbuf, tempbufsize);
+    }
+}
+/* Copy S2 to S1, removing all underscores, and downcasing all letters. */
+
+static void
+canonicalizeNumeral (s1,s2)
+     char* s1;
+     const char* s2;
+{
+  for (; *s2 != '\000'; s2 += 1) 
+    {
+      if (*s2 != '_')
+       {
+         *s1 = tolower(*s2);
+         s1 += 1;
+       }
+    }
+  s1[0] = '\000';
+}
+
+#define HIGH_BYTE_POSN ((sizeof (ULONGEST) - 1) * HOST_CHAR_BIT)
+
+/* True (non-zero) iff DIGIT is a valid digit in radix BASE, 
+   where 2 <= BASE <= 16.  */
+
+static int
+is_digit_in_base (digit, base)
+     unsigned char digit;
+     int base;
+{
+  if (!isxdigit (digit))
+    return 0;
+  if (base <= 10)
+    return (isdigit (digit) && digit < base + '0');
+  else 
+    return (isdigit (digit) || tolower (digit) < base - 10 + 'a');
+}
+
+static int
+digit_to_int (c)
+     unsigned char c;
+{
+  if (isdigit (c))
+    return c - '0';
+  else
+    return tolower (c) - 'a' + 10;
+}
+
+/* As for strtoul, but for ULONGEST results. */
+ULONGEST
+strtoulst (num, trailer, base)
+     const char *num;
+     const char **trailer;
+     int base;
+{
+  unsigned int high_part;
+  ULONGEST result;
+  int i;
+  unsigned char lim;
+
+  if (base < 2 || base > 16)
+    {
+      errno = EINVAL;
+      return 0;
+    }
+  lim = base - 1 + '0';
+
+  result = high_part = 0;
+  for (i = 0; is_digit_in_base (num[i], base); i += 1)
+    {
+      result = result*base + digit_to_int (num[i]);
+      high_part = high_part*base + (unsigned int) (result >> HIGH_BYTE_POSN);
+      result &= ((ULONGEST) 1 << HIGH_BYTE_POSN) - 1;
+      if (high_part > 0xff) 
+       {
+         errno = ERANGE;
+         result = high_part = 0;
+         break;
+       }
+    }
+
+  if (trailer != NULL)
+    *trailer = &num[i];
+
+  return result + ((ULONGEST) high_part << HIGH_BYTE_POSN);
+}
+
+
+
+/* Interprets the prefix of NUM that consists of digits of the given BASE
+   as an integer of that BASE, with the string EXP as an exponent.
+   Puts value in yylval, and returns INT, if the string is valid.  Causes
+   an error if the number is improperly formated.   BASE, if NULL, defaults 
+   to "10", and EXP to "1". The EXP does not contain a leading 'e' or 'E'. */
+
+static int
+processInt (base0, num0, exp0)
+     const char* num0;
+     const char* base0;
+     const char* exp0;
+{
+  ULONGEST result;
+  long exp;
+  int base;
+
+  char* trailer;
+
+  if (base0 == NULL)
+    base = 10;
+  else
+    {  
+      base = strtol (base0, (char**) NULL, 10);
+      if (base < 2 || base > 16)
+       error ("Invalid base: %d.", base);
+    }
+
+  if (exp0 == NULL)
+    exp = 0;
+  else
+    exp = strtol(exp0, (char**) NULL, 10);
+
+  errno = 0;
+  result = strtoulst (num0, &trailer, base);
+  if (errno == ERANGE)
+    error ("Integer literal out of range");
+  if (isxdigit(*trailer))
+    error ("Invalid digit `%c' in based literal", *trailer);
+
+  while (exp > 0) 
+    {
+      if (result > (ULONG_MAX / base))
+       error ("Integer literal out of range");
+      result *= base;
+      exp -= 1;
+    }
+    
+  if ((result >> (TARGET_INT_BIT-1)) == 0)
+    yylval.typed_val.type = builtin_type_ada_int;
+  else if ((result >> (TARGET_LONG_BIT-1)) == 0)
+    yylval.typed_val.type = builtin_type_ada_long;
+  else if (((result >> (TARGET_LONG_BIT-1)) >> 1) == 0)
+    {
+      /* We have a number representable as an unsigned integer quantity.
+         For consistency with the C treatment, we will treat it as an 
+        anonymous modular (unsigned) quantity.  Alas, the types are such
+        that we need to store .val as a signed quantity.  Sorry 
+         for the mess, but C doesn't officially guarantee that a simple
+         assignment does the trick (no, it doesn't; read the reference manual).
+       */
+      yylval.typed_val.type = builtin_type_unsigned_long;
+      if (result & LONGEST_SIGN)
+       yylval.typed_val.val = 
+         (LONGEST) (result & ~LONGEST_SIGN) 
+         - (LONGEST_SIGN>>1) - (LONGEST_SIGN>>1);
+      else
+       yylval.typed_val.val = (LONGEST) result;
+      return INT;
+    }
+  else 
+    yylval.typed_val.type = builtin_type_ada_long_long;
+
+  yylval.typed_val.val = (LONGEST) result;
+  return INT;
+}
+
+static int
+processReal (num0)
+     const char* num0;
+{
+  if (sizeof (DOUBLEST) <= sizeof (float))
+    sscanf (num0, "%g", &yylval.typed_val_float.dval);
+  else if (sizeof (DOUBLEST) <= sizeof (double))
+    sscanf (num0, "%lg", &yylval.typed_val_float.dval);
+  else
+    {
+#ifdef PRINTF_HAS_LONG_DOUBLE
+      sscanf (num0, "%Lg", &yylval.typed_val_float.dval);
+#else
+      /* Scan it into a double, then convert and assign it to the 
+        long double.  This at least wins with values representable 
+        in the range of doubles. */
+      double temp;
+      sscanf (num0, "%lg", &temp);
+      yylval.typed_val_float.dval = temp;
+#endif
+    }
+
+  yylval.typed_val_float.type = builtin_type_ada_float;
+  if (sizeof(DOUBLEST) >= TARGET_DOUBLE_BIT / TARGET_CHAR_BIT)
+    yylval.typed_val_float.type = builtin_type_ada_double;
+  if (sizeof(DOUBLEST) >= TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT)
+    yylval.typed_val_float.type = builtin_type_ada_long_double;
+
+  return FLOAT;
+}
+
+static int
+processId (name0, len)
+     const char *name0;
+     int len;
+{
+  char* name = xmalloc (len + 11);
+  int i0, i;
+  
+/*  add_name_string_cleanup (name); */
+/* FIXME: add_name_string_cleanup should be defined in parse.c */
+  while (len > 0 && isspace (name0[len-1]))
+    len -= 1;
+  i = i0 = 0;
+  while (i0 < len) 
+    {
+      if (isalnum (name0[i0]))
+       {
+         name[i] = tolower (name0[i0]);
+         i += 1; i0 += 1;
+       }
+      else switch (name0[i0]) 
+       {
+       default:
+         name[i] = name0[i0];
+         i += 1; i0 += 1;
+         break;
+       case ' ': case '\t':
+         i0 += 1;
+         break;
+       case '\'':
+         i0 += 1;
+         while (i0 < len && name0[i0] != '\'')
+           {
+             name[i] = name0[i0];
+             i += 1; i0 += 1;
+           }
+         i0 += 1;
+         break;
+       case '<':
+         i0 += 1;
+         while (i0 < len && name0[i0] != '>')
+           {
+             name[i] = name0[i0];
+             i += 1; i0 += 1;
+           }
+         i0 += 1;
+         break;
+       }
+    }
+  name[i] = '\000';
+
+  yylval.ssym.sym = NULL;
+  yylval.ssym.stoken.ptr = name;
+  yylval.ssym.stoken.length = i;
+  return NAME;
+}
+
+static void 
+block_lookup (name, err_name)
+     char* name;
+     char* err_name;
+{
+  struct symbol** syms;
+  struct block** blocks;
+  int nsyms;
+  struct symtab *symtab;
+  nsyms = ada_lookup_symbol_list (name, left_block_context,
+                                 VAR_NAMESPACE, &syms, &blocks);
+  if (left_block_context == NULL &&
+      (nsyms == 0 || SYMBOL_CLASS (syms[0]) != LOC_BLOCK))
+    symtab = lookup_symtab (name);
+  else
+    symtab = NULL;
+
+  if (symtab != NULL)
+    left_block_context = yylval.bval =
+      BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
+  else if (nsyms == 0 || SYMBOL_CLASS (syms[0]) != LOC_BLOCK)
+    {
+      if (left_block_context == NULL)
+       error ("No file or function \"%s\".", err_name);
+      else
+       error ("No function \"%s\" in specified context.", err_name);
+    }
+  else 
+    {
+      left_block_context = yylval.bval = SYMBOL_BLOCK_VALUE (syms[0]); 
+      if (nsyms > 1)
+       warning ("Function name \"%s\" ambiguous here", err_name);
+    }
+}
+
+/* Look up NAME0 (assumed to be mangled) as a name in VAR_NAMESPACE,
+   setting *TOKEN_TYPE to NAME or TYPENAME, depending on what is
+   found.  Try first the entire name, then the name without the last 
+   segment (i.e., after the last .id), etc., and return the number of
+   segments that had to be removed to get a match.  Calls error if no
+   matches are found, using ERR_NAME in any error message.  When
+   exactly one symbol match is found, it is placed in yylval. */
+static int
+name_lookup (name0, err_name, token_type)
+     char* name0;
+     char* err_name;
+     int* token_type;
+{
+  struct symbol** syms;
+  struct block** blocks;
+  struct type* type;
+  int len0 = strlen (name0);
+  char* name = savestring (name0, len0);
+  int nsyms;
+  int segments;
+/*  add_name_string_cleanup (name);*/
+/* FIXME: add_name_string_cleanup should be defined in parse.c */
+  yylval.ssym.stoken.ptr = name;
+  yylval.ssym.stoken.length = strlen (name);
+  for (segments = 0; ; segments += 1)
+    {
+      struct type* preferred_type;
+      int i, preferred_index;
+
+      if (left_block_context == NULL) 
+       nsyms = ada_lookup_symbol_list (name, expression_context_block, 
+                                       VAR_NAMESPACE, &syms, &blocks);
+      else
+       nsyms = ada_lookup_symbol_list (name, left_block_context, 
+                                       VAR_NAMESPACE, &syms, &blocks);
+
+      /* Check for a type definition. */
+
+      /* Look for a symbol that doesn't denote void.  This is (I think) a */
+      /* temporary kludge to get around problems in GNAT output. */
+      preferred_index = -1; preferred_type = NULL;
+      for (i = 0; i < nsyms; i += 1)
+       switch (SYMBOL_CLASS (syms[i])) 
+         {
+         case LOC_TYPEDEF:
+           if (ada_prefer_type (SYMBOL_TYPE (syms[i]), preferred_type))
+             {
+               preferred_index = i;
+               preferred_type = SYMBOL_TYPE (syms[i]);
+             }
+           break;
+         case LOC_REGISTER:
+         case LOC_ARG:
+         case LOC_REF_ARG:
+         case LOC_REGPARM:
+         case LOC_REGPARM_ADDR:
+         case LOC_LOCAL:
+         case LOC_LOCAL_ARG:
+         case LOC_BASEREG:
+         case LOC_BASEREG_ARG:
+           goto NotType;
+         default:
+           break;
+         }
+      if (preferred_type != NULL)
+       {
+/*       if (TYPE_CODE (preferred_type) == TYPE_CODE_VOID)
+           error ("`%s' matches only void type name(s)", 
+                  ada_demangle (name));
+*/
+/* FIXME: ada_demangle should be defined in defs.h, and is located in ada-lang.c */
+/*       else*/ if (ada_is_object_renaming (syms[preferred_index]))
+           {
+             yylval.ssym.sym = syms[preferred_index];
+             *token_type = OBJECT_RENAMING;
+             return segments;
+           } 
+         else if (ada_renaming_type (SYMBOL_TYPE (syms[preferred_index])) 
+                   != NULL)
+           {
+             int result;
+             const char* renaming = 
+               ada_simple_renamed_entity (syms[preferred_index]);
+             char* new_name = xmalloc (strlen (renaming) + len0 
+                                       - yylval.ssym.stoken.length + 1);
+/*           add_name_string_cleanup (new_name);*/
+/* FIXME: add_name_string_cleanup should be defined in parse.c */
+             strcpy (new_name, renaming);
+             strcat (new_name, name0 + yylval.ssym.stoken.length);
+             result = name_lookup (new_name, err_name, token_type);
+             if (result > segments) 
+               error ("Confused by renamed symbol.");
+             return result;
+           }
+         else if (segments == 0)
+           {
+             yylval.tval = preferred_type;
+             *token_type = TYPENAME;
+             return 0;
+           } 
+       }
+
+      if (segments == 0)
+       {
+         type = lookup_primitive_typename (name);
+         if (type == NULL && STREQ ("system__address", name))
+           type = builtin_type_ada_system_address;
+         if (type != NULL)
+           {
+             yylval.tval = type;
+             *token_type = TYPENAME;
+             return 0;
+           }
+       }
+
+    NotType:
+      if (nsyms == 1) 
+       {
+         *token_type = NAME;
+         yylval.ssym.sym = syms[0];
+         yylval.ssym.msym = NULL;
+         yylval.ssym.block = blocks[0];
+         return segments;
+       }
+      else if (nsyms == 0) {
+       int i;
+       yylval.ssym.msym = ada_lookup_minimal_symbol (name);
+       if (yylval.ssym.msym != NULL)
+         {
+           yylval.ssym.sym = NULL;
+           yylval.ssym.block = NULL;
+            *token_type = NAME;
+           return segments;
+         }
+
+       for (i = yylval.ssym.stoken.length - 1; i > 0; i -= 1)
+         {
+            if (name[i] == '.')
+             { 
+               name[i] = '\0';
+               yylval.ssym.stoken.length = i;
+               break;
+             }
+           else if (name[i] == '_' && name[i-1] == '_')
+             {
+               i -= 1;
+               name[i] = '\0';
+               yylval.ssym.stoken.length = i;
+               break;
+             }
+         }
+       if (i <= 0) 
+         {
+           if (!have_full_symbols () && !have_partial_symbols ()
+               && left_block_context == NULL)
+             error ("No symbol table is loaded.  Use the \"file\" command.");
+           if (left_block_context == NULL)
+             error ("No definition of \"%s\" in current context.", 
+                    err_name);
+           else
+             error ("No definition of \"%s\" in specified context.", 
+                    err_name);
+         }
+      }
+      else 
+       {
+         *token_type = NAME;
+         yylval.ssym.sym = NULL;
+         yylval.ssym.msym = NULL;
+         if (left_block_context == NULL)
+           yylval.ssym.block = expression_context_block;
+         else
+           yylval.ssym.block = left_block_context;
+         return segments;
+       }
+    }
+}
+
+/* Returns the position within STR of the '.' in a
+   '.{WHITE}*all' component of a dotted name, or -1 if there is none. */
+static int
+find_dot_all (str)
+     const char* str;
+{
+  int i;
+  for (i = 0; str[i] != '\000'; i += 1)
+    {
+      if (str[i] == '.')
+       {
+         int i0 = i;
+         do 
+           i += 1;
+         while (isspace (str[i]));
+         if (strcmp (str+i, "all") == 0
+             && ! isalnum (str[i+3]) && str[i+3] != '_')
+           return i0;
+       }
+    }
+  return -1;
+}    
+
+/* Returns non-zero iff string SUBSEQ matches a subsequence of STR, ignoring
+   case. */
+
+static int
+subseqMatch (subseq, str)
+     const char* subseq;
+     const char* str;
+{
+  if (subseq[0] == '\0')
+    return 1;
+  else if (str[0] == '\0')
+    return 0;
+  else if (tolower (subseq[0]) == tolower (str[0]))
+    return subseqMatch (subseq+1, str+1) || subseqMatch (subseq, str+1);
+  else
+    return subseqMatch (subseq, str+1);
+}
+  
+
+static struct { const char* name; int code; } 
+attributes[] = {
+  { "address", TICK_ADDRESS },
+  { "unchecked_access", TICK_ACCESS },
+  { "unrestricted_access", TICK_ACCESS },
+  { "access", TICK_ACCESS },
+  { "first", TICK_FIRST },
+  { "last", TICK_LAST },
+  { "length", TICK_LENGTH },
+  { "max", TICK_MAX },
+  { "min", TICK_MIN },
+  { "modulus", TICK_MODULUS },
+  { "pos", TICK_POS },
+  { "range", TICK_RANGE },
+  { "size", TICK_SIZE },
+  { "tag", TICK_TAG },
+  { "val", TICK_VAL },
+  { NULL, -1 }
+};
+
+/* Return the syntactic code corresponding to the attribute name or
+   abbreviation STR.  */
+
+static int
+processAttribute (str)
+     const char* str;
+{
+  int i, k;
+
+  for (i = 0; attributes[i].code != -1; i += 1)
+    if (strcasecmp (str, attributes[i].name) == 0)
+      return attributes[i].code;
+
+  for (i = 0, k = -1; attributes[i].code != -1; i += 1)
+    if (subseqMatch (str, attributes[i].name)) 
+      {
+       if (k == -1)
+         k = i;
+       else 
+         error ("ambiguous attribute name: `%s'", str);
+      }
+  if (k == -1)
+    error ("unrecognized attribute: `%s'", str);
+
+  return attributes[k].code;
+}
+
+int
+yywrap()
+{
+  return 1;
+}
diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c
new file mode 100644 (file)
index 0000000..23dc105
--- /dev/null
@@ -0,0 +1,806 @@
+/* file ada-tasks.c: Ada tasking control for GDB
+   Copyright 1997 Free Software Foundation, Inc.
+   Contributed by Ada Core Technologies, Inc
+.
+   This file is part of GDB.
+
+   [$Id$]
+   Authors: Roch-Alexandre Nomine Beguin, Arnaud Charlet <charlet@gnat.com>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+*/
+
+#include <ctype.h> 
+#include "defs.h" 
+#include "command.h" 
+#include "value.h"
+#include "language.h"
+#include "inferior.h"
+#include "symtab.h"
+#include "target.h"
+#include "gdbcore.h"
+
+#if (defined(__alpha__) && defined(__osf__) && !defined(__alpha_vxworks))
+#include <sys/procfs.h>
+#endif
+
+#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
+#include "gregset.h"
+#endif 
+
+#include "ada-lang.h"
+
+/* FIXME: move all this conditional compilation in description
+   files or in configure.in */
+
+#if defined (VXWORKS_TARGET)
+#define THREAD_TO_PID(tid,lwpid) (tid)
+
+#elif defined (linux)
+#define THREAD_TO_PID(tid,lwpid) (0)
+
+#elif (defined (sun) && defined (__SVR4))
+#define THREAD_TO_PID thread_to_pid
+
+#elif defined (sgi) || defined (__WIN32__) || defined (hpux)
+#define THREAD_TO_PID(tid,lwpid) ((int)lwpid)
+
+#else
+#define THREAD_TO_PID(tid,lwpid) (0)
+#endif
+
+#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
+#define THREAD_FETCH_REGISTERS dec_thread_fetch_registers
+#define GET_CURRENT_THREAD dec_thread_get_current_thread
+extern int dec_thread_get_registers (gdb_gregset_t *, gdb_fpregset_t *);
+#endif
+
+#if defined (_AIX)
+#define THREAD_FETCH_REGISTERS aix_thread_fetch_registers
+#define GET_CURRENT_THREAD aix_thread_get_current_thread
+#endif
+
+#if defined(VXWORKS_TARGET)
+#define GET_CURRENT_THREAD() ((void*)inferior_pid)
+#define THREAD_FETCH_REGISTERS() (-1)
+
+#elif defined (sun) && defined (__SVR4)
+#define GET_CURRENT_THREAD solaris_thread_get_current_thread
+#define THREAD_FETCH_REGISTERS() (-1)
+extern void *GET_CURRENT_THREAD();
+
+#elif defined (_AIX) || (defined(__alpha__) && defined(__osf__))
+extern void *GET_CURRENT_THREAD();
+
+#elif defined (__WIN32__) || defined (hpux)
+#define GET_CURRENT_THREAD() (inferior_pid)
+#define THREAD_FETCH_REGISTERS() (-1)
+
+#else
+#define GET_CURRENT_THREAD() (NULL)
+#define THREAD_FETCH_REGISTERS() (-1)
+#endif
+
+#define KNOWN_TASKS_NAME "system__tasking__debug__known_tasks"
+
+#define READ_MEMORY(addr, var) read_memory (addr, (char*) &var, sizeof (var))
+/* external declarations */
+
+extern struct value* find_function_in_inferior (char *);
+
+/* Global visible variables */
+
+struct task_entry *task_list = NULL;
+int ada__tasks_check_symbol_table = 1;
+void *pthread_kern_addr = NULL;
+
+#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
+gdb_gregset_t gregset_saved;
+gdb_fpregset_t fpregset_saved;
+#endif
+
+/* The maximum number of tasks known to the Ada runtime */
+const int MAX_NUMBER_OF_KNOWN_TASKS = 1000;
+
+/* the current task */
+int current_task = -1, current_task_id = -1, current_task_index;
+void *current_thread, *current_lwp;
+
+char *ada_task_states[] =
+{
+  "Unactivated",
+  "Runnable",
+  "Terminated",
+  "Child Activation Wait",
+  "Accept Statement",
+  "Waiting on entry call",
+  "Async Select Wait",
+  "Delay Sleep",
+  "Child Termination Wait",
+  "Wait Child in Term Alt",
+  "",
+  "",
+  "",
+  "",
+  "Asynchronous Hold"
+};
+
+/* Global internal types */
+
+static char *ada_long_task_states[] =
+{
+  "Unactivated",
+  "Runnable",
+  "Terminated",
+  "Waiting for child activation",
+  "Blocked in accept statement",
+  "Waiting on entry call",
+  "Asynchronous Selective Wait",
+  "Delay Sleep",
+  "Waiting for children termination",
+  "Waiting for children in terminate alternative",
+  "",
+  "",
+  "",
+  "",
+  "Asynchronous Hold"
+};
+
+/* Global internal variables */
+
+static int highest_task_num = 0;
+int thread_support = 0; /* 1 if the thread library in use is supported */
+static int gdbtk_task_initialization = 0;
+
+static int add_task_entry (p_task_id, index)
+     void *p_task_id;
+     int index;
+{
+  struct task_entry *new_task_entry = NULL;
+  struct task_entry *pt;
+
+  highest_task_num++;
+  new_task_entry = malloc (sizeof (struct task_entry));
+  new_task_entry->task_num = highest_task_num;
+  new_task_entry->task_id = p_task_id;
+  new_task_entry->known_tasks_index = index;
+  new_task_entry->next_task = NULL;
+  pt = task_list;
+  if (pt)
+    {
+      while (pt->next_task)
+       pt = pt->next_task;
+      pt->next_task = new_task_entry;
+      pt->stack_per = 0;
+    }
+  else task_list = new_task_entry;
+  return new_task_entry->task_num;
+}
+
+int 
+get_entry_number (p_task_id)
+     void *p_task_id;
+{
+  struct task_entry *pt;
+
+  pt = task_list;
+  while (pt != NULL)
+    {
+      if (pt->task_id == p_task_id)
+       return pt->task_num;
+      pt = pt->next_task;
+    }
+  return 0;
+}
+
+static struct task_entry *get_thread_entry_vptr (thread)
+     void *thread;
+{
+  struct task_entry *pt;
+
+  pt = task_list;
+  while (pt != NULL)
+    {
+      if (pt->thread == thread)
+      return pt;
+      pt = pt->next_task;
+    }
+  return 0;
+}
+
+static struct task_entry *get_entry_vptr (p_task_num)
+     int p_task_num;
+{
+  struct task_entry *pt;
+
+  pt = task_list;
+  while (pt)
+    {
+      if (pt->task_num == p_task_num)
+       return pt;
+      pt = pt->next_task;
+    }
+  return NULL;
+}
+
+void init_task_list ()
+{
+  struct task_entry *pt, *old_pt;
+
+  pt = task_list;
+  while (pt)
+    {
+      old_pt = pt;
+      pt = pt->next_task;
+      free (old_pt);
+    };
+  task_list = NULL;
+  highest_task_num = 0;
+}
+
+int valid_task_id (task)
+     int task;
+{
+  return get_entry_vptr (task) != NULL;
+}
+
+void *get_self_id ()
+{
+  struct value* val;
+  void *self_id;
+  int result;
+  struct task_entry *ent;
+  extern int do_not_insert_breakpoints;
+
+#if !((defined(sun) && defined(__SVR4)) || defined(VXWORKS_TARGET) || defined(__WIN32__))
+  if (thread_support)
+#endif
+    {
+      ent = get_thread_entry_vptr (GET_CURRENT_THREAD ());
+      return ent ? ent->task_id : 0;
+    }
+
+  /* FIXME: calling a function in the inferior with a multithreaded application
+     is not reliable, so return NULL if there is no safe way to get the current
+     task */
+  return NULL;
+}
+
+int get_current_task ()
+{
+  int result;
+  
+  /* FIXME: language_ada should be defined in defs.h */
+  /*  if (current_language->la_language != language_ada) return -1; */
+
+  result = get_entry_number (get_self_id ());
+
+  /* return -1 if not found */
+  return result == 0 ? -1 : result;
+}
+
+/* Print detailed information about specified task */
+
+static void
+info_task (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  void *temp_task;
+  struct task_entry *pt, *pt2;
+  void *self_id, *caller;
+  struct task_fields atcb, atcb2;
+  struct entry_call call;
+  int bounds [2];
+  char image [256];
+  int num;
+
+  /* FIXME: language_ada should be defined in defs.h */
+  /*  if (current_language->la_language != language_ada) 
+    { 
+      printf_filtered ("The current language does not support tasks.\n"); 
+      return; 
+    } 
+  */
+  pt = get_entry_vptr (atoi (arg));
+  if (pt == NULL)
+    {
+      printf_filtered ("Task %s not found.\n", arg); 
+      return; 
+    }
+
+  temp_task = pt->task_id;
+
+  /* read the atcb in the inferior */
+  READ_MEMORY ((CORE_ADDR) temp_task, atcb);
+
+  /* print the Ada task id */
+  printf_filtered ("Ada Task: %p\n", temp_task);
+
+  /* print the name of the task */
+  if (atcb.image.P_ARRAY != NULL) {
+    READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.image.P_BOUNDS), bounds);
+    bounds [1] = EXTRACT_INT (bounds [1]);
+    read_memory ((CORE_ADDR) EXTRACT_ADDRESS (atcb.image.P_ARRAY),
+                 (char*) &image, bounds [1]);
+    printf_filtered ("Name: %.*s\n", bounds [1], image);
+  }
+  else printf_filtered ("<no name>\n");
+
+  /* print the thread id */
+
+  if ((long) pt->thread < 65536)
+    printf_filtered ("Thread: %ld\n", (long int) pt->thread);
+  else
+    printf_filtered ("Thread: %p\n", pt->thread);
+
+  if ((long) pt->lwp != 0)
+    {
+      if ((long) pt->lwp < 65536)
+        printf_filtered ("LWP: %ld\n", (long int) pt->lwp);
+      else
+        printf_filtered ("LWP: %p\n", pt->lwp);
+    }
+
+  /* print the parent gdb task id */
+  num = get_entry_number (EXTRACT_ADDRESS (atcb.parent));
+  if (num != 0)
+    {
+      printf_filtered ("Parent: %d", num);
+      pt2 = get_entry_vptr (num);
+      READ_MEMORY ((CORE_ADDR) pt2->task_id, atcb2);
+
+      /* print the name of the task */
+      if (atcb2.image.P_ARRAY != NULL) {
+        READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_BOUNDS),
+                     bounds);
+        bounds [1] = EXTRACT_INT (bounds [1]);
+        read_memory ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_ARRAY),
+                     (char*) &image, bounds [1]);
+        printf_filtered (" (%.*s)\n", bounds [1], image);
+      }
+      else
+        printf_filtered ("\n");
+    }
+  else
+    printf_filtered ("No parent\n");
+
+  /* print the base priority of the task */
+  printf_filtered ("Base Priority: %d\n", EXTRACT_INT (atcb.priority));
+
+  /* print the current state of the task */
+
+  /* check if this task is accepting a rendezvous */
+  if (atcb.call == NULL)
+    caller = NULL;
+  else {
+    READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.call), call);
+    caller = EXTRACT_ADDRESS (call.self);
+  }
+  if (caller != NULL)
+    {
+      num = get_entry_number (caller);
+      printf_filtered ("Accepting rendezvous with %d", num);
+
+      if (num != 0)
+       {
+         pt2 = get_entry_vptr (num);
+         READ_MEMORY ((CORE_ADDR) pt2->task_id, atcb2);
+
+         /* print the name of the task */
+         if (atcb2.image.P_ARRAY != NULL) {
+           READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_BOUNDS),
+                         bounds);
+            bounds [1] = EXTRACT_INT (bounds [1]);
+           read_memory ((CORE_ADDR) EXTRACT_ADDRESS (atcb2.image.P_ARRAY),
+                         (char*) &image, bounds [1]);
+           printf_filtered (" (%.*s)\n", bounds [1], image);
+         }
+         else
+           printf_filtered ("\n");
+       }
+      else
+       printf_filtered ("\n");
+    }
+  else
+    printf_filtered ("State: %s\n", ada_long_task_states [atcb.state]);
+}
+
+#if 0
+
+/* A useful function that shows the alignment of all the fields in the
+   tasks_fields structure
+ */
+
+print_align ()
+{
+  struct task_fields tf;
+  void *tf_base             = &(tf);
+  void *tf_state            = &(tf.state);
+  void *tf_entry_num        = &(tf.entry_num);
+  void *tf_parent           = &(tf.parent);
+  void *tf_priority         = &(tf.priority);
+  void *tf_current_priority = &(tf.current_priority);
+  void *tf_image            = &(tf.image);
+  void *tf_call             = &(tf.call);
+  void *tf_thread           = &(tf.thread);
+  void *tf_lwp              = &(tf.lwp);
+  printf_filtered ("\n");
+  printf_filtered ("(tf_base = 0x%x)\n", tf_base);
+  printf_filtered ("task_fields.entry_num        at %3d (0x%x)\n", tf_entry_num - tf_base, tf_entry_num);
+  printf_filtered ("task_fields.state            at %3d (0x%x)\n", tf_state - tf_base, tf_state);
+  printf_filtered ("task_fields.parent           at %3d (0x%x)\n", tf_parent - tf_base, tf_parent);
+  printf_filtered ("task_fields.priority         at %3d (0x%x)\n", tf_priority - tf_base, tf_priority);
+  printf_filtered ("task_fields.current_priority at %3d (0x%x)\n", tf_current_priority - tf_base, tf_current_priority);
+  printf_filtered ("task_fields.image            at %3d (0x%x)\n", tf_image - tf_base, tf_image);
+  printf_filtered ("task_fields.call             at %3d (0x%x)\n", tf_call - tf_base, tf_call);
+  printf_filtered ("task_fields.thread           at %3d (0x%x)\n", tf_thread - tf_base, tf_thread);
+  printf_filtered ("task_fields.lwp              at %3d (0x%x)\n", tf_lwp - tf_base, tf_lwp);
+  printf_filtered ("\n"); 
+}
+#endif
+
+/* Print information about currently known tasks */
+
+static void
+info_tasks (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  struct value* val;
+  int i, task_number, state;
+  void *temp_task, *temp_tasks [MAX_NUMBER_OF_KNOWN_TASKS];
+  struct task_entry *pt;
+  void *self_id, *caller, *thread_id=NULL;
+  struct task_fields atcb;
+  struct entry_call call;
+  int bounds [2];
+  char image [256];
+  int size;
+  char car;
+
+#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
+  pthreadTeb_t thr;
+  gdb_gregset_t regs;
+#endif
+
+  static struct symbol *sym;
+  static struct minimal_symbol *msym;
+  static void *known_tasks_addr = NULL;
+
+  int init_only = gdbtk_task_initialization;
+  gdbtk_task_initialization = 0;
+
+  task_number = 0;
+
+  if (PIDGET(inferior_ptid) == 0)
+    {
+      printf_filtered ("The program is not being run under gdb. ");
+      printf_filtered ("Use 'run' or 'attach' first.\n");
+      return;
+    }
+
+  if (ada__tasks_check_symbol_table)
+    {
+      thread_support = 0;
+#if (defined(__alpha__) && defined(__osf__) & !defined(VXWORKS_TARGET)) || \
+    defined (_AIX)
+      thread_support = 1;
+#endif
+
+      msym = lookup_minimal_symbol (KNOWN_TASKS_NAME, NULL, NULL);
+      if (msym != NULL)
+       known_tasks_addr = (void *) SYMBOL_VALUE_ADDRESS (msym);
+      else
+#ifndef VXWORKS_TARGET
+       return; 
+#else
+       {
+         if (target_lookup_symbol (KNOWN_TASKS_NAME, &known_tasks_addr) != 0)
+           return;
+       }
+#endif
+
+      ada__tasks_check_symbol_table = 0;
+    }
+
+  if (known_tasks_addr == NULL)
+    return;
+
+#if !((defined(sun) && defined(__SVR4)) || defined(VXWORKS_TARGET) || defined(__WIN32__) || defined (hpux))
+  if (thread_support)
+#endif
+    thread_id = GET_CURRENT_THREAD ();
+
+  /* then we get a list of tasks created */
+
+  init_task_list ();
+
+  READ_MEMORY ((CORE_ADDR) known_tasks_addr, temp_tasks);
+
+  for (i=0; i<MAX_NUMBER_OF_KNOWN_TASKS; i++)
+    {
+      temp_task = EXTRACT_ADDRESS (temp_tasks[i]);
+
+      if (temp_task != NULL)
+        {
+          task_number = get_entry_number (temp_task);
+          if (task_number == 0)
+           task_number = add_task_entry (temp_task, i);
+        }
+    }      
+
+  /* Return without printing anything if this function was called in
+     order to init GDBTK tasking. */
+
+  if (init_only) return;
+
+  /* print the header */
+
+#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
+  printf_filtered
+   ("  ID       TID P-ID Pri Stack  %% State                  Name\n");
+#else
+  printf_filtered ("  ID       TID P-ID Pri State                  Name\n");
+#endif
+
+  /* Now that we have a list of task id's, we can print them */
+  pt = task_list;
+  while (pt)
+    {
+      temp_task = pt->task_id;
+
+      /* read the atcb in the inferior */
+      READ_MEMORY ((CORE_ADDR) temp_task, atcb);
+
+      /* store the thread id for future use */
+      pt->thread = EXTRACT_ADDRESS (atcb.thread);
+
+#if defined (linux)
+      pt->lwp = (void *) THREAD_TO_PID (atcb.thread, 0);
+#else
+      pt->lwp = EXTRACT_ADDRESS (atcb.lwp);
+#endif
+
+      /* print a star if this task is the current one */
+      if (thread_id)
+#if defined (__WIN32__) || defined (SGI) || defined (hpux)
+       printf_filtered (pt->lwp == thread_id ? "*" : " ");
+#else
+       printf_filtered (pt->thread == thread_id ? "*" : " ");
+#endif
+
+      /* print the gdb task id */
+      printf_filtered ("%3d", pt->task_num);
+
+      /* print the Ada task id */
+#ifndef VXWORKS_TARGET
+      printf_filtered (" %9lx", (long) temp_task);
+#else
+#ifdef TARGET_64
+      printf_filtered (" %#9lx", (unsigned long)pt->thread & 0x3ffffffffff);
+#else
+      printf_filtered (" %#9lx", (long)pt->thread);
+#endif
+#endif
+
+      /* print the parent gdb task id */
+      printf_filtered
+        (" %4d", get_entry_number (EXTRACT_ADDRESS (atcb.parent)));
+
+      /* print the base priority of the task */
+      printf_filtered (" %3d", EXTRACT_INT (atcb.priority));
+
+#if defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET)
+      if (pt->task_num == 1 || atcb.state == Terminated)
+       {
+          printf_filtered ("  Unknown");
+         goto next;
+       }
+
+      read_memory ((CORE_ADDR)atcb.thread, &thr, sizeof (thr));
+      current_thread = atcb.thread;
+      regs.regs [SP_REGNUM] = 0;
+      if (dec_thread_get_registers (&regs, NULL) == 0) {
+       pt->stack_per = (100 * ((long)thr.__stack_base -
+       regs.regs [SP_REGNUM])) / thr.__stack_size;
+       /* if the thread is terminated but still there, the
+       stack_base/size values are erroneous. Try to patch it */
+       if (pt->stack_per < 0 || pt->stack_per > 100) pt->stack_per = 0;
+      }
+
+      /* print information about stack space used in the thread */
+      if (thr.__stack_size < 1024*1024)
+       {
+         size = thr.__stack_size / 1024;
+         car = 'K';
+       }
+      else if (thr.__stack_size < 1024*1024*1024)
+       {
+         size = thr.__stack_size / 1024 / 1024;
+         car = 'M';
+       }
+      else /* Who knows... */
+       {
+         size = thr.__stack_size / 1024 / 1024 / 1024;
+         car = 'G';
+       }
+      printf_filtered (" %4d%c %2d", size, car, pt->stack_per);
+next:
+#endif
+
+      /* print the current state of the task */
+
+      /* check if this task is accepting a rendezvous */
+      if (atcb.call == NULL)
+       caller = NULL;
+      else {
+       READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.call), call);
+       caller = EXTRACT_ADDRESS (call.self);
+      }
+      if (caller != NULL)
+       printf_filtered (" Accepting RV with %-4d", get_entry_number (caller));
+      else
+       {
+         state = atcb.state;
+#if defined (__WIN32__) || defined (SGI) || defined (hpux)
+         if (state == Runnable && (thread_id && pt->lwp == thread_id))
+#else
+         if (state == Runnable && (thread_id && pt->thread == thread_id))
+#endif
+           /* Replace "Runnable" by "Running" if this is the current task */
+           printf_filtered (" %-22s", "Running");
+         else
+           printf_filtered (" %-22s", ada_task_states [state]);
+       }
+
+      /* finally, print the name of the task */
+      if (atcb.image.P_ARRAY != NULL) {
+        READ_MEMORY ((CORE_ADDR) EXTRACT_ADDRESS (atcb.image.P_BOUNDS), bounds);
+        bounds [1] = EXTRACT_INT (bounds [1]);
+        read_memory ((CORE_ADDR) EXTRACT_ADDRESS (atcb.image.P_ARRAY),
+                     (char*)&image, bounds [1]);
+        printf_filtered (" %.*s\n", bounds [1], image);
+      }
+      else printf_filtered (" <no name>\n");
+
+      pt = pt->next_task;
+    }
+}
+
+/* Task list initialization for GDB-Tk.  We basically use info_tasks()
+   to initialize our variables, but abort that function before we
+   actually print anything. */
+
+int
+gdbtk_tcl_tasks_initialize ()
+{
+  gdbtk_task_initialization = 1;
+  info_tasks ("", gdb_stdout);
+
+  return (task_list != NULL);
+}
+
+static void
+info_tasks_command (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+   if (arg == NULL || *arg == '\000')
+      info_tasks (arg, from_tty);
+   else
+      info_task (arg, from_tty);
+}
+
+/* Switch from one thread to another. */
+
+static void
+switch_to_thread (ptid_t ptid)
+
+{
+  if (ptid_equal (ptid, inferior_ptid))
+    return;
+
+  inferior_ptid = ptid;
+  flush_cached_frames ();
+  registers_changed ();
+  stop_pc = read_pc ();
+  select_frame (get_current_frame ());
+}
+
+/* Switch to a specified task. */
+
+static int task_switch (tid, lwpid)
+     void *tid, *lwpid;
+{
+  int res = 0, pid;
+
+  if (thread_support)
+    {
+      flush_cached_frames ();
+
+      if (current_task != current_task_id)
+       {
+         res = THREAD_FETCH_REGISTERS ();
+       }
+      else
+       {
+#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
+         supply_gregset (&gregset_saved);
+         supply_fpregset (&fpregset_saved);
+#endif
+       }
+
+      if (res == 0) stop_pc = read_pc();
+      select_frame (get_current_frame ());
+      return res;
+    }
+
+  return -1;
+}
+
+static void task_command (tidstr, from_tty)
+     char *tidstr;
+     int from_tty;
+{
+  int num;
+  struct task_entry *e;
+
+  if (!tidstr)
+    error ("Please specify a task ID.  Use the \"info tasks\" command to\n"
+           "see the IDs of currently known tasks.");
+
+  num = atoi (tidstr);
+  e = get_entry_vptr (num);
+
+  if (e == NULL)
+    error ("Task ID %d not known.  Use the \"info tasks\" command to\n"
+           "see the IDs of currently known tasks.", num);
+
+  if (current_task_id == -1)
+    {
+#if (defined(__alpha__) && defined(__osf__) && !defined(VXWORKS_TARGET))
+      fill_gregset (&gregset_saved, -1);
+      fill_fpregset (&fpregset_saved, -1);
+#endif
+      current_task_id = get_current_task ();
+    }
+
+  current_task = num;
+  current_task_index = e->known_tasks_index;
+  current_thread = e->thread;
+  current_lwp = e->lwp;
+  if (task_switch (e->thread, e->lwp) == 0)
+    {
+      /* FIXME: find_printable_frame should be defined in frame.h, and
+        implemented in ada-lang.c */
+      /*      find_printable_frame (selected_frame, frame_relative_level (selected_frame));*/
+      printf_filtered ("[Switching to task %d]\n", num);
+      print_stack_frame (selected_frame, frame_relative_level (selected_frame), 1);
+    }
+  else
+    printf_filtered ("Unable to switch to task %d\n", num);
+}
+
+void
+_initialize_tasks ()
+{
+  static struct cmd_list_element *task_cmd_list = NULL;
+  extern struct cmd_list_element *cmdlist;
+
+  add_info (
+        "tasks", info_tasks_command,
+       "Without argument: list all known Ada tasks, with status information.\n"
+       "info tasks n: print detailed information of task n.\n");
+
+  add_prefix_cmd ("task", class_run, task_command,
+                  "Use this command to switch between tasks.\n\
+ The new task ID must be currently known.", &task_cmd_list, "task ", 1,
+                  &cmdlist);
+}
diff --git a/gdb/ada-typeprint.c b/gdb/ada-typeprint.c
new file mode 100644 (file)
index 0000000..6773561
--- /dev/null
@@ -0,0 +1,896 @@
+/* Support for printing Ada types for GDB, the GNU debugger.
+   Copyright 1986, 1988, 1989, 1991, 1997 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "defs.h"
+#include "obstack.h"
+#include "bfd.h"               /* Binary File Description */
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "gdbcore.h"
+#include "target.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "language.h"
+#include "demangle.h"
+#include "c-lang.h"
+#include "typeprint.h"
+#include "ada-lang.h"
+
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+
+static int print_record_field_types (struct type *, struct type *, 
+                                    struct ui_file *, int, int);
+
+static void print_array_type (struct type*, struct ui_file*, int, int);
+
+static void print_choices (struct type*, int, struct ui_file*, struct type*);
+
+static void print_range (struct type*, struct ui_file*);
+
+static void print_range_bound (struct type*, char*, int*, struct ui_file*);
+
+static void 
+print_dynamic_range_bound (struct type*, const char*, int, 
+                          const char*, struct ui_file*);
+
+static void print_range_type_named (char*, struct ui_file*);
+
+\f
+
+static char* name_buffer;
+static int name_buffer_len;
+
+/* The (demangled) Ada name of TYPE. This value persists until the
+   next call. */
+
+static char*
+demangled_type_name (type)
+     struct type *type;
+{
+  if (ada_type_name (type) == NULL)
+    return NULL;
+  else 
+    {
+      char* raw_name = ada_type_name (type);
+      char *s, *q; 
+
+      if (name_buffer == NULL || name_buffer_len <= strlen (raw_name))
+       {
+         name_buffer_len = 16 + 2 * strlen (raw_name);
+         name_buffer = xrealloc (name_buffer, name_buffer_len);
+       }
+      strcpy (name_buffer, raw_name);
+
+      s = (char*) strstr (name_buffer, "___");
+      if (s != NULL)
+       *s = '\0';
+
+      s = name_buffer + strlen (name_buffer) - 1;
+      while (s > name_buffer && (s[0] != '_' || s[-1] != '_'))
+       s -= 1;
+
+      if (s == name_buffer)
+       return name_buffer;
+
+      if (! islower (s[1]))
+       return NULL;
+
+      for (s = q = name_buffer; *s != '\0'; q += 1)
+       {
+         if (s[0] == '_' && s[1] == '_')
+           {
+             *q = '.'; s += 2;
+           }
+         else
+           {
+             *q = *s; s += 1;
+           }
+       }
+      *q = '\0';
+      return name_buffer;
+    }
+}
+
+
+/* Print a description of a type in the format of a 
+   typedef for the current language.
+   NEW is the new name for a type TYPE. */
+
+void
+ada_typedef_print (type, new, stream)
+   struct type *type;
+   struct symbol *new;
+   struct ui_file *stream;
+{
+  fprintf_filtered (stream, "type %.*s is ", 
+                   ada_name_prefix_len (SYMBOL_SOURCE_NAME(new)), 
+                   SYMBOL_SOURCE_NAME(new));
+  type_print (type, "", stream, 1);
+}
+
+/* Print range type TYPE on STREAM. */
+
+static void
+print_range (type, stream)
+     struct type* type;
+     struct ui_file* stream;
+{
+  struct type* target_type;
+  target_type = TYPE_TARGET_TYPE (type);
+  if (target_type == NULL)
+    target_type = type;
+
+  switch (TYPE_CODE (target_type)) 
+    {
+    case TYPE_CODE_RANGE:
+    case TYPE_CODE_INT:
+    case TYPE_CODE_BOOL:
+    case TYPE_CODE_CHAR:
+    case TYPE_CODE_ENUM:
+      break;
+    default:
+      target_type = builtin_type_ada_int;
+      break;
+    }
+
+  if (TYPE_NFIELDS (type) < 2)
+    {
+      /* A range needs at least 2 bounds to be printed. If there are less
+         than 2, just print the type name instead of the range itself.
+         This check handles cases such as characters, for example. 
+
+         Note that if the name is not defined, then we don't print anything.
+       */
+      fprintf_filtered (stream, "%.*s",
+                        ada_name_prefix_len (TYPE_NAME (type)),
+                        TYPE_NAME (type));
+    }
+  else
+    {
+      /* We extract the range type bounds respectively from the first element
+         and the last element of the type->fields array */
+      const LONGEST lower_bound = (LONGEST) TYPE_LOW_BOUND (type);
+      const LONGEST upper_bound =
+        (LONGEST) TYPE_FIELD_BITPOS (type, TYPE_NFIELDS (type) -1);
+
+      ada_print_scalar (target_type, lower_bound, stream);
+      fprintf_filtered (stream, " .. ");
+      ada_print_scalar (target_type, upper_bound, stream);
+    }
+}
+
+/* Print the number or discriminant bound at BOUNDS+*N on STREAM, and
+   set *N past the bound and its delimiter, if any. */
+
+static void
+print_range_bound (type, bounds, n, stream)
+     struct type* type;
+     char* bounds;
+     int* n;
+     struct ui_file* stream;
+{
+  LONGEST B;
+  if (ada_scan_number (bounds, *n, &B, n))
+    {
+      ada_print_scalar (type, B, stream);
+      if (bounds[*n] == '_')
+       *n += 2;
+    }
+  else
+    {
+      int bound_len;
+      char* bound = bounds + *n;
+      char* pend;
+
+      pend = strstr (bound, "__");
+      if (pend == NULL)
+       *n += bound_len = strlen (bound);
+      else 
+       {
+         bound_len = pend - bound;
+         *n += bound_len + 2;
+       }
+      fprintf_filtered (stream, "%.*s", bound_len, bound);
+    }
+}
+
+/* Assuming NAME[0 .. NAME_LEN-1] is the name of a range type, print
+   the value (if found) of the bound indicated by SUFFIX ("___L" or
+   "___U") according to the ___XD conventions. */
+
+static void
+print_dynamic_range_bound (type, name, name_len, suffix, stream)
+     struct type* type;
+     const char* name;
+     int name_len;
+     const char* suffix;
+     struct ui_file* stream;
+{
+  static char *name_buf = NULL;
+  static size_t name_buf_len = 0;
+  LONGEST B;
+  int OK;
+
+  GROW_VECT (name_buf, name_buf_len, name_len + strlen (suffix) + 1);
+  strncpy (name_buf, name, name_len);
+  strcpy (name_buf + name_len, suffix);
+
+  B = get_int_var_value (name_buf, 0, &OK);
+  if (OK)
+    ada_print_scalar (type, B, stream);
+  else
+    fprintf_filtered (stream, "?");
+}
+
+/* Print the range type named NAME. */
+
+static void
+print_range_type_named (name, stream)
+     char* name;
+     struct ui_file* stream;
+{
+  struct type *raw_type = ada_find_any_type (name);
+  struct type *base_type;
+  LONGEST low, high;
+  char* subtype_info;
+
+  if (raw_type == NULL)
+    base_type = builtin_type_int;
+  else if (TYPE_CODE (raw_type) == TYPE_CODE_RANGE)
+    base_type = TYPE_TARGET_TYPE (raw_type);
+  else
+    base_type = raw_type;
+
+  subtype_info = strstr (name, "___XD");
+  if (subtype_info == NULL && raw_type == NULL)
+    fprintf_filtered (stream, "? .. ?");
+  else if (subtype_info == NULL)
+    print_range (raw_type, stream);
+  else
+    {
+      int prefix_len = subtype_info - name;
+      char *bounds_str;
+      int n;
+
+      subtype_info += 5;
+      bounds_str = strchr (subtype_info, '_');
+      n = 1;
+
+      if (*subtype_info == 'L') 
+       {
+         print_range_bound (raw_type, bounds_str, &n, stream);
+         subtype_info += 1;
+       }
+      else
+       print_dynamic_range_bound (raw_type, name, prefix_len, "___L", stream);
+
+      fprintf_filtered (stream, " .. ");
+
+      if (*subtype_info == 'U') 
+       print_range_bound (raw_type, bounds_str, &n, stream);
+      else
+       print_dynamic_range_bound (raw_type, name, prefix_len, "___U", stream);
+    }
+}  
+
+/* Print enumerated type TYPE on STREAM. */
+
+static void
+print_enum_type (type, stream)
+     struct type *type;
+     struct ui_file *stream;
+{
+  int len = TYPE_NFIELDS (type);
+  int i, lastval;
+
+  fprintf_filtered (stream, "(");
+  wrap_here (" ");
+
+  lastval = 0;
+  for (i = 0; i < len; i++)
+    {
+      QUIT;
+      if (i) fprintf_filtered (stream, ", ");
+      wrap_here ("    ");
+      fputs_filtered (ada_enum_name (TYPE_FIELD_NAME (type, i)), stream);
+      if (lastval != TYPE_FIELD_BITPOS (type, i))
+       {
+         fprintf_filtered (stream, " => %d", TYPE_FIELD_BITPOS (type, i));
+         lastval = TYPE_FIELD_BITPOS (type, i);
+       }
+      lastval += 1;
+    }
+  fprintf_filtered (stream, ")");
+}
+
+/* Print representation of Ada fixed-point type TYPE on STREAM. */
+
+static void
+print_fixed_point_type (type, stream)
+     struct type *type;
+     struct ui_file *stream;
+{
+  DOUBLEST delta = ada_delta (type);
+  DOUBLEST small = ada_fixed_to_float (type, 1.0);
+
+  if (delta < 0.0)
+    fprintf_filtered (stream, "delta ??");
+  else
+    {
+      fprintf_filtered (stream, "delta %g", (double) delta);
+      if (delta != small) 
+       fprintf_filtered (stream, " <'small = %g>", (double) small);
+    }
+}
+
+/* Print representation of special VAX floating-point type TYPE on STREAM. */
+
+static void
+print_vax_floating_point_type (type, stream)
+     struct type *type;
+     struct ui_file *stream;
+{
+  fprintf_filtered (stream, "<float format %c>",
+                   ada_vax_float_type_suffix (type));
+}
+
+/* Print simple (constrained) array type TYPE on STREAM.  LEVEL is the 
+   recursion (indentation) level, in case the element type itself has 
+   nested structure, and SHOW is the number of levels of internal
+   structure to show (see ada_print_type). */
+
+static void
+print_array_type (type, stream, show, level)
+     struct type *type;
+     struct ui_file *stream;
+     int show;
+     int level;
+{
+  int bitsize;
+  int n_indices;
+
+  bitsize = 0;
+  fprintf_filtered (stream, "array (");
+
+  n_indices = -1;
+  if (show < 0) 
+    fprintf_filtered (stream, "...");
+  else
+    {
+      if (ada_is_packed_array_type (type))
+       type = ada_coerce_to_simple_array_type (type);
+      if (ada_is_simple_array (type)) 
+       {
+         struct type* range_desc_type = 
+           ada_find_parallel_type (type, "___XA");
+         struct type* arr_type;
+
+         bitsize = 0;
+         if (range_desc_type == NULL)
+           {
+             for (arr_type = type; TYPE_CODE (arr_type) == TYPE_CODE_ARRAY;
+                  arr_type = TYPE_TARGET_TYPE (arr_type))
+               {
+                 if (arr_type != type)
+                   fprintf_filtered (stream, ", ");
+                 print_range (TYPE_INDEX_TYPE (arr_type), stream);
+                 if (TYPE_FIELD_BITSIZE (arr_type, 0) > 0)
+                   bitsize = TYPE_FIELD_BITSIZE (arr_type, 0);
+               }
+           }
+         else 
+           {
+             int k;
+             n_indices = TYPE_NFIELDS (range_desc_type); 
+             for (k = 0, arr_type = type; 
+                  k < n_indices;
+                  k += 1, arr_type = TYPE_TARGET_TYPE (arr_type))
+               {
+                 if (k > 0)
+                   fprintf_filtered (stream, ", ");
+                 print_range_type_named (TYPE_FIELD_NAME (range_desc_type, k),
+                                         stream);
+                 if (TYPE_FIELD_BITSIZE (arr_type, 0) > 0)
+                   bitsize = TYPE_FIELD_BITSIZE (arr_type, 0);
+               }                 
+           }
+       }
+      else 
+       {
+         int i, i0;
+         for (i = i0 = ada_array_arity (type); i > 0; i -= 1)
+           fprintf_filtered (stream, "%s<>", i == i0 ? "" : ", ");
+       }
+    }
+
+  fprintf_filtered (stream, ") of ");
+  wrap_here ("");
+  ada_print_type (ada_array_element_type (type, n_indices), "", stream, 
+                 show == 0 ? 0 : show-1, level+1);
+  if (bitsize > 0)
+    fprintf_filtered (stream, " <packed: %d-bit elements>", bitsize);
+}
+
+/* Print the choices encoded by field FIELD_NUM of variant-part TYPE on
+   STREAM, assuming the VAL_TYPE is the type of the values. */
+
+static void
+print_choices (type, field_num, stream, val_type)
+     struct type *type;
+     int field_num;
+     struct ui_file *stream;
+     struct type *val_type;
+{
+  int have_output;
+  int p;
+  const char* name = TYPE_FIELD_NAME (type, field_num);
+
+  have_output = 0;
+
+  /* Skip over leading 'V': NOTE soon to be obsolete. */
+  if (name[0] == 'V')
+    {
+      if (! ada_scan_number (name, 1, NULL, &p))
+       goto Huh;
+    }
+  else
+    p = 0;
+
+  while (1)
+    {
+      switch (name[p]) 
+       {
+       default:
+         return;
+       case 'S':
+       case 'R':
+       case 'O':
+         if (have_output) 
+           fprintf_filtered (stream, " | ");
+         have_output = 1;
+         break;
+       }
+
+      switch (name[p]) 
+       {
+       case 'S':
+         {
+           LONGEST W;
+           if (! ada_scan_number (name, p + 1, &W, &p))
+             goto Huh;
+           ada_print_scalar (val_type, W, stream);
+           break;
+         }
+       case 'R':
+         {
+           LONGEST L, U;
+           if (! ada_scan_number (name, p + 1, &L, &p)
+               || name[p] != 'T'
+               || ! ada_scan_number (name, p + 1, &U, &p))
+             goto Huh;
+           ada_print_scalar (val_type, L, stream);
+           fprintf_filtered (stream, " .. ");
+           ada_print_scalar (val_type, U, stream);
+           break;
+         }
+       case 'O':
+         fprintf_filtered (stream, "others");
+         p += 1;
+         break;
+       }
+    }
+
+Huh:
+  fprintf_filtered (stream, "??");
+
+}
+
+/* Assuming that field FIELD_NUM of TYPE is a VARIANTS field whose 
+   discriminant is contained in OUTER_TYPE, print its variants on STREAM.  
+   LEVEL is the recursion
+   (indentation) level, in case any of the fields themselves have
+   nested structure, and SHOW is the number of levels of internal structure
+   to show (see ada_print_type). For this purpose, fields nested in a
+   variant part are taken to be at the same level as the fields
+   immediately outside the variant part. */
+
+static void
+print_variant_clauses (type, field_num, outer_type, stream, show, level)
+     struct type *type;
+     int field_num;
+     struct type *outer_type;
+     struct ui_file *stream;
+     int show;
+     int level;
+{
+  int i;
+  struct type *var_type;
+  struct type *discr_type;
+
+  var_type = TYPE_FIELD_TYPE (type, field_num);
+  discr_type = ada_variant_discrim_type (var_type, outer_type);
+
+  if (TYPE_CODE (var_type) == TYPE_CODE_PTR)
+    {
+      var_type = TYPE_TARGET_TYPE (var_type);
+      if (TYPE_FLAGS (var_type) & TYPE_FLAG_STUB) 
+       {
+         var_type = ada_find_parallel_type (var_type, "___XVU");
+         if (var_type == NULL)
+           return;
+       }
+    }
+
+  for (i = 0; i < TYPE_NFIELDS (var_type); i += 1) 
+    {
+      fprintf_filtered (stream, "\n%*swhen ", level + 4, "");
+      print_choices (var_type, i, stream, discr_type);
+      fprintf_filtered (stream, " =>");
+      if (print_record_field_types (TYPE_FIELD_TYPE (var_type, i), 
+                                   outer_type, stream, show, level+4) <= 0)
+       fprintf_filtered (stream, " null;");
+    }
+}
+
+/* Assuming that field FIELD_NUM of TYPE is a variant part whose 
+   discriminants are contained in OUTER_TYPE, print a description of it
+   on STREAM.  LEVEL is the recursion (indentation) level, in case any of 
+   the fields themselves have nested structure, and SHOW is the number of 
+   levels of internal structure to show (see ada_print_type). For this 
+   purpose, fields nested in a variant part are taken to be at the same 
+   level as the fields immediately outside the variant part. */
+
+static void
+print_variant_part (type, field_num, outer_type, stream, show, level)
+     struct type *type;
+     int field_num;
+     struct type *outer_type;
+     struct ui_file *stream;
+     int show;
+     int level;
+{
+  fprintf_filtered (stream, "\n%*scase %s is", level + 4, "",
+                   ada_variant_discrim_name 
+                     (TYPE_FIELD_TYPE (type, field_num)));
+  print_variant_clauses (type, field_num, outer_type, stream, show, level + 4);
+  fprintf_filtered (stream, "\n%*send case;", level + 4, "");
+}
+
+/* Print a description on STREAM of the fields in record type TYPE, whose 
+   discriminants are in OUTER_TYPE.  LEVEL is the recursion (indentation) 
+   level, in case any of the fields themselves have nested structure, 
+   and SHOW is the number of levels of internal structure to show 
+   (see ada_print_type).  Does not print parent type information of TYPE. 
+   Returns 0 if no fields printed, -1 for an incomplete type, else > 0. 
+   Prints each field beginning on a new line, but does not put a new line at
+   end. */
+
+static int
+print_record_field_types (type, outer_type, stream, show, level)
+     struct type *type;
+     struct type *outer_type;
+     struct ui_file *stream;
+     int show;
+     int level;
+{
+  int len, i, flds;
+
+  flds = 0;
+  len = TYPE_NFIELDS (type);
+
+  if (len == 0 && (TYPE_FLAGS (type) & TYPE_FLAG_STUB) != 0)
+    return -1;
+
+  for (i = 0; i < len; i += 1)
+    {
+      QUIT;
+
+      if (ada_is_parent_field (type, i) 
+         || ada_is_ignored_field (type, i))
+       ;
+      else if (ada_is_wrapper_field (type, i))
+       flds += print_record_field_types (TYPE_FIELD_TYPE (type, i), type,
+                                         stream, show, level);
+      else if (ada_is_variant_part (type, i)) 
+       {
+         print_variant_part (type, i, outer_type, stream, show, level);
+         flds = 1;
+       }
+      else
+       {
+         flds += 1;
+         fprintf_filtered (stream, "\n%*s", level + 4, "");
+         ada_print_type (TYPE_FIELD_TYPE (type, i),
+                         TYPE_FIELD_NAME (type, i),
+                         stream, show - 1, level + 4);
+         fprintf_filtered (stream, ";");
+       }
+    }
+
+  return flds;
+}
+
+/* Print record type TYPE on STREAM.  LEVEL is the recursion (indentation) 
+   level, in case the element type itself has nested structure, and SHOW is 
+   the number of levels of internal structure to show (see ada_print_type). */
+
+static void
+print_record_type (type0, stream, show, level)
+     struct type* type0;
+     struct ui_file* stream;
+     int show;
+     int level;
+{
+  struct type* parent_type;
+  struct type* type;
+  
+  type = type0;
+  if (TYPE_FLAGS (type) & TYPE_FLAG_STUB)
+    {
+      struct type* type1 = ada_find_parallel_type (type, "___XVE");
+      if (type1 != NULL)
+       type = type1;
+    }
+
+  parent_type = ada_parent_type (type);
+  if (ada_type_name (parent_type) != NULL) 
+    fprintf_filtered (stream, "new %s with ", 
+                     demangled_type_name (parent_type));
+  else if (parent_type == NULL && ada_is_tagged_type (type))
+    fprintf_filtered (stream, "tagged ");
+
+  fprintf_filtered (stream, "record");
+
+  if (show < 0)
+    fprintf_filtered (stream, " ... end record");
+  else
+    {
+      int flds;
+
+      flds = 0;
+      if (parent_type != NULL && ada_type_name (parent_type) == NULL)
+       flds += print_record_field_types (parent_type, parent_type, 
+                                         stream, show, level);
+      flds += print_record_field_types (type, type, stream, show, level);
+      
+      if (flds > 0)
+       fprintf_filtered (stream, "\n%*send record", level, "");
+      else if (flds < 0) 
+       fprintf_filtered (stream, " <incomplete type> end record");
+      else 
+       fprintf_filtered (stream, " null; end record");
+    }
+}
+
+/* Print the unchecked union type TYPE in something resembling Ada
+   format on STREAM. LEVEL is the recursion (indentation) level
+   in case the element type itself has nested structure, and SHOW is the
+   number of levels of internal structure to show (see ada_print_type). */
+static void
+print_unchecked_union_type (struct type* type, struct ui_file* stream, 
+                           int show, int level)
+{
+  fprintf_filtered (stream, "record (?) is");
+
+  if (show < 0)
+    fprintf_filtered (stream, " ... end record");
+  else if (TYPE_NFIELDS (type) == 0) 
+    fprintf_filtered (stream, " null; end record");
+  else
+    {
+      int i;
+
+      fprintf_filtered (stream, "\n%*scase ? is", 
+                       level+4, "");
+
+      for (i = 0; i < TYPE_NFIELDS (type); i += 1) 
+       {
+         fprintf_filtered (stream, "\n%*swhen ? =>\n%*s", level+8, "",
+                           level+12, "");
+         ada_print_type (TYPE_FIELD_TYPE (type, i),
+                         TYPE_FIELD_NAME (type, i),
+                         stream, show - 1, level + 12);
+         fprintf_filtered (stream, ";");
+       }
+
+      fprintf_filtered (stream, "\n%*send case;\n%*send record", 
+                       level+4, "", level, "");
+    }
+}
+  
+
+
+/* Print function or procedure type TYPE on STREAM.  Make it a header
+   for function or procedure NAME if NAME is not null. */
+
+static void
+print_func_type (type, stream, name)
+     struct type *type;
+     struct ui_file *stream;
+     char* name;
+{
+  int i, len = TYPE_NFIELDS (type);
+
+  if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_VOID)
+    fprintf_filtered (stream, "procedure");
+  else
+    fprintf_filtered (stream, "function");
+
+  if (name != NULL && name[0] != '\0') 
+    fprintf_filtered (stream, " %s", name);
+
+  if (len > 0) 
+    {
+      fprintf_filtered (stream, " (");
+      for (i = 0; i < len; i += 1)
+       {
+         if (i > 0)
+           {
+             fputs_filtered ("; ", stream);
+             wrap_here ("    ");
+           }
+         fprintf_filtered (stream, "a%d: ", i+1);
+         ada_print_type (TYPE_FIELD_TYPE (type, i), "", stream, -1, 0);
+       }
+      fprintf_filtered (stream, ")");
+    }      
+
+  if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_VOID)
+    {
+      fprintf_filtered (stream, " return ");
+      ada_print_type (TYPE_TARGET_TYPE (type), "", stream, 0, 0);
+    }
+}
+
+
+/* Print a description of a type TYPE0.
+   Output goes to STREAM (via stdio).
+   If VARSTRING is a non-empty string, print as an Ada variable/field
+       declaration.
+   SHOW+1 is the maximum number of levels of internal type structure 
+      to show (this applies to record types, enumerated types, and
+      array types).
+   SHOW is the number of levels of internal type structure to show
+      when there is a type name for the SHOWth deepest level (0th is 
+      outer level).
+   When SHOW<0, no inner structure is shown.
+   LEVEL indicates level of recursion (for nested definitions). */
+
+void
+ada_print_type (type0, varstring, stream, show, level)
+     struct type* type0;
+     char* varstring;
+     struct ui_file* stream;
+     int show;
+     int level;
+{
+  enum type_code code;
+  int demangled_args;
+  struct type* type = ada_completed_type (ada_get_base_type (type0));
+  char* type_name = demangled_type_name (type);
+  int is_var_decl = (varstring != NULL && varstring[0] != '\0');
+
+  if (type == NULL)
+    {
+      if (is_var_decl)
+       fprintf_filtered (stream, "%.*s: ",
+                         ada_name_prefix_len(varstring),
+                         varstring);
+      fprintf_filtered (stream, "<null type?>");
+      return;
+    }
+
+  if (show > 0)
+      CHECK_TYPEDEF (type);
+
+  if (is_var_decl && TYPE_CODE (type) != TYPE_CODE_FUNC)
+      fprintf_filtered (stream, "%.*s: ", 
+                       ada_name_prefix_len (varstring), varstring);
+
+  if (type_name != NULL && show <= 0)
+    {
+      fprintf_filtered (stream, "%.*s", 
+                       ada_name_prefix_len (type_name), type_name);
+      return;
+    }
+
+  if (ada_is_aligner_type (type))
+    ada_print_type (ada_aligned_type (type), "", stream, show, level);
+  else if (ada_is_packed_array_type (type))
+    print_array_type (type, stream, show, level);
+  else
+  switch (TYPE_CODE (type))
+    {
+    default:
+      fprintf_filtered (stream, "<");
+      c_print_type (type, "", stream, show, level);
+      fprintf_filtered (stream, ">");
+      break;
+    case TYPE_CODE_PTR:
+      fprintf_filtered (stream, "access ");
+      ada_print_type (TYPE_TARGET_TYPE (type), "", stream, show,
+                     level);
+      break;
+    case TYPE_CODE_REF:
+      fprintf_filtered (stream, "<ref> ");
+      ada_print_type (TYPE_TARGET_TYPE (type), "", stream, show,
+                     level);
+      break;
+    case TYPE_CODE_ARRAY:
+      print_array_type (type, stream, show, level);
+      break;
+    case TYPE_CODE_INT:
+      if (ada_is_fixed_point_type (type))
+       print_fixed_point_type (type, stream);
+      else if (ada_is_vax_floating_type (type))
+       print_vax_floating_point_type (type, stream);
+      else
+       {
+         char* name = ada_type_name (type);
+         if (! ada_is_range_type_name (name))
+           fprintf_filtered (stream, "<%d-byte integer>", TYPE_LENGTH (type));
+         else
+           {
+             fprintf_filtered (stream, "range ");
+             print_range_type_named (name, stream);
+           }
+       }
+      break;
+    case TYPE_CODE_RANGE:
+      if (ada_is_fixed_point_type (type))
+       print_fixed_point_type (type, stream);
+      else if (ada_is_vax_floating_type (type))
+       print_vax_floating_point_type (type, stream);
+      else if (ada_is_modular_type (type))
+       fprintf_filtered (stream, "mod %ld", (long) ada_modulus (type));
+      else
+       {
+         fprintf_filtered (stream, "range ");
+         print_range (type, stream);
+       }
+      break;
+    case TYPE_CODE_FLT:
+      fprintf_filtered (stream, "<%d-byte float>", TYPE_LENGTH (type));
+      break;
+    case TYPE_CODE_ENUM:
+      if (show < 0)
+       fprintf_filtered (stream, "(...)");
+      else
+       print_enum_type (type, stream);
+      break;
+    case TYPE_CODE_STRUCT:
+      if (ada_is_array_descriptor (type))
+       print_array_type (type, stream, show, level);
+      else if (ada_is_bogus_array_descriptor (type))
+       fprintf_filtered (stream, "array (?) of ? (<mal-formed descriptor>)");
+      else
+       print_record_type (type, stream, show, level);
+      break;
+    case TYPE_CODE_UNION:
+      print_unchecked_union_type (type, stream, show, level);
+      break;
+    case TYPE_CODE_FUNC:
+      print_func_type (type, stream, varstring);
+      break;
+    }
+}
diff --git a/gdb/ada-valprint.c b/gdb/ada-valprint.c
new file mode 100644 (file)
index 0000000..6db18eb
--- /dev/null
@@ -0,0 +1,1058 @@
+/* Support for printing Ada values for GDB, the GNU debugger.  
+   Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1997, 2001
+             Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include <ctype.h>
+#include "defs.h"
+#include "symtab.h"
+#include "gdbtypes.h"
+#include "expression.h"
+#include "value.h"
+#include "demangle.h"
+#include "valprint.h"
+#include "language.h"
+#include "annotate.h"
+#include "ada-lang.h"
+#include "c-lang.h"
+
+/* Encapsulates arguments to ada_val_print. */
+struct ada_val_print_args {
+  struct type* type;
+  char* valaddr0;
+  int embedded_offset;
+  CORE_ADDR address;
+  struct ui_file *stream;
+  int format;
+  int deref_ref;
+  int recurse;
+  enum val_prettyprint pretty;
+};
+
+extern int inspect_it;
+extern unsigned int repeat_count_threshold;
+
+static void print_record (struct type*, char*, struct ui_file*, int,
+                         int, enum val_prettyprint);
+
+static int print_field_values (struct type*, char*, struct ui_file*, 
+                              int, int, enum val_prettyprint,
+                              int, struct type*, char*);
+
+static int print_variant_part (struct type*, int, char*, 
+                              struct ui_file*, int, int, enum val_prettyprint,
+                              int, struct type*, char*);
+
+static void
+val_print_packed_array_elements (struct type*, char *valaddr, int,
+                                struct ui_file*, int, int, 
+                                enum val_prettyprint);
+
+static void adjust_type_signedness (struct type*);
+
+static int ada_val_print_stub (PTR args0);
+
+static int
+ada_val_print_1 (struct type*, char*, int, CORE_ADDR, struct ui_file*,
+                int, int, int, enum val_prettyprint);
+\f
+
+/* Make TYPE unsigned if its range of values includes no negatives. */
+static void 
+adjust_type_signedness (type)
+     struct type* type;
+{
+  if (type != NULL && TYPE_CODE (type) == TYPE_CODE_RANGE 
+      && TYPE_LOW_BOUND (type) >= 0)
+    TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
+}      
+
+/* Assuming TYPE is a simple array type, prints its lower bound on STREAM,
+   if non-standard (i.e., other than 1 for numbers, other than lower bound
+   of index type for enumerated type). Returns 1 if something printed, 
+   otherwise 0. */
+
+static int 
+print_optional_low_bound (stream, type)
+     struct ui_file *stream;
+     struct type *type;
+{
+  struct type *index_type;
+  long low_bound;
+
+  index_type = TYPE_INDEX_TYPE (type);
+  low_bound = 0;
+
+  if (index_type == NULL)
+    return 0;
+  if (TYPE_CODE (index_type) == TYPE_CODE_RANGE) 
+    {
+      low_bound = TYPE_LOW_BOUND (index_type);
+      index_type = TYPE_TARGET_TYPE (index_type);
+    }
+  else
+    return 0;
+      
+  switch (TYPE_CODE (index_type)) {
+  case TYPE_CODE_ENUM:
+    if (low_bound == TYPE_FIELD_BITPOS (index_type, 0))
+      return 0;
+    break;
+  case TYPE_CODE_UNDEF:
+    index_type = builtin_type_long;
+    /* FALL THROUGH */
+  default:
+    if (low_bound == 1)
+      return 0;
+    break;
+  }
+
+  ada_print_scalar (index_type, (LONGEST) low_bound, stream);
+  fprintf_filtered (stream, " => ");
+  return 1;
+}
+
+/*  Version of val_print_array_elements for GNAT-style packed arrays.
+    Prints elements of packed array of type TYPE at bit offset
+    BITOFFSET from VALADDR on STREAM.  Formats according to FORMAT and
+    separates with commas. RECURSE is the recursion (nesting) level.
+    If PRETTY, uses "prettier" format. TYPE must have been decoded (as
+    by ada_coerce_to_simple_array).  */ 
+
+static void
+val_print_packed_array_elements (type, valaddr, bitoffset, stream, format, 
+                                recurse, pretty)
+     struct type *type;
+     char *valaddr;
+     int bitoffset;
+     struct ui_file *stream;
+     int format;
+     int recurse;
+     enum val_prettyprint pretty;
+{
+  unsigned int i;
+  unsigned int things_printed = 0;
+  unsigned len;
+  struct type *elttype;
+  unsigned eltlen;
+  /* Position of the array element we are examining to see
+     whether it is repeated.  */
+  unsigned int rep1;
+  /* Number of repetitions we have detected so far.  */
+  unsigned int reps;
+  unsigned long bitsize = TYPE_FIELD_BITSIZE (type, 0);
+  struct value* mark = value_mark ();
+      
+  elttype = TYPE_TARGET_TYPE (type);
+  eltlen = TYPE_LENGTH (check_typedef (elttype));
+
+  {
+    LONGEST low, high;
+    if (get_discrete_bounds (TYPE_FIELD_TYPE (type, 0), &low, &high) < 0)
+      len = 1;
+    else
+      len = high - low + 1;
+  }
+
+  i = 0;
+  annotate_array_section_begin (i, elttype);
+
+  while (i < len && things_printed < print_max)
+    {
+      struct value *v0, *v1;
+      int i0;
+
+      if (i != 0)
+       {
+         if (prettyprint_arrays)
+           {
+             fprintf_filtered (stream, ",\n");
+             print_spaces_filtered (2 + 2 * recurse, stream);
+           }
+         else
+           {
+             fprintf_filtered (stream, ", ");
+           }
+       }
+      wrap_here (n_spaces (2 + 2 * recurse));
+
+      i0 = i;
+      v0 = ada_value_primitive_packed_val (NULL, valaddr, 
+                                          (i0 * bitsize) / HOST_CHAR_BIT,
+                                          (i0 * bitsize) % HOST_CHAR_BIT,
+                                          bitsize, elttype);
+      while (1)
+       {
+         i += 1;
+         if (i >= len)
+           break;
+         v1 = ada_value_primitive_packed_val (NULL, valaddr, 
+                                              (i * bitsize) / HOST_CHAR_BIT,
+                                              (i * bitsize) % HOST_CHAR_BIT,
+                                              bitsize, elttype);
+         if (memcmp (VALUE_CONTENTS (v0), VALUE_CONTENTS (v1), eltlen) 
+             != 0)
+           break;
+       }
+
+      if (i - i0 > repeat_count_threshold)
+       {
+         val_print (elttype, VALUE_CONTENTS (v0), 0, 0, stream, format,
+                    0, recurse + 1, pretty);
+         annotate_elt_rep (i - i0);
+         fprintf_filtered (stream, " <repeats %u times>", i - i0);
+         annotate_elt_rep_end ();
+
+       }
+      else
+       {
+         int j;
+         for (j = i0; j < i; j += 1)
+           {
+             if (j > i0) 
+               {
+                 if (prettyprint_arrays)
+                   {
+                     fprintf_filtered (stream, ",\n");
+                     print_spaces_filtered (2 + 2 * recurse, stream);
+                   }
+                 else
+                   {
+                     fprintf_filtered (stream, ", ");
+                   }
+                 wrap_here (n_spaces (2 + 2 * recurse));
+               }
+             val_print (elttype, VALUE_CONTENTS (v0), 0, 0, stream, format,
+                        0, recurse + 1, pretty);
+             annotate_elt ();
+           }
+       }
+      things_printed += i - i0;
+    }
+  annotate_array_section_end ();
+  if (i < len)
+    {
+      fprintf_filtered (stream, "...");
+    }
+
+  value_free_to_mark (mark);
+}
+
+static struct type*
+printable_val_type (type, valaddr)
+     struct type* type;
+     char* valaddr;
+{
+  return ada_to_fixed_type (ada_aligned_type (type), valaddr, 0, NULL);
+}
+
+/* Print the character C on STREAM as part of the contents of a literal
+   string whose delimiter is QUOTER.  TYPE_LEN is the length in bytes
+   (1 or 2) of the character. */
+
+void
+ada_emit_char (c, stream, quoter, type_len)
+     int c;
+     struct ui_file *stream;
+     int quoter;
+     int type_len;
+{
+  if (type_len != 2)
+    type_len = 1;
+
+  c &= (1 << (type_len * TARGET_CHAR_BIT)) - 1;
+
+  if (isascii (c) && isprint (c))
+    {
+      if (c == quoter && c == '"')
+       fprintf_filtered (stream, "[\"%c\"]", quoter);
+      else
+       fprintf_filtered (stream, "%c", c);
+    }
+  else
+    fprintf_filtered (stream, "[\"%0*x\"]", type_len*2, c);
+}
+
+/* Character #I of STRING, given that TYPE_LEN is the size in bytes (1
+   or 2) of a character. */
+
+static int
+char_at (string, i, type_len)
+     char* string;
+     int i;
+     int type_len;
+{
+  if (type_len == 1)
+    return string[i];
+  else 
+    return (int) extract_unsigned_integer (string + 2*i, 2);
+}
+
+void
+ada_printchar (c, stream)
+     int c;
+     struct ui_file *stream;
+{
+  fputs_filtered ("'", stream);
+  ada_emit_char (c, stream, '\'', 1);
+  fputs_filtered ("'", stream);
+}
+
+/* [From print_type_scalar in typeprint.c].   Print VAL on STREAM in a
+   form appropriate for TYPE. */
+
+void
+ada_print_scalar (type, val, stream)
+     struct type *type;
+     LONGEST val;
+     struct ui_file *stream;
+{
+  unsigned int i;
+  unsigned len;
+
+  CHECK_TYPEDEF (type);
+
+  switch (TYPE_CODE (type))
+    {
+
+    case TYPE_CODE_ENUM:
+      len = TYPE_NFIELDS (type);
+      for (i = 0; i < len; i++)
+       {
+         if (TYPE_FIELD_BITPOS (type, i) == val)
+           {
+             break;
+           }
+       }
+      if (i < len)
+       {
+         fputs_filtered (ada_enum_name (TYPE_FIELD_NAME (type, i)), stream);
+       }
+      else
+       {
+         print_longest (stream, 'd', 0, val);
+       }
+      break;
+
+    case TYPE_CODE_INT:
+      print_longest (stream, TYPE_UNSIGNED (type) ? 'u' : 'd', 0, val);
+      break;
+
+    case TYPE_CODE_CHAR:
+      LA_PRINT_CHAR ((unsigned char) val, stream);
+      break;
+
+    case TYPE_CODE_BOOL:
+      fprintf_filtered (stream, val ? "true" : "false");
+      break;
+
+    case TYPE_CODE_RANGE:
+      ada_print_scalar (TYPE_TARGET_TYPE (type), val, stream);
+      return;
+
+    case TYPE_CODE_UNDEF:
+    case TYPE_CODE_PTR:
+    case TYPE_CODE_ARRAY:
+    case TYPE_CODE_STRUCT:
+    case TYPE_CODE_UNION:
+    case TYPE_CODE_FUNC:
+    case TYPE_CODE_FLT:
+    case TYPE_CODE_VOID:
+    case TYPE_CODE_SET:
+    case TYPE_CODE_STRING:
+    case TYPE_CODE_ERROR:
+    case TYPE_CODE_MEMBER:
+    case TYPE_CODE_METHOD:
+    case TYPE_CODE_REF:
+      warning ("internal error: unhandled type in ada_print_scalar");
+      break;
+
+    default:
+      error ("Invalid type code in symbol table.");
+    }
+  gdb_flush (stream);
+}
+
+/* Print the character string STRING, printing at most LENGTH characters.
+   Printing stops early if the number hits print_max; repeat counts
+   are printed as appropriate.  Print ellipses at the end if we
+   had to stop before printing LENGTH characters, or if
+   FORCE_ELLIPSES.   TYPE_LEN is the length (1 or 2) of the character type.
+ */
+
+static void
+printstr (stream, string, length, force_ellipses, type_len)
+     struct ui_file *stream;
+     char *string;
+     unsigned int length;
+     int force_ellipses;
+     int type_len;
+{
+  unsigned int i;
+  unsigned int things_printed = 0;
+  int in_quotes = 0;
+  int need_comma = 0;
+
+  if (length == 0)
+    {
+      fputs_filtered ("\"\"", stream);
+      return;
+    }
+
+  for (i = 0; i < length && things_printed < print_max; i += 1)
+    {
+      /* Position of the character we are examining
+        to see whether it is repeated.  */
+      unsigned int rep1;
+      /* Number of repetitions we have detected so far.  */
+      unsigned int reps;
+
+      QUIT;
+
+      if (need_comma)
+       {
+         fputs_filtered (", ", stream);
+         need_comma = 0;
+       }
+
+      rep1 = i + 1;
+      reps = 1;
+      while (rep1 < length && 
+            char_at(string, rep1, type_len) == char_at (string, i, type_len))
+       {
+         rep1 += 1;
+         reps += 1;
+       }
+
+      if (reps > repeat_count_threshold)
+       {
+         if (in_quotes)
+           {
+             if (inspect_it)
+               fputs_filtered ("\\\", ", stream);
+             else
+               fputs_filtered ("\", ", stream);
+             in_quotes = 0;
+           }
+         fputs_filtered ("'", stream);
+         ada_emit_char (char_at (string, i, type_len), stream, '\'', type_len);
+         fputs_filtered ("'", stream);
+         fprintf_filtered (stream, " <repeats %u times>", reps);
+         i = rep1 - 1;
+         things_printed += repeat_count_threshold;
+         need_comma = 1;
+       }
+      else
+       {
+         if (!in_quotes)
+           {
+             if (inspect_it)
+               fputs_filtered ("\\\"", stream);
+             else
+               fputs_filtered ("\"", stream);
+             in_quotes = 1;
+           }
+         ada_emit_char (char_at (string, i, type_len), stream, '"',
+                        type_len);
+         things_printed += 1;
+       }
+    }
+
+  /* Terminate the quotes if necessary.  */
+  if (in_quotes)
+    {
+      if (inspect_it)
+       fputs_filtered ("\\\"", stream);
+      else
+       fputs_filtered ("\"", stream);
+    }
+
+  if (force_ellipses || i < length)
+    fputs_filtered ("...", stream);
+}
+
+void
+ada_printstr (stream, string, length, force_ellipses, width)
+     struct ui_file *stream;
+     char *string;
+     unsigned int length;
+     int force_ellipses;
+     int width;
+{
+  printstr (stream, string, length, force_ellipses, width);
+}
+
+
+/* Print data of type TYPE located at VALADDR (within GDB), which came from
+   the inferior at address ADDRESS, onto stdio stream STREAM according to
+   FORMAT (a letter as for the printf % codes or 0 for natural format).  
+   The data at VALADDR is in target byte order.
+
+   If the data is printed as a string, returns the number of string characters
+   printed.
+
+   If DEREF_REF is nonzero, then dereference references, otherwise just print
+   them like pointers.
+
+   RECURSE indicates the amount of indentation to supply before
+   continuation lines; this amount is roughly twice the value of RECURSE.
+
+   When PRETTY is non-zero, prints record fields on separate lines.
+   (For some reason, the current version of gdb instead uses a global
+   variable---prettyprint_arrays--- to causes a similar effect on
+   arrays.)  */
+
+int
+ada_val_print (type, valaddr0, embedded_offset, address, stream,
+              format, deref_ref, recurse, pretty)
+     struct type* type;
+     char* valaddr0;
+     int embedded_offset;
+     CORE_ADDR address;
+     struct ui_file *stream;
+     int format;
+     int deref_ref;
+     int recurse;
+     enum val_prettyprint pretty;
+{
+  struct ada_val_print_args args;
+  args.type = type; args.valaddr0 = valaddr0; 
+  args.embedded_offset = embedded_offset;
+  args.address = address;
+  args.stream = stream;
+  args.format = format;
+  args.deref_ref = deref_ref;
+  args.recurse = recurse;
+  args.pretty = pretty;
+
+  return catch_errors (ada_val_print_stub, &args, NULL, RETURN_MASK_ALL);
+}
+
+/* Helper for ada_val_print; used as argument to catch_errors to
+   unmarshal the arguments to ada_val_print_1, which does the work. */
+static int
+ada_val_print_stub (PTR args0)
+{
+  struct ada_val_print_args* argsp = (struct ada_val_print_args*) args0;
+  return ada_val_print_1 (argsp->type, argsp->valaddr0, argsp->embedded_offset,
+                         argsp->address, argsp->stream, argsp->format,
+                         argsp->deref_ref, argsp->recurse,
+                         argsp->pretty);
+}
+
+/* See the comment on ada_val_print.  This function differs in that it
+ * does not catch evaluation errors (leaving that to ada_val_print). */
+
+static int
+ada_val_print_1 (type, valaddr0, embedded_offset, address, stream,
+                format, deref_ref, recurse, pretty)
+     struct type* type;
+     char* valaddr0;
+     int embedded_offset;
+     CORE_ADDR address;
+     struct ui_file *stream;
+     int format;
+     int deref_ref;
+     int recurse;
+     enum val_prettyprint pretty;
+{
+  unsigned int len;
+  int i;
+  struct type *elttype;
+  unsigned int eltlen;
+  LONGEST val;
+  CORE_ADDR addr;
+  char* valaddr = valaddr0 + embedded_offset;
+
+  CHECK_TYPEDEF (type);
+
+  if (ada_is_array_descriptor (type) || ada_is_packed_array_type (type))
+    {
+      int retn;
+      struct value* mark = value_mark ();
+      struct value* val;
+      val = value_from_contents_and_address (type, valaddr, address);
+      val = ada_coerce_to_simple_array_ptr (val);
+      if (val == NULL)
+       {
+         fprintf_filtered (stream, "(null)");
+         retn = 0;
+       }
+      else
+       retn = ada_val_print_1 (VALUE_TYPE (val), VALUE_CONTENTS (val), 0,
+                               VALUE_ADDRESS (val), stream, format, 
+                               deref_ref, recurse, pretty);
+      value_free_to_mark (mark);
+      return retn;
+    }
+
+  valaddr = ada_aligned_value_addr (type, valaddr);
+  embedded_offset -= valaddr - valaddr0 - embedded_offset;
+  type = printable_val_type (type, valaddr);
+
+  switch (TYPE_CODE (type))
+    {
+    default:
+      return c_val_print (type, valaddr0, embedded_offset, address, stream, 
+                         format, deref_ref, recurse, pretty);
+
+    case TYPE_CODE_INT:
+    case TYPE_CODE_RANGE:
+      if (ada_is_fixed_point_type (type))
+       {
+         LONGEST v = unpack_long (type, valaddr);
+         int len = TYPE_LENGTH (type);
+
+         fprintf_filtered (stream, len < 4 ? "%.11g" : "%.17g",
+                           (double) ada_fixed_to_float (type, v));
+         return 0;
+       }
+      else if (ada_is_vax_floating_type (type))
+       {
+         struct value* val = 
+           value_from_contents_and_address (type, valaddr, address);
+         struct value* func = ada_vax_float_print_function (type);
+         if (func != 0)
+           {
+             static struct type* parray_of_char = NULL;
+             struct value* printable_val;
+
+             if (parray_of_char == NULL) 
+               parray_of_char = 
+                 make_pointer_type 
+                   (create_array_type 
+                     (NULL, builtin_type_char,
+                      create_range_type (NULL, builtin_type_int, 0, 32)),
+                    NULL);
+
+             printable_val = 
+               value_ind (value_cast (parray_of_char,
+                                      call_function_by_hand (func, 1, &val)));
+             
+             fprintf_filtered (stream, "%s", VALUE_CONTENTS (printable_val));
+             return 0;
+           }
+         /* No special printing function.  Do as best we can. */
+       }
+      else if (TYPE_CODE (type) == TYPE_CODE_RANGE)
+       {
+         struct type* target_type = TYPE_TARGET_TYPE (type);
+         if (TYPE_LENGTH (type) != TYPE_LENGTH (target_type))
+           {
+             /* Obscure case of range type that has different length from
+                its base type.  Perform a conversion, or we will get a
+                nonsense value.  Actually, we could use the same
+                code regardless of lengths; I'm just avoiding a cast. */
+             struct value* v = 
+               value_cast (target_type, 
+                           value_from_contents_and_address (type, valaddr, 0));
+             return ada_val_print_1 (target_type, VALUE_CONTENTS (v), 0, 0,
+                                     stream, format, 0, recurse + 1, pretty);
+           }
+         else
+           return ada_val_print_1 (TYPE_TARGET_TYPE (type), 
+                                   valaddr0, embedded_offset,
+                                   address,  stream, format, deref_ref, 
+                                   recurse, pretty);
+       }
+      else 
+       {
+         format = format ? format : output_format;
+         if (format)
+           {
+             print_scalar_formatted (valaddr, type, format, 0, stream);
+           }
+         else
+           {
+             val_print_type_code_int (type, valaddr, stream);
+             if (ada_is_character_type (type))
+               {
+                 fputs_filtered (" ", stream);
+                 ada_printchar ((unsigned char) unpack_long (type, valaddr),
+                                stream);
+               }
+           }
+         return 0;
+       }
+
+    case TYPE_CODE_ENUM:
+      if (format)
+       {
+         print_scalar_formatted (valaddr, type, format, 0, stream);
+         break;
+       }
+      len = TYPE_NFIELDS (type);
+      val = unpack_long (type, valaddr);
+      for (i = 0; i < len; i++)
+       {
+         QUIT;
+         if (val == TYPE_FIELD_BITPOS (type, i))
+           {
+             break;
+           }
+       }
+      if (i < len)
+       {
+         const char* name = ada_enum_name (TYPE_FIELD_NAME (type, i));
+         if (name[0] == '\'') 
+           fprintf_filtered (stream, "%ld %s", (long) val, name);
+         else
+           fputs_filtered (name, stream);
+       }
+      else
+       {
+         print_longest (stream, 'd', 0, val);
+       }
+      break;
+      
+    case TYPE_CODE_UNION:
+    case TYPE_CODE_STRUCT:
+      if (ada_is_bogus_array_descriptor (type))
+       {
+         fprintf_filtered (stream, "(...?)");
+         return 0;
+       }                             
+      else
+       {
+         print_record (type, valaddr, stream, format,
+                       recurse, pretty);
+         return 0;
+       }
+
+    case TYPE_CODE_ARRAY:
+      if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0)
+       {
+         elttype = TYPE_TARGET_TYPE (type);
+         eltlen = TYPE_LENGTH (elttype);
+         len = TYPE_LENGTH (type) / eltlen;
+             
+         /* For an array of chars, print with string syntax.  */
+         if (ada_is_string_type (type) 
+             && (format == 0 || format == 's'))
+           {
+             if (prettyprint_arrays)
+               {
+                 print_spaces_filtered (2 + 2 * recurse, stream);
+               }
+             /* If requested, look for the first null char and only print
+                elements up to it.  */
+             if (stop_print_at_null)
+               {
+                 int temp_len;
+                 
+                 /* Look for a NULL char. */
+                 for (temp_len = 0;
+                      temp_len < len && temp_len < print_max
+                      && char_at (valaddr, temp_len, eltlen) != 0;
+                      temp_len += 1);
+                 len = temp_len;
+               }
+             
+             printstr (stream, valaddr, len, 0, eltlen);
+           }
+         else
+           {
+             len = 0;
+             fprintf_filtered (stream, "(");
+             print_optional_low_bound (stream, type);
+             if (TYPE_FIELD_BITSIZE (type, 0) > 0) 
+               val_print_packed_array_elements (type, valaddr, 0, stream,
+                                                format, recurse,
+                                                pretty);
+             else
+               val_print_array_elements (type, valaddr, address, stream,
+                                         format, deref_ref, recurse,
+                                         pretty, 0);
+             fprintf_filtered (stream, ")");
+           }
+         gdb_flush (stream);
+         return len;
+       }
+
+    case TYPE_CODE_REF:
+      elttype = check_typedef (TYPE_TARGET_TYPE (type));
+      if (addressprint)
+        {
+         fprintf_filtered (stream, "@");
+         print_address_numeric
+           (extract_address (valaddr,
+                             TARGET_PTR_BIT / HOST_CHAR_BIT), 1, stream);
+         if (deref_ref)
+           fputs_filtered (": ", stream);
+        }
+      /* De-reference the reference */
+      if (deref_ref)
+       {
+         if (TYPE_CODE (elttype) != TYPE_CODE_UNDEF)
+           {
+             LONGEST deref_val_int = (LONGEST) 
+               unpack_pointer (lookup_pointer_type (builtin_type_void), 
+                               valaddr);
+             if (deref_val_int != 0) 
+               {
+                 struct value* deref_val =
+                   ada_value_ind (value_from_longest 
+                                  (lookup_pointer_type (elttype), 
+                                   deref_val_int));
+                 val_print (VALUE_TYPE (deref_val),
+                            VALUE_CONTENTS (deref_val), 0,
+                            VALUE_ADDRESS (deref_val), stream, format,
+                            deref_ref, recurse + 1, pretty);
+               }
+             else
+               fputs_filtered ("(null)", stream);
+           }
+         else
+           fputs_filtered ("???", stream);
+       }
+      break;
+    }
+  return 0;
+}
+
+static int
+print_variant_part (type, field_num, valaddr, 
+                   stream, format, recurse, pretty, comma_needed,
+                   outer_type, outer_valaddr)
+     struct type *type;
+     int field_num;
+     char *valaddr;
+     struct ui_file *stream;
+     int format;
+     int recurse;
+     enum val_prettyprint pretty;
+     int comma_needed;
+     struct type *outer_type;
+     char *outer_valaddr;
+{
+  struct type *var_type = TYPE_FIELD_TYPE (type, field_num);
+  int which = 
+    ada_which_variant_applies (var_type, outer_type, outer_valaddr);
+
+  if (which < 0)
+    return 0;
+  else
+    return print_field_values 
+      (TYPE_FIELD_TYPE (var_type, which),
+       valaddr + TYPE_FIELD_BITPOS (type, field_num) / HOST_CHAR_BIT
+       + TYPE_FIELD_BITPOS (var_type, which) / HOST_CHAR_BIT,
+       stream, format, recurse, pretty,
+       comma_needed, outer_type, outer_valaddr);
+}
+
+int
+ada_value_print (val0, stream, format, pretty)
+     struct value* val0;
+     struct ui_file *stream;
+     int format;
+     enum val_prettyprint pretty;
+{
+  char* valaddr = VALUE_CONTENTS (val0);
+  CORE_ADDR address = VALUE_ADDRESS (val0) + VALUE_OFFSET (val0);
+  struct type* type = 
+    ada_to_fixed_type (VALUE_TYPE (val0), valaddr, address, NULL);
+  struct value* val = value_from_contents_and_address (type, valaddr, address);
+
+  /* If it is a pointer, indicate what it points to. */
+  if (TYPE_CODE (type) == TYPE_CODE_PTR ||
+      TYPE_CODE (type) == TYPE_CODE_REF)
+    {
+      /* Hack:  remove (char *) for char strings.  Their
+        type is indicated by the quoted string anyway. */
+      if (TYPE_CODE (type) == TYPE_CODE_PTR &&
+         TYPE_LENGTH (TYPE_TARGET_TYPE (type)) == sizeof(char) &&
+         TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_INT &&
+         !TYPE_UNSIGNED (TYPE_TARGET_TYPE (type)))
+       {
+         /* Print nothing */
+       }
+      else
+       {
+         fprintf_filtered (stream, "(");
+         type_print (type, "", stream, -1);
+         fprintf_filtered (stream, ") ");
+       }
+    }
+  else if (ada_is_array_descriptor (type)) 
+    {
+      fprintf_filtered (stream, "(");
+      type_print (type, "", stream, -1);
+      fprintf_filtered (stream, ") ");
+    }
+  else if (ada_is_bogus_array_descriptor (type))
+    {
+      fprintf_filtered (stream, "(");
+      type_print (type, "", stream, -1);
+      fprintf_filtered (stream, ") (...?)");
+      return 0;
+    }
+  return (val_print (type, VALUE_CONTENTS (val), 0, address, 
+                    stream, format, 1, 0, pretty));
+}
+static void
+print_record (type, valaddr, stream, format, recurse, pretty)
+     struct type *type;
+     char *valaddr;
+     struct ui_file *stream;
+     int format;
+     int recurse;
+     enum val_prettyprint pretty;
+{
+  CHECK_TYPEDEF (type);
+
+  fprintf_filtered (stream, "(");
+
+  if (print_field_values (type, valaddr, stream, format, recurse, pretty,
+                         0, type, valaddr) != 0
+      && pretty)
+    {
+      fprintf_filtered (stream, "\n");
+      print_spaces_filtered (2 * recurse, stream);
+    }
+
+  fprintf_filtered (stream, ")");
+}
+
+/* Print out fields of value at VALADDR having structure type TYPE.
+  
+   TYPE, VALADDR, STREAM, FORMAT, RECURSE, and PRETTY have the
+   same meanings as in ada_print_value and ada_val_print.   
+
+   OUTER_TYPE and OUTER_VALADDR give type and address of enclosing record
+   (used to get discriminant values when printing variant parts).
+
+   COMMA_NEEDED is 1 if fields have been printed at the current recursion 
+   level, so that a comma is needed before any field printed by this
+   call. 
+
+   Returns 1 if COMMA_NEEDED or any fields were printed. */
+
+static int
+print_field_values (type, valaddr, stream, format, recurse, pretty, 
+                   comma_needed, outer_type, outer_valaddr)
+     struct type *type;
+     char *valaddr;
+     struct ui_file *stream;
+     int format;
+     int recurse;
+     enum val_prettyprint pretty;
+     int comma_needed;
+     struct type *outer_type;
+     char *outer_valaddr;
+{
+  int i, len;
+
+  len = TYPE_NFIELDS (type);
+
+  for (i = 0; i < len; i += 1)
+    {
+      if (ada_is_ignored_field (type, i))
+         continue;
+
+      if (ada_is_wrapper_field (type, i))
+       {
+         comma_needed = 
+           print_field_values (TYPE_FIELD_TYPE (type, i),
+                               valaddr 
+                               + TYPE_FIELD_BITPOS (type, i) / HOST_CHAR_BIT,
+                               stream, format, recurse, pretty,
+                               comma_needed, type, valaddr);
+         continue;
+       }
+      else if (ada_is_variant_part (type, i))
+       {
+         comma_needed =
+           print_variant_part (type, i, valaddr,
+                               stream, format, recurse, pretty, comma_needed,
+                               outer_type, outer_valaddr);
+         continue;
+       }
+
+      if (comma_needed)
+       fprintf_filtered (stream, ", ");
+      comma_needed = 1;
+
+      if (pretty)
+       {
+         fprintf_filtered (stream, "\n");
+         print_spaces_filtered (2 + 2 * recurse, stream);
+       }
+      else 
+       {
+         wrap_here (n_spaces (2 + 2 * recurse));
+       }
+      if (inspect_it)
+       {
+         if (TYPE_CODE (TYPE_FIELD_TYPE (type, i)) == TYPE_CODE_PTR)
+           fputs_filtered ("\"( ptr \"", stream);
+         else
+           fputs_filtered ("\"( nodef \"", stream);
+         fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i),
+                                  language_cplus, DMGL_NO_OPTS);
+         fputs_filtered ("\" \"", stream);
+         fprintf_symbol_filtered (stream, TYPE_FIELD_NAME (type, i),
+                                  language_cplus, DMGL_NO_OPTS);
+         fputs_filtered ("\") \"", stream);
+       }
+      else
+       {
+         annotate_field_begin (TYPE_FIELD_TYPE (type, i));
+         fprintf_filtered (stream, "%.*s", 
+                           ada_name_prefix_len (TYPE_FIELD_NAME (type, i)),
+                           TYPE_FIELD_NAME (type, i));
+         annotate_field_name_end ();
+         fputs_filtered (" => ", stream);
+         annotate_field_value ();
+       }
+
+      if (TYPE_FIELD_PACKED (type, i))
+       {
+         struct value* v;
+
+         /* Bitfields require special handling, especially due to byte
+            order problems.  */
+         if (TYPE_CPLUS_SPECIFIC (type) != NULL
+             && TYPE_FIELD_IGNORE (type, i))
+           {
+             fputs_filtered ("<optimized out or zero length>", stream);
+           }
+         else
+           {
+             int bit_pos = TYPE_FIELD_BITPOS (type, i);
+             int bit_size = TYPE_FIELD_BITSIZE (type, i);
+      
+             adjust_type_signedness (TYPE_FIELD_TYPE (type, i));
+             v = ada_value_primitive_packed_val (NULL, valaddr,
+                                                 bit_pos / HOST_CHAR_BIT,
+                                                 bit_pos % HOST_CHAR_BIT,
+                                                 bit_size, 
+                                                 TYPE_FIELD_TYPE (type, i));
+             val_print (TYPE_FIELD_TYPE(type, i), VALUE_CONTENTS (v), 0, 0,
+                        stream, format, 0, recurse + 1, pretty);
+           }
+       }
+      else
+         ada_val_print (TYPE_FIELD_TYPE (type, i), 
+                        valaddr + TYPE_FIELD_BITPOS (type, i) / HOST_CHAR_BIT,
+                        0, 0, stream, format, 0, recurse + 1, pretty);
+      annotate_field_end ();
+    }
+
+  return comma_needed;
+}