* monitor.c (monitor_load_srec monitor_make_srec): Move all
[deliverable/binutils-gdb.git] / gdb / parse.c
index 214df03b6b5d8307e865b09001b06990e3a85e07..316ab53c93c4252d769a7850e7315a56cbf90488 100644 (file)
@@ -1,5 +1,5 @@
 /* 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.
 
@@ -17,7 +17,7 @@ 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.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /* Parse an expression from text in a string,
    and return the result as a  struct expression  pointer.
@@ -28,21 +28,63 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
    during the process of parsing; the lower levels of the tree always
    come first in the result.  */
    
-#include <stdio.h>
 #include "defs.h"
-#include "param.h"
+#include "gdb_string.h"
 #include "symtab.h"
+#include "gdbtypes.h"
 #include "frame.h"
 #include "expression.h"
 #include "value.h"
 #include "command.h"
 #include "language.h"
 #include "parser-defs.h"
+\f
+/* Global variables declared in parser-defs.h (and commented there).  */
+struct expression *expout;
+int expout_size;
+int expout_ptr;
+struct block *expression_context_block;
+struct block *innermost_block;
+int arglist_len;
+union type_stack_elt *type_stack;
+int type_stack_depth, type_stack_size;
+char *lexptr;
+char *namecopy;
+int paren_depth;
+int comma_terminates;
+\f
+static void
+free_funcalls PARAMS ((void));
+
+static void
+prefixify_expression PARAMS ((struct expression *));
+
+static int
+length_of_subexp PARAMS ((struct expression *, int));
+
+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
@@ -55,10 +97,13 @@ struct std_regs std_regs[] = {
 #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.  */
@@ -66,8 +111,9 @@ unsigned num_std_regs = (sizeof std_regs / sizeof std_regs[0]);
 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;
@@ -84,14 +130,14 @@ end_arglist ()
   register struct funcall *call = funcall_chain;
   funcall_chain = call->next;
   arglist_len = call->arglist_len;
-  free (call);
+  free ((PTR)call);
   return val;
 }
 
 /* Free everything in the funcall chain.
    Used when there is an error inside parsing.  */
 
-void
+static void
 free_funcalls ()
 {
   register struct funcall *call, *next;
@@ -99,7 +145,7 @@ free_funcalls ()
   for (call = funcall_chain; call; call = next)
     {
       next = call->next;
-      free (call);
+      free ((PTR)call);
     }
 }
 \f
@@ -118,9 +164,9 @@ write_exp_elt (expelt)
   if (expout_ptr >= expout_size)
     {
       expout_size *= 2;
-      expout = (struct expression *) xrealloc (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;
 }
@@ -147,6 +193,15 @@ write_exp_elt_sym (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;
@@ -192,29 +247,248 @@ write_exp_elt_intern (expelt)
 }
 
 /* Add a string constant to the end of the expression.
-   Follow it by its length in bytes, as a separate exp_element.  */
+
+   String constants are stored by first writing an expression element
+   that contains the length of the string, then stuffing the string
+   constant itself into however many expression elements are needed
+   to hold it, and then writing another expression element that contains
+   the length of the string.  I.E. an expression element at each end of
+   the string records the string length, so you can skip over the 
+   expression elements containing the actual string bytes from either
+   end of the string.  Note that this also allows gdb to handle
+   strings with embedded null bytes, as is required for some languages.
+
+   Don't be fooled by the fact that the string is null byte terminated,
+   this is strictly for the convenience of debugging gdb itself.  Gdb
+   Gdb does not depend up the string being null terminated, since the
+   actual length is recorded in expression elements at each end of the
+   string.  The null byte is taken into consideration when computing how
+   many expression elements are required to hold the string constant, of
+   course. */
+
 
 void
 write_exp_string (str)
      struct stoken str;
 {
   register int len = str.length;
-  register int lenelt
-    = (len + sizeof (union exp_element)) / sizeof (union exp_element);
+  register int lenelt;
+  register char *strdata;
 
-  expout_ptr += lenelt;
+  /* Compute the number of expression elements required to hold the string
+     (including a null byte terminator), along with one expression element
+     at each end to record the actual string length (not including the
+     null byte terminator). */
 
-  if (expout_ptr >= expout_size)
+  lenelt = 2 + BYTES_TO_EXP_ELEM (len + 1);
+
+  /* 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 + 10);
+      expout_size = max (expout_size * 2, expout_ptr + lenelt + 10);
       expout = (struct expression *)
-       xrealloc (expout, (sizeof (struct expression)
-                          + (expout_size * sizeof (union exp_element))));
+       xrealloc ((char *) expout, (sizeof (struct expression)
+                                   + EXP_ELEM_TO_BYTES (expout_size)));
     }
-  bcopy (str.ptr, (char *) &expout->elts[expout_ptr - lenelt], len);
-  ((char *) &expout->elts[expout_ptr - lenelt])[len] = 0;
+
+  /* Write the leading length expression element (which advances the current
+     expression element index), then write the string constant followed by a
+     terminating null byte, and then write the trailing length expression
+     element. */
+
+  write_exp_elt_longcst ((LONGEST) len);
+  strdata = (char *) &expout->elts[expout_ptr];
+  memcpy (strdata, str.ptr, len);
+  *(strdata + len) = '\0';
+  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);
+}
+
+/* Add the appropriate elements for a minimal symbol to the end of
+   the expression.  The rationale behind passing in text_symbol_type and
+   data_symbol_type was so that Modula-2 could pass in WORD for
+   data_symbol_type.  Perhaps it still is useful to have those types vary
+   based on the language, but they no longer have names like "int", so
+   the initial rationale is gone.  */
+
+static struct type *msym_text_symbol_type;
+static struct type *msym_data_symbol_type;
+static struct type *msym_unknown_symbol_type;
+
+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 (lookup_pointer_type (builtin_type_void));
+  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:
+    case mst_solib_trampoline:
+      write_exp_elt_type (msym_text_symbol_type);
+      break;
+
+    case mst_data:
+    case mst_file_data:
+    case mst_bss:
+    case mst_file_bss:
+      write_exp_elt_type (msym_data_symbol_type);
+      break;
+
+    default:
+      write_exp_elt_type (msym_unknown_symbol_type);
+      break;
+    }
+  write_exp_elt_opcode (UNOP_MEMVAL);
+}
+\f
+/* Recognize tokens that start with '$'.  These include:
+
+       $regname        A native register name or a "standard
+                       register name".
+
+       $variable       A convenience variable with a name chosen
+                       by the user.
+
+       $digits         Value history with index <digits>, starting
+                       from the first value which has index 1.
+
+       $$digits        Value history with index <digits> relative
+                       to the last value.  I.E. $$0 is the last
+                       value, $$1 is the one previous to that, $$2
+                       is the one previous to $$1, etc.
+
+       $ | $0 | $$0    The last value in the value history.
+
+       $$              An abbreviation for the second to the last
+                       value in the value history, I.E. $$1
+
+   */
+
+void
+write_dollar_variable (str)
+     struct stoken str;
+{
+  /* Handle the tokens $digits; also $ (short for $0) and $$ (short for $$1)
+     and $$digits (equivalent to $<-digits> if you could type that). */
+
+  int negate = 0;
+  int i = 1;
+  /* Double dollar means negate the number and add -1 as well.
+     Thus $$ alone means -1.  */
+  if (str.length >= 2 && str.ptr[1] == '$')
+    {
+      negate = 1;
+      i = 2;
+    }
+  if (i == str.length)
+    {
+      /* Just dollars (one or two) */
+      i = - negate;
+      goto handle_last;
+    }
+  /* Is the rest of the token digits?  */
+  for (; i < str.length; i++)
+    if (!(str.ptr[i] >= '0' && str.ptr[i] <= '9'))
+      break;
+  if (i == str.length)
+    {
+      i = atoi (str.ptr + 1 + negate);
+      if (negate)
+       i = - i;
+      goto handle_last;
+    }
+  
+  /* Handle tokens that refer to machine registers:
+     $ followed by a register name.  */
+  for (i = 0; i < NUM_REGS; i++)
+    if (str.length - 1 == strlen (reg_names[i])
+       && STREQN (str.ptr + 1, reg_names[i], str.length - 1))
+      {
+       goto handle_register;
+      }
+  for (i = 0; i < num_std_regs; i++)
+    if (str.length - 1 == strlen (std_regs[i].name)
+       && STREQN (str.ptr + 1, std_regs[i].name, str.length - 1))
+      {
+       i = std_regs[i].regnum;
+       goto handle_register;
+      }
+
+  /* Any other names starting in $ are debugger internal variables.  */
+
+  write_exp_elt_opcode (OP_INTERNALVAR);
+  write_exp_elt_intern (lookup_internalvar (copy_name (str) + 1));
+  write_exp_elt_opcode (OP_INTERNALVAR); 
+  return;
+ handle_last:
+  write_exp_elt_opcode (OP_LAST);
+  write_exp_elt_longcst ((LONGEST) i);
+  write_exp_elt_opcode (OP_LAST);
+  return;
+ handle_register:
+  write_exp_elt_opcode (OP_REGISTER);
+  write_exp_elt_longcst (i);
+  write_exp_elt_opcode (OP_REGISTER); 
+  return;
+}
 \f
 /* Return a null-terminated temporary copy of the name
    of a string token.  */
@@ -223,7 +497,7 @@ char *
 copy_name (token)
      struct stoken token;
 {
-  bcopy (token.ptr, namecopy, token.length);
+  memcpy (namecopy, token.ptr, token.length);
   namecopy[token.length] = 0;
   return namecopy;
 }
@@ -231,21 +505,19 @@ copy_name (token)
 /* Reverse an expression from suffix form (in which it is constructed)
    to prefix form (in which we can conveniently print or execute it).  */
 
-static void prefixify_subexp ();
-
-void
+static void
 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;
 
   temp = (struct expression *) alloca (len);
 
   /* Copy the original expression into temp.  */
-  bcopy (expr, temp, len);
+  memcpy (temp, expr, len);
 
   prefixify_subexp (temp, expr, inpos, outpos);
 }
@@ -253,7 +525,7 @@ prefixify_expression (expr)
 /* Return the number of exp_elements in the subexpression of EXPR
    whose last exp_element is at index ENDPOS - 1 in EXPR.  */
 
-int
+static int
 length_of_subexp (expr, endpos)
      register struct expression *expr;
      register int endpos;
@@ -262,7 +534,7 @@ length_of_subexp (expr, endpos)
   register int args = 0;
   register int i;
 
-  if (endpos < 0)
+  if (endpos < 1)
     error ("?error in length_of_subexp");
 
   i = (int) expr->elts[endpos - 1].opcode;
@@ -271,34 +543,38 @@ length_of_subexp (expr, endpos)
     {
       /* C++  */
     case OP_SCOPE:
-      oplen = 4 + ((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:
       oplen = 3;
       break;
 
+    case OP_COMPLEX:
+      oplen = 1; 
+      args = 2;
+      break; 
+
     case OP_FUNCALL:
+    case OP_F77_UNDETERMINED_ARGLIST:
       oplen = 3;
-      args = 1 + expr->elts[endpos - 2].longconst;
+      args = 1 + longest_to_int (expr->elts[endpos - 2].longconst);
       break;
 
     case UNOP_MAX:
     case UNOP_MIN:
       oplen = 3;
-      args = 0;
       break;
 
    case BINOP_VAL:
@@ -320,24 +596,47 @@ length_of_subexp (expr, endpos)
       args = 1;
       break;
 
+    case OP_LABELED:
     case STRUCTOP_STRUCT:
     case STRUCTOP_PTR:
+/* start-sanitize-gm */
+#ifdef GENERAL_MAGIC
+    case STRUCTOP_FIELD:
+#endif /* GENERAL_MAGIC */
+/* end-sanitize-gm */
       args = 1;
+      /* fall through */
     case OP_M2_STRING:
     case OP_STRING:
-      oplen = 3 + ((expr->elts[endpos - 2].longconst
-                   + sizeof (union exp_element))
-                  / sizeof (union exp_element));
+    case OP_NAME:
+    case OP_EXPRSTRING:
+      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:
+    case TERNOP_SLICE:
+    case TERNOP_SLICE_COUNT:
       args = 3;
       break;
 
       /* Modula-2 */
-   case BINOP_MULTI_SUBSCRIPT:
-      oplen=3;
-      args = 1 + expr->elts[endpos- 2].longconst;
+   case MULTI_SUBSCRIPT:
+      oplen = 3;
+      args = 1 + longest_to_int (expr->elts[endpos- 2].longconst);
       break;
 
     case BINOP_ASSIGN_MODIFY:
@@ -389,34 +688,38 @@ prefixify_subexp (inexpr, outexpr, inend, outbeg)
     {
       /* C++  */
     case OP_SCOPE:
-      oplen = 4 + ((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:
       oplen = 3;
       break;
 
+    case OP_COMPLEX:
+      oplen = 1; 
+      args = 2; 
+      break; 
+
     case OP_FUNCALL:
+    case OP_F77_UNDETERMINED_ARGLIST:
       oplen = 3;
-      args = 1 + inexpr->elts[inend - 2].longconst;
+      args = 1 + longest_to_int (inexpr->elts[inend - 2].longconst);
       break;
 
     case UNOP_MIN:
     case UNOP_MAX:
       oplen = 3;
-      args = 0;
       break;
 
     case UNOP_CAST:
@@ -437,18 +740,35 @@ prefixify_subexp (inexpr, outexpr, inend, outbeg)
       args=1;
       break;
 
-   case STRUCTOP_STRUCT:
+    case STRUCTOP_STRUCT:
     case STRUCTOP_PTR:
+    case OP_LABELED:
       args = 1;
+      /* fall through */
     case OP_M2_STRING:
     case OP_STRING:
-      oplen = 3 + ((inexpr->elts[inend - 2].longconst
-                   + sizeof (union exp_element))
-                  / sizeof (union exp_element));
-                  
+    case OP_NAME:
+    case OP_EXPRSTRING:
+      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:
+    case TERNOP_SLICE:
+    case TERNOP_SLICE_COUNT:
       args = 3;
       break;
 
@@ -458,9 +778,9 @@ prefixify_subexp (inexpr, outexpr, inend, outbeg)
       break;
 
       /* Modula-2 */
-   case BINOP_MULTI_SUBSCRIPT:
-      oplen=3;
-      args = 1 + inexpr->elts[inend - 2].longconst;
+   case MULTI_SUBSCRIPT:
+      oplen = 3;
+      args = 1 + longest_to_int (inexpr->elts[inend - 2].longconst);
       break;
 
       /* C++ */
@@ -475,8 +795,8 @@ prefixify_subexp (inexpr, outexpr, inend, outbeg)
   /* Copy the final operator itself, from the end of the input
      to the beginning of the output.  */
   inend -= oplen;
-  bcopy (&inexpr->elts[inend], &outexpr->elts[outbeg],
-        oplen * sizeof (union exp_element));
+  memcpy (&outexpr->elts[outbeg], &inexpr->elts[inend],
+         EXP_ELEM_TO_BYTES (oplen));
   outbeg += oplen;
 
   /* Find the lengths of the arg subexpressions.  */
@@ -542,8 +862,7 @@ parse_exp_1 (stringptr, block, comma)
   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);
 
@@ -551,12 +870,23 @@ parse_exp_1 (stringptr, block, comma)
     current_language->la_error (NULL);
 
   discard_cleanups (old_chain);
+
+  /* Record the actual number of expression elements, and then
+     reallocate the expression memory so that we free up any
+     excess elements. */
+
   expout->nelts = expout_ptr;
   expout = (struct expression *)
-    xrealloc (expout,
-             sizeof (struct expression)
-             + expout_ptr * sizeof (union exp_element));
+    xrealloc ((char *) expout,
+             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, gdb_stdout, "before conversion to prefix form");
   prefixify_expression (expout);
+  DUMP_EXPRESSION (expout, gdb_stdout, "after conversion to prefix form");
+
   *stringptr = lexptr;
   return expout;
 }
@@ -574,6 +904,9 @@ parse_expression (string)
     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)
@@ -583,7 +916,7 @@ push_type (tp)
     {
       type_stack_size *= 2;
       type_stack = (union type_stack_elt *)
-       xrealloc (type_stack, type_stack_size * sizeof (*type_stack));
+       xrealloc ((char *) type_stack, type_stack_size * sizeof (*type_stack));
     }
   type_stack[type_stack_depth++].piece = tp;
 }
@@ -596,7 +929,7 @@ push_type_int (n)
     {
       type_stack_size *= 2;
       type_stack = (union type_stack_elt *)
-       xrealloc (type_stack, type_stack_size * sizeof (*type_stack));
+       xrealloc ((char *) type_stack, type_stack_size * sizeof (*type_stack));
     }
   type_stack[type_stack_depth++].int_val = n;
 }
@@ -618,6 +951,52 @@ pop_type_int ()
   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 ();
+       /* FIXME-type-allocation: need a way to free this type when we are
+          done with it.  */
+       range_type =
+         create_range_type ((struct type *) NULL,
+                            builtin_type_int, 0,
+                            array_size >= 0 ? array_size - 1 : 0);
+       follow_type =
+         create_array_type ((struct type *) NULL,
+                            follow_type, range_type);
+       if (array_size < 0)
+         TYPE_ARRAY_UPPER_BOUND_TYPE(follow_type)
+           = BOUND_CANNOT_BE_DETERMINED;
+       break;
+      case tp_function:
+       /* FIXME-type-allocation: need a way to free this type when we are
+          done with it.  */
+       follow_type = lookup_function_type (follow_type);
+       break;
+      }
+  return follow_type;
+}
+\f
 void
 _initialize_parse ()
 {
@@ -625,4 +1004,15 @@ _initialize_parse ()
   type_stack_depth = 0;
   type_stack = (union type_stack_elt *)
     xmalloc (type_stack_size * sizeof (*type_stack));
+
+  msym_text_symbol_type =
+    init_type (TYPE_CODE_FUNC, 1, 0, "<text variable, no debug info>", NULL);
+  TYPE_TARGET_TYPE (msym_text_symbol_type) = builtin_type_int;
+  msym_data_symbol_type =
+    init_type (TYPE_CODE_INT, TARGET_INT_BIT / HOST_CHAR_BIT, 0,
+              "<data variable, no debug info>", NULL);
+  msym_unknown_symbol_type =
+    init_type (TYPE_CODE_INT, 1, 0,
+              "<variable (not text or data), no debug info>",
+              NULL);
 }
This page took 0.032264 seconds and 4 git commands to generate.