/* Parse expressions for GDB.
- Copyright (C) 1986, 1989, 1990, 1991 Free Software Foundation, Inc.
+ Copyright (C) 1986, 1989, 1990, 1991, 1994 Free Software Foundation, Inc.
Modified from expread.y by the Department of Computer Science at the
State University of New York at Buffalo, 1991.
#include "language.h"
#include "parser-defs.h"
+static void
+free_funcalls PARAMS ((void));
+
static void
prefixify_expression PARAMS ((struct expression *));
static void
prefixify_subexp PARAMS ((struct expression *, struct expression *, int, int));
+/* Data structure for saving values of arglist_len for function calls whose
+ arguments contain other function calls. */
+
+struct funcall
+ {
+ struct funcall *next;
+ int arglist_len;
+ };
+
+static struct funcall *funcall_chain;
+
/* Assign machine-independent names to certain registers
(unless overridden by the REGISTER_NAMES table) */
+#ifdef NO_STD_REGS
+unsigned num_std_regs = 0;
+struct std_regs std_regs[1];
+#else
struct std_regs std_regs[] = {
+
#ifdef PC_REGNUM
{ "pc", PC_REGNUM },
#endif
#ifdef PS_REGNUM
{ "ps", PS_REGNUM },
#endif
+
};
unsigned num_std_regs = (sizeof std_regs / sizeof std_regs[0]);
+#endif
+
/* Begin counting arguments for a function call,
saving the data about any containing call. */
void
start_arglist ()
{
- register struct funcall *new = (struct funcall *) xmalloc (sizeof (struct funcall));
+ register struct funcall *new;
+ new = (struct funcall *) xmalloc (sizeof (struct funcall));
new->next = funcall_chain;
new->arglist_len = arglist_len;
arglist_len = 0;
/* Free everything in the funcall chain.
Used when there is an error inside parsing. */
-void
+static void
free_funcalls ()
{
register struct funcall *call, *next;
if (expout_ptr >= expout_size)
{
expout_size *= 2;
- expout = (struct expression *) xrealloc ((char *) expout,
- sizeof (struct expression)
- + expout_size * sizeof (union exp_element));
+ expout = (struct expression *)
+ xrealloc ((char *) expout, sizeof (struct expression)
+ + EXP_ELEM_TO_BYTES (expout_size));
}
expout->elts[expout_ptr++] = expelt;
}
write_exp_elt (tmp);
}
+void
+write_exp_elt_block (b)
+ struct block *b;
+{
+ union exp_element tmp;
+ tmp.block = b;
+ write_exp_elt (tmp);
+}
+
void
write_exp_elt_longcst (expelt)
LONGEST expelt;
at each end to record the actual string length (not including the
null byte terminator). */
- lenelt = 2 + (len + sizeof (union exp_element)) / sizeof (union exp_element);
+ lenelt = 2 + BYTES_TO_EXP_ELEM (len + 1);
/* Ensure that we have enough available expression elements to store
everything. */
expout_size = max (expout_size * 2, expout_ptr + lenelt + 10);
expout = (struct expression *)
xrealloc ((char *) expout, (sizeof (struct expression)
- + (expout_size * sizeof (union exp_element))));
+ + EXP_ELEM_TO_BYTES (expout_size)));
}
/* Write the leading length expression element (which advances the current
expout_ptr += lenelt - 2;
write_exp_elt_longcst ((LONGEST) len);
}
+
+/* Add a bitstring constant to the end of the expression.
+
+ Bitstring constants are stored by first writing an expression element
+ that contains the length of the bitstring (in bits), then stuffing the
+ bitstring constant itself into however many expression elements are
+ needed to hold it, and then writing another expression element that
+ contains the length of the bitstring. I.E. an expression element at
+ each end of the bitstring records the bitstring length, so you can skip
+ over the expression elements containing the actual bitstring bytes from
+ either end of the bitstring. */
+
+void
+write_exp_bitstring (str)
+ struct stoken str;
+{
+ register int bits = str.length; /* length in bits */
+ register int len = (bits + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT;
+ register int lenelt;
+ register char *strdata;
+
+ /* Compute the number of expression elements required to hold the bitstring,
+ along with one expression element at each end to record the actual
+ bitstring length in bits. */
+
+ lenelt = 2 + BYTES_TO_EXP_ELEM (len);
+
+ /* Ensure that we have enough available expression elements to store
+ everything. */
+
+ if ((expout_ptr + lenelt) >= expout_size)
+ {
+ expout_size = max (expout_size * 2, expout_ptr + lenelt + 10);
+ expout = (struct expression *)
+ xrealloc ((char *) expout, (sizeof (struct expression)
+ + EXP_ELEM_TO_BYTES (expout_size)));
+ }
+
+ /* Write the leading length expression element (which advances the current
+ expression element index), then write the bitstring constant, and then
+ write the trailing length expression element. */
+
+ write_exp_elt_longcst ((LONGEST) bits);
+ strdata = (char *) &expout->elts[expout_ptr];
+ memcpy (strdata, str.ptr, len);
+ expout_ptr += lenelt - 2;
+ write_exp_elt_longcst ((LONGEST) bits);
+}
+
+/* Type that corresponds to the address given in a minimal symbol. */
+
+static struct type *msymbol_addr_type;
+
+/* Add the appropriate elements for a minimal symbol to the end of
+ the expression. */
+
+void
+write_exp_msymbol (msymbol, text_symbol_type, data_symbol_type)
+ struct minimal_symbol *msymbol;
+ struct type *text_symbol_type;
+ struct type *data_symbol_type;
+{
+ write_exp_elt_opcode (OP_LONG);
+ write_exp_elt_type (msymbol_addr_type);
+ write_exp_elt_longcst ((LONGEST) SYMBOL_VALUE_ADDRESS (msymbol));
+ write_exp_elt_opcode (OP_LONG);
+
+ write_exp_elt_opcode (UNOP_MEMVAL);
+ switch (msymbol -> type)
+ {
+ case mst_text:
+ case mst_file_text:
+ write_exp_elt_type (text_symbol_type);
+ break;
+
+ case mst_data:
+ case mst_file_data:
+ case mst_bss:
+ case mst_file_bss:
+ write_exp_elt_type (data_symbol_type);
+ break;
+
+ default:
+ write_exp_elt_type (builtin_type_char);
+ break;
+ }
+ write_exp_elt_opcode (UNOP_MEMVAL);
+}
\f
/* Return a null-terminated temporary copy of the name
of a string token. */
prefixify_expression (expr)
register struct expression *expr;
{
- register int len = sizeof (struct expression) +
- expr->nelts * sizeof (union exp_element);
+ register int len =
+ sizeof (struct expression) + EXP_ELEM_TO_BYTES (expr->nelts);
register struct expression *temp;
register int inpos = expr->nelts, outpos = 0;
{
/* C++ */
case OP_SCOPE:
- oplen = 5 + ((longest_to_int (expr->elts[endpos - 2].longconst)
- + sizeof (union exp_element))
- / sizeof (union exp_element));
+ oplen = longest_to_int (expr->elts[endpos - 2].longconst);
+ oplen = 5 + BYTES_TO_EXP_ELEM (oplen + 1);
break;
case OP_LONG:
case OP_DOUBLE:
+ case OP_VAR_VALUE:
oplen = 4;
break;
case OP_TYPE:
case OP_BOOL:
- case OP_VAR_VALUE:
case OP_LAST:
case OP_REGISTER:
case OP_INTERNALVAR:
/* fall through */
case OP_M2_STRING:
case OP_STRING:
- oplen = 4 + ((longest_to_int (expr->elts[endpos - 2].longconst)
- + sizeof (union exp_element))
- / sizeof (union exp_element));
+ oplen = longest_to_int (expr->elts[endpos - 2].longconst);
+ oplen = 4 + BYTES_TO_EXP_ELEM (oplen + 1);
+ break;
+
+ case OP_BITSTRING:
+ oplen = longest_to_int (expr->elts[endpos - 2].longconst);
+ oplen = (oplen + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT;
+ oplen = 4 + BYTES_TO_EXP_ELEM (oplen);
+ break;
+
+ case OP_ARRAY:
+ oplen = 4;
+ args = longest_to_int (expr->elts[endpos - 2].longconst);
+ args -= longest_to_int (expr->elts[endpos - 3].longconst);
+ args += 1;
break;
case TERNOP_COND:
{
/* C++ */
case OP_SCOPE:
- oplen = 5 + ((longest_to_int (inexpr->elts[inend - 2].longconst)
- + sizeof (union exp_element))
- / sizeof (union exp_element));
+ oplen = longest_to_int (inexpr->elts[inend - 2].longconst);
+ oplen = 5 + BYTES_TO_EXP_ELEM (oplen + 1);
break;
case OP_LONG:
case OP_DOUBLE:
+ case OP_VAR_VALUE:
oplen = 4;
break;
case OP_TYPE:
case OP_BOOL:
- case OP_VAR_VALUE:
case OP_LAST:
case OP_REGISTER:
case OP_INTERNALVAR:
args=1;
break;
- case STRUCTOP_STRUCT:
+ case STRUCTOP_STRUCT:
case STRUCTOP_PTR:
args = 1;
/* fall through */
case OP_M2_STRING:
case OP_STRING:
- oplen = 4 + ((longest_to_int (inexpr->elts[inend - 2].longconst)
- + sizeof (union exp_element))
- / sizeof (union exp_element));
+ oplen = longest_to_int (inexpr->elts[inend - 2].longconst);
+ oplen = 4 + BYTES_TO_EXP_ELEM (oplen + 1);
+ break;
+
+ case OP_BITSTRING:
+ oplen = longest_to_int (inexpr->elts[inend - 2].longconst);
+ oplen = (oplen + HOST_CHAR_BIT - 1) / HOST_CHAR_BIT;
+ oplen = 4 + BYTES_TO_EXP_ELEM (oplen);
+ break;
+
+ case OP_ARRAY:
+ oplen = 4;
+ args = longest_to_int (inexpr->elts[inend - 2].longconst);
+ args -= longest_to_int (inexpr->elts[inend - 3].longconst);
+ args += 1;
break;
case TERNOP_COND:
to the beginning of the output. */
inend -= oplen;
memcpy (&outexpr->elts[outbeg], &inexpr->elts[inend],
- oplen * sizeof (union exp_element));
+ EXP_ELEM_TO_BYTES (oplen));
outbeg += oplen;
/* Find the lengths of the arg subexpressions. */
expout_size = 10;
expout_ptr = 0;
expout = (struct expression *)
- xmalloc (sizeof (struct expression)
- + expout_size * sizeof (union exp_element));
+ xmalloc (sizeof (struct expression) + EXP_ELEM_TO_BYTES (expout_size));
expout->language_defn = current_language;
make_cleanup (free_current_contents, &expout);
expout->nelts = expout_ptr;
expout = (struct expression *)
xrealloc ((char *) expout,
- sizeof (struct expression)
- + expout_ptr * sizeof (union exp_element));
+ sizeof (struct expression) + EXP_ELEM_TO_BYTES (expout_ptr));;
/* Convert expression from postfix form as generated by yacc
parser, to a prefix form. */
- DUMP_EXPRESSION (expout, stdout, "before conversion to prefix form");
+ DUMP_EXPRESSION (expout, gdb_stdout, "before conversion to prefix form");
prefixify_expression (expout);
- DUMP_EXPRESSION (expout, stdout, "after conversion to prefix form");
+ DUMP_EXPRESSION (expout, gdb_stdout, "after conversion to prefix form");
*stringptr = lexptr;
return expout;
error ("Junk after end of expression.");
return exp;
}
+\f
+/* Stuff for maintaining a stack of types. Currently just used by C, but
+ probably useful for any language which declares its types "backwards". */
void
push_type (tp)
return 0;
}
+/* Pop the type stack and return the type which corresponds to FOLLOW_TYPE
+ as modified by all the stuff on the stack. */
+struct type *
+follow_types (follow_type)
+ struct type *follow_type;
+{
+ int done = 0;
+ int array_size;
+ struct type *range_type;
+
+ while (!done)
+ switch (pop_type ())
+ {
+ case tp_end:
+ done = 1;
+ break;
+ case tp_pointer:
+ follow_type = lookup_pointer_type (follow_type);
+ break;
+ case tp_reference:
+ follow_type = lookup_reference_type (follow_type);
+ break;
+ case tp_array:
+ array_size = pop_type_int ();
+ if (array_size != -1)
+ {
+ range_type =
+ create_range_type ((struct type *) NULL,
+ builtin_type_int, 0,
+ array_size - 1);
+ follow_type =
+ create_array_type ((struct type *) NULL,
+ follow_type, range_type);
+ }
+ else
+ follow_type = lookup_pointer_type (follow_type);
+ break;
+ case tp_function:
+ follow_type = lookup_function_type (follow_type);
+ break;
+ }
+ return follow_type;
+}
+\f
void
_initialize_parse ()
{
type_stack_depth = 0;
type_stack = (union type_stack_elt *)
xmalloc (type_stack_size * sizeof (*type_stack));
+
+ /* We don't worry too much about what the name of this type is
+ because the name should rarely appear in output to the user. */
+
+ msymbol_addr_type =
+ init_type (TYPE_CODE_PTR, TARGET_PTR_BIT / HOST_CHAR_BIT, 0,
+ "void *", NULL);
}