aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ada-exp.tab.c2389
-rw-r--r--gdb/ada-exp.y962
-rw-r--r--gdb/ada-lang.c8626
-rw-r--r--gdb/ada-lang.h365
-rw-r--r--gdb/ada-lex.c3174
-rw-r--r--gdb/ada-lex.l928
-rw-r--r--gdb/ada-tasks.c806
-rw-r--r--gdb/ada-typeprint.c896
-rw-r--r--gdb/ada-valprint.c1058
9 files changed, 19204 insertions, 0 deletions
diff --git a/gdb/ada-exp.tab.c b/gdb/ada-exp.tab.c
new file mode 100644
index 0000000..bb6d29b
--- /dev/null
+++ b/gdb/ada-exp.tab.c
@@ -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
+
+#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
+
+#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"
+
+
+ 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
index 0000000..7d46dd2
--- /dev/null
+++ b/gdb/ada-exp.y
@@ -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
+
+
+%%
+
+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
index 0000000..2c4f1d9
--- /dev/null
+++ b/gdb/ada-lang.c
@@ -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);
+
+
+
+/* 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);
+}
+
+
+ /* 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;
+}
+
+
+ /* 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));
+}
+
+
+ /* 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);
+}
+
+
+ /* 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));
+
+ }
+}
+
+ /* 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;
+}
+
+
+ /* 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);
+}
+
+
+ /* 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);
+ }
+ }
+}
+
+
+ /* 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;
+ }
+}
+
+
+ /* 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;
+}
+
+
+ /* 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;
+}
+
+
+
+ /* 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);
+}
+
+
+
+
+
+/* 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));
+}
+
+
+ /* 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);
+}
+
+
+ /* 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");
+ }
+}
+
+
+ /* 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"));
+}
+
+
+ /* 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;
+}
+
+
+
+ /* 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}
+};
+
+ /* 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
index 0000000..e5353f8
--- /dev/null
+++ b/gdb/ada-lang.h
@@ -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
index 0000000..9538f76
--- /dev/null
+++ b/gdb/ada-lex.c
@@ -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
index 0000000..2252d52
--- /dev/null
+++ b/gdb/ada-lex.l
@@ -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
index 0000000..23dc105
--- /dev/null
+++ b/gdb/ada-tasks.c
@@ -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
index 0000000..6773561
--- /dev/null
+++ b/gdb/ada-typeprint.c
@@ -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*);
+
+
+
+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
index 0000000..6db18eb
--- /dev/null
+++ b/gdb/ada-valprint.c
@@ -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);
+
+
+/* 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;
+}