home *** CD-ROM | disk | FTP | other *** search
/ Education Sampler 1992 [NeXTSTEP] / Education_1992_Sampler.iso / NeXT / GnuSource / cplusplus-8 / cplus-lex.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-29  |  113.9 KB  |  4,494 lines

  1. /* Separate lexical analyzer for GNU C++.
  2.    Copyright (C) 1987 Free Software Foundation, Inc.
  3.    Hacked by Michael Tiemann (tiemann@mcc.com)
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 1, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21.  
  22. /* This file is the lexical analyzer for GNU C++.  */
  23.  
  24. #include <sys/types.h>
  25. #include <stdio.h>
  26. #include <errno.h>
  27. #include <setjmp.h>
  28. #include <string.h>
  29. #include "config.h"
  30. #include "input.h"
  31. #include "tree.h"
  32. #ifdef VMS
  33. #define _IOFBF 2        /* Missing from GNU's stdio.h */
  34. #endif
  35. #include "cplus-tab.h"
  36. #include "cplus-parse.h"
  37. #include "cplus-tree.h"
  38. #include "flags.h"
  39. #include "obstack.h"
  40. #include "assert.h"
  41. extern int errno;        /* needed for VAX.  */
  42. extern jmp_buf toplevel;
  43.  
  44. #ifdef VMS
  45. #define    NULL_FILE    "nla0:"
  46. #else
  47. #define    NULL_FILE    "/dev/null"
  48. #endif
  49.  
  50. #ifdef OBJCPLUS
  51. #include "objc-actions.h"
  52. #endif /* OBJCPLUS */
  53.   
  54. #define obstack_chunk_alloc xmalloc
  55. #define obstack_chunk_free free
  56.  
  57. extern int xmalloc ();
  58. extern void free ();
  59.  
  60. extern double atof ();
  61.  
  62. /* If you don't have strrchr, but instead have rindex,
  63.    add your machine to this list, and send mail to
  64.    tiemann@wheaties.ai.mit.edu.  */
  65. #if defined(sequent) || defined(convex)
  66. #define strrchr rindex
  67. #endif
  68. extern char *strrchr ();
  69.  
  70. /* This obstack is needed to hold text.  It is not safe to use
  71.    TOKEN_BUFFER because `check_newline' calls `yylex'.  */
  72. static struct obstack inline_text_obstack;
  73. static char *inline_text_firstobj;
  74.  
  75. /* Holds translations from TREE_CODEs to operator name strings,
  76.    i.e., opname_tab[PLUS_EXPR] == "+".  */
  77. char **opname_tab;
  78. char **assignop_tab;
  79.  
  80. #define YYEMPTY        -2
  81. int    yychar;            /*  the lookahead symbol        */
  82. YYSTYPE    yylval;            /*  the semantic value of the        */
  83.                 /*  lookahead symbol            */
  84.  
  85. #if 0
  86. YYLTYPE yylloc;            /*  location data for the lookahead    */
  87.                 /*  symbol                */
  88. #endif
  89.  
  90. int end_of_file;
  91.  
  92. /* the declaration found for the last IDENTIFIER token read in.
  93.    yylex must look this up to detect typedefs, which get token type TYPENAME,
  94.    so it is left around in case the identifier is not a typedef but is
  95.    used in a context which makes it a reference to a variable.  */
  96. tree lastiddecl;
  97.  
  98. /* C++ extensions */
  99. tree ridpointers[];        /* need this up here */
  100.  
  101. /* We may keep statistics about how long which files took to compile.  */
  102. static int header_time, body_time;
  103. static tree get_time_identifier ();
  104. static tree filename_times;
  105. static tree this_filename_time;
  106.  
  107. /* For implementing #pragma unit.  */
  108. tree current_unit_name;
  109. tree current_unit_language;
  110.  
  111. /* Array for holding counts of the numbers of tokens seen.  */
  112. int *token_count;
  113.  
  114. /* Return something to represent absolute declarators containing a *.
  115.    TARGET is the absolute declarator that the * contains.
  116.    TYPE_QUALS is a list of modifiers such as const or volatile
  117.    to apply to the pointer type, represented as identifiers.
  118.  
  119.    We return an INDIRECT_REF whose "contents" are TARGET
  120.    and whose type is the modifier list.  */
  121.  
  122. tree
  123. make_pointer_declarator (type_quals, target)
  124.      tree type_quals, target;
  125. {
  126.   if (target && TREE_CODE (target) == IDENTIFIER_NODE
  127.       && ANON_AGGRNAME_P (target))
  128.     error ("type name expected before `*'");
  129.   return build1 (INDIRECT_REF, type_quals, target);
  130. }
  131.  
  132. /* Return something to represent absolute declarators containing a &.
  133.    TARGET is the absolute declarator that the & contains.
  134.    TYPE_QUALS is a list of modifiers such as const or volatile
  135.    to apply to the reference type, represented as identifiers.
  136.  
  137.    We return an ADDR_EXPR whose "contents" are TARGET
  138.    and whose type is the modifier list.  */
  139.    
  140. tree
  141. make_reference_declarator (type_quals, target)
  142.      tree type_quals, target;
  143. {
  144.   if (target)
  145.     {
  146.       if (TREE_CODE (target) == ADDR_EXPR)
  147.     {
  148.       error ("cannot declare references to references");
  149.       return target;
  150.     }
  151.       if (TREE_CODE (target) == INDIRECT_REF)
  152.     {
  153.       error ("cannot declare pointers to references");
  154.       return target;
  155.     }
  156.       if (TREE_CODE (target) == IDENTIFIER_NODE && ANON_AGGRNAME_P (target))
  157.       error ("type name expected before `&'");
  158.     }
  159.   return build1 (ADDR_EXPR, type_quals, target);
  160. }
  161.  
  162. /* Given a chain of STRING_CST nodes,
  163.    concatenate them into one STRING_CST
  164.    and give it a suitable array-of-chars data type.  */
  165.  
  166. tree
  167. combine_strings (strings)
  168.      tree strings;
  169. {
  170.   register tree value, t;
  171.   register int length = 1;
  172.   int wide_length = 0;
  173.   int wide_flag = 0;
  174.  
  175.   if (TREE_CHAIN (strings))
  176.     {
  177.       /* More than one in the chain, so concatenate.  */
  178.       register char *p, *q;
  179.  
  180.       /* Don't include the \0 at the end of each substring,
  181.      except for the last one.
  182.      Count wide strings and ordinary strings separately.  */
  183.       for (t = strings; t; t = TREE_CHAIN (t))
  184.     {
  185.       if (TREE_TYPE (t) == int_array_type_node)
  186.         {
  187.           wide_length += (TREE_STRING_LENGTH (t) - 1);
  188.           wide_flag = 1;
  189.         }
  190.       else
  191.         length += (TREE_STRING_LENGTH (t) - 1);
  192.     }
  193.  
  194.       /* If anything is wide, the non-wides will be converted,
  195.      which makes them take more space.  */
  196.       if (wide_flag)
  197.     length = length * UNITS_PER_WORD + wide_length;
  198.  
  199.       p = (char *) savealloc (length);
  200.  
  201.       /* Copy the individual strings into the new combined string.
  202.      If the combined string is wide, convert the chars to ints
  203.      for any individual strings that are not wide.  */
  204.  
  205.       q = p;
  206.       for (t = strings; t; t = TREE_CHAIN (t))
  207.     {
  208.       int len = TREE_STRING_LENGTH (t) - 1;
  209.       if ((TREE_TYPE (t) == int_array_type_node) == wide_flag)
  210.         {
  211.           bcopy (TREE_STRING_POINTER (t), q, len);
  212.           q += len;
  213.         }
  214.       else
  215.         {
  216.           int i;
  217.           for (i = 0; i < len; i++)
  218.         ((int *) q)[i] = TREE_STRING_POINTER (t)[i];
  219.           q += len * UNITS_PER_WORD;
  220.         }
  221.     }
  222.       *q = 0;
  223.  
  224.       value = make_node (STRING_CST);
  225.       TREE_STRING_POINTER (value) = p;
  226.       TREE_STRING_LENGTH (value) = length;
  227.       TREE_LITERAL (value) = 1;
  228.     }
  229.   else
  230.     {
  231.       value = strings;
  232.       length = TREE_STRING_LENGTH (value);
  233.       if (TREE_TYPE (value) == int_array_type_node)
  234.     wide_flag = 1;
  235.     }
  236.  
  237.   /* Create the array type for the string constant.
  238.      -Wwrite-strings says make the string constant an array of const char
  239.      so that copying it to a non-const pointer will get a warning.  */
  240.   if (warn_write_strings)
  241.     {
  242.       tree elements
  243.     = build_type_variant (wide_flag ? integer_type_node : char_type_node,
  244.                   1, 0);
  245.       TREE_TYPE (value)
  246.     = build_array_type (elements,
  247.                 build_index_type (build_int_2 (length - 1, 0)));
  248.     }
  249.   else
  250.     TREE_TYPE (value)
  251.       = build_array_type (wide_flag ? integer_type_node : char_type_node,
  252.               build_index_type (build_int_2 (length - 1, 0)));
  253.   TREE_LITERAL (value) = 1;
  254.   TREE_STATIC (value) = 1;
  255.   return value;
  256. }
  257.  
  258. /* Build names and nodes for overloaded operators.  */
  259.  
  260. /* Memoized table for operator names.  */
  261. tree *node_table;
  262.  
  263. tree
  264. build_opid (code1, code2)
  265.      enum tree_code code1, code2;
  266. {
  267.   register tree t = make_node (OP_IDENTIFIER);
  268.   register tree tmp;
  269.   extern struct obstack *expression_obstack, permanent_obstack;
  270.   struct obstack *ambient_obstack = expression_obstack;
  271.   expression_obstack = &permanent_obstack;
  272.   if (code1 != 0)
  273.     {
  274.       if ((tmp = node_table[(int)code1]) == 0)
  275.     node_table[(int)code1] = tmp = make_node (code1);
  276.       TREE_PURPOSE (t) = tmp;
  277.     }
  278.   if ((tmp = node_table[(int)code2]) == 0)
  279.     node_table[(int)code2] = tmp = make_node (code2);
  280.   TREE_VALUE (t) = tmp;
  281.   expression_obstack = ambient_obstack;
  282.   return t;
  283. }
  284.  
  285. #ifdef __GNUC__
  286. #define DEFTREECODE(SYM, NAME, TYPE, LEN) sizeof (NAME),
  287. #else
  288. #define DEFTREECODE(SYM, NAME, TYPE, LEN) -1,
  289. #endif
  290. static short opname_end[] = {
  291. #include "tree.def"
  292. 7,                /* sizeof ("@@dummy"), */
  293. #include "cplus-tree.def"
  294. };
  295. #undef DEFTREECODE
  296.  
  297. /* Given a TOKEN and its estimated tree code CODE, produce a name which
  298.    can be recognized by lookup_name.  Based on the number of PARMS,
  299.    build an appropriate operator fnname.  This function is needed because
  300.    until we know how many parameters we have, we cannot reliably tell
  301.    what function indeed we are trying to declare.
  302.  
  303.    NPARMS is the number of additional parameters that this operator
  304.    will ultimately have.  If NPARMS == -1, then we are just building
  305.    a name, and should not complain.
  306.  
  307.    This would be a good candidate for memoizing.  */
  308. tree
  309. build_operator_fnname (declp, parms, nparms)
  310.      tree *declp;
  311.      tree parms;
  312.      int nparms;
  313. {
  314.   tree decl = *declp;
  315.   char **opname_table, *opname;
  316.   int assignop_p = 0;
  317.   tree rval;
  318.   enum tree_code code;
  319.   char buf[1024];
  320.   int saw_class = nparms;
  321.   int erred = 0;
  322.  
  323.   while (parms)
  324.     {
  325.       tree type;
  326.       if (parms == void_list_node)
  327.     break;
  328.  
  329.       if (! saw_class)
  330.     {
  331.       type = TREE_VALUE (parms);
  332.       if (TREE_CODE (type) == REFERENCE_TYPE)
  333.         type = TREE_TYPE (type);
  334.       if (TREE_CODE (type) == POINTER_TYPE)
  335.         type = TREE_TYPE (type);
  336.       if (IS_AGGR_TYPE (type))
  337.         saw_class = 1;
  338.     }
  339.       nparms++;
  340.       parms = TREE_CHAIN (parms);
  341.     }
  342.  
  343.   if (TREE_CODE (decl) == TYPE_EXPR)
  344.     {
  345.       /* @@ may need to perform type instantiation here.  */
  346.       if (nparms > 1)
  347.     error ("wrong number of arguments to type conversion operator");
  348.  
  349.       /* The grammar will swallow an "()" if one was given.
  350.      We attempt to correct for this lossage here.  */
  351.       if (TREE_OPERAND (decl, 0)
  352.       && TREE_CODE (TREE_OPERAND (decl, 0)) == CALL_EXPR)
  353.     {
  354.       rval = build_typename_overload (groktypename (build_tree_list (TREE_TYPE (decl), NULL_TREE)));
  355.       yychar = LEFT_RIGHT;
  356.     }
  357.       else
  358.     {
  359.       rval = build_typename_overload (groktypename (build_tree_list (TREE_TYPE (decl), TREE_OPERAND (decl, 0))));
  360.     }
  361.       return rval;
  362.     }
  363.  
  364.   if (TREE_PURPOSE (decl))
  365.     if (TREE_CODE (TREE_PURPOSE (decl)) == MODIFY_EXPR)
  366.       {
  367.     opname_table = assignop_tab;
  368.     assignop_p = 1;
  369.       }
  370.     else
  371.       abort ();
  372.   else
  373.     opname_table = opname_tab;
  374.  
  375.   code = TREE_CODE (TREE_VALUE (decl));
  376.   opname = opname_table[(int) code];
  377.  
  378.   if (assignop_p)
  379.     {
  380.       if (nparms == 1 || nparms > 2)
  381.     error ("wrong number of parameters op `operator %s'", opname);
  382.     }
  383.   else switch (code)
  384.     {
  385.     case ERROR_MARK:
  386.       rval = get_identifier ("<invalid operator>");
  387.       TREE_OVERLOADED (rval) = 1;
  388.       return rval;
  389.  
  390.       /* AC/DC */
  391.     case PLUS_EXPR:
  392.       if (nparms == 1)
  393.     code = CONVERT_EXPR;
  394.       else if (nparms != 2)
  395.     erred = 1;
  396.       break;
  397.  
  398.     case ADDR_EXPR:
  399.     case BIT_AND_EXPR:
  400.       if (nparms == 1)
  401.     code = ADDR_EXPR;
  402.       else if (nparms == 2)
  403.     code = BIT_AND_EXPR;
  404.       else
  405.     {
  406.       code = BIT_AND_EXPR;
  407.       erred = 1;
  408.     }
  409.       break;
  410.  
  411.     case MULT_EXPR:
  412.     case INDIRECT_REF:
  413.       if (nparms == 1)
  414.     code = INDIRECT_REF;
  415.       else if (nparms == 2)
  416.     code = MULT_EXPR;
  417.       else
  418.     {
  419.       code = MULT_EXPR;
  420.       erred = 1;
  421.     }
  422.       break;
  423.  
  424.     case MINUS_EXPR:
  425.     case NEGATE_EXPR:
  426.       if (nparms == 1)
  427.     code = NEGATE_EXPR;
  428.       else if (nparms == 2)
  429.     code = MINUS_EXPR;
  430.       else
  431.     {
  432.       code = MINUS_EXPR;
  433.       erred = 1;
  434.     }
  435.       break;
  436.  
  437.     case POINTSAT:
  438.       if (nparms == 1 || nparms < 0)
  439.     code = COMPONENT_REF;
  440.       else
  441.     {
  442.       erred = -1;
  443.       error ("wrong number of parameters to `operator ->()'");
  444.     }
  445.       break;
  446.  
  447.     case METHOD_CALL_EXPR:
  448.       switch (nparms)
  449.     {
  450.     case 0:
  451.     case 1:
  452.       erred = -1;
  453.       error ("too few arguments to `operator ->()(...)'");
  454.       break;
  455.       /* 4 happens when we pass in the canonical number
  456.          of arguments.  */
  457.     case 4:
  458.       nparms = 3;
  459.     case -1:
  460.     case 2:
  461.     case 3:
  462.       break;
  463.     default:
  464.       erred = -1;
  465.       error ("too many arguments to `operator ->()(...)'");
  466.       break;
  467.     }
  468.       break;
  469.  
  470.       /* The two following entrys are for two different ways of
  471.      encoding `operator ='.  */
  472.     case NOP_EXPR:
  473.       if (nparms != 2 && nparms >= 0)
  474.     erred = 1;
  475.       break;
  476.  
  477.     case MODIFY_EXPR:
  478.       if (nparms != 2 && nparms >= 0)
  479.     erred = 1;
  480.       break;
  481.  
  482.     case NEW_EXPR:
  483.       if (saw_class == 0)
  484.     {
  485.       if (nparms > 1)
  486.         return get_identifier (OPERATOR_NEW_FORMAT);
  487.       return get_identifier ("__builtin_new");
  488.     }
  489.       break;
  490.  
  491.     case DELETE_EXPR:
  492.       if (saw_class == 0)
  493.     {
  494.       if (nparms > 1)
  495.         error ("too many parameters to `operator ::delete'");
  496.       return get_identifier ("__builtin_delete");
  497.     }
  498. #ifdef NeXT
  499.       if (nparms > 3)
  500. #else /* NeXT */
  501.       if (nparms > 2)
  502. #endif /* NeXT */
  503.     erred = 1;
  504.       break;
  505.  
  506.       /* Whatever it was, we know its arity.  Just check that it
  507.          has the right number of parameters defined.  */
  508.     default:
  509.       /* These are the only operators which do not need
  510.      to have a class-type associated with them.  */
  511.  
  512.       if (code == PREDECREMENT_EXPR
  513.       || code == POSTINCREMENT_EXPR
  514.       || code == COMPONENT_REF)
  515.     {
  516.       if (nparms > 1)
  517.         erred = 1;
  518.     }
  519.       else if (nparms < 0
  520.            || code == CALL_EXPR
  521.            || code == METHOD_CALL_EXPR)
  522.     ;
  523.       else if (nparms != tree_code_length [(int) code])
  524.     erred = 1;
  525.       break;
  526.     }
  527.  
  528.   if (erred > 0)
  529.     error ("wrong number of parameters to `operator %s'", opname);
  530.   else if (erred == 0 && code != TREE_CODE (TREE_VALUE (decl)))
  531.     {
  532.       enum tree_code assign_code = ERROR_MARK;
  533.       if (TREE_PURPOSE (decl))
  534.     assign_code = TREE_CODE (TREE_PURPOSE (decl));
  535.       decl = build_opid (assign_code, code);
  536.       *declp = decl;
  537.     }
  538.  
  539.   if (! saw_class)
  540.     error ("`operator %s' must have at least one class type", opname);
  541.  
  542.   if (assignop_p)
  543.     {
  544.       sprintf (buf, OPERATOR_ASSIGN_FORMAT, tree_code_name [(int) code]);
  545.       buf[opname_end[(int) code] + sizeof (OPERATOR_ASSIGN_FORMAT) - 3] = '\0';
  546.     }
  547.   else
  548.     {
  549.       sprintf (buf, OPERATOR_FORMAT, tree_code_name [(int) code]);
  550.       buf[opname_end[(int) code] + sizeof (OPERATOR_FORMAT) - 3] = '\0';
  551.     }      
  552.   rval = get_identifier (buf);
  553.   TREE_OVERLOADED (rval) = 1;
  554.   return rval;
  555. }
  556.  
  557. char *
  558. operator_name_string (name)
  559.      tree name;
  560. {
  561.   char *opname = IDENTIFIER_POINTER (name)
  562.     + sizeof (OPERATOR_FORMAT) - sizeof ("%s");
  563.   int i, assign;
  564.  
  565.   /* Works for builtin and user defined types.  */
  566.   if (IDENTIFIER_GLOBAL_VALUE (name)
  567.       && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (name)) == TYPE_DECL)
  568.     return IDENTIFIER_POINTER (name);
  569.  
  570.   if (! strncmp (opname, "assign", 6))
  571.     {
  572.       opname += 7;
  573.       assign = 1;
  574.     }
  575.   else
  576.     assign = 0;
  577.  
  578.   for (i = 0; i < LAST_CPLUS_TREE_CODE; i++)
  579.     {
  580.       if (! strncmp (opname, tree_code_name[i], opname_end[i]))
  581.     break;
  582.     }
  583.  
  584.   assert (i != LAST_CPLUS_TREE_CODE);
  585.  
  586.   if (assign)
  587.     return assignop_tab[i];
  588.   else
  589.     return opname_tab[i];
  590. }
  591.  
  592. int lineno;            /* current line number in file being read */
  593.  
  594. FILE *finput;            /* input file.
  595.                    Normally a pipe from the preprocessor.  */
  596. static FILE *finput1;        /* Real input files: 1 is main input file */
  597. static FILE *finput2;        /* 2 is input file for inline functions */
  598.  
  599. int interface_only;        /* whether or not current file is only for
  600.                    interface definitions.  */
  601. int interface_unknown;        /* whether or not we know this class
  602.                    to behave according to #pragma interface.  */
  603.  
  604. /* lexical analyzer */
  605.  
  606. static int maxtoken;        /* Current nominal length of token buffer.  */
  607. char *token_buffer;        /* Pointer to token buffer.
  608.                    Actual allocated length is maxtoken + 2.  */
  609. static int max_wide;        /* Current nominal length of wide_buffer.  */
  610. static int *wide_buffer;    /* Pointer to wide-string buffer.
  611.                    Actual allocated length is max_wide + 1.  */
  612.  
  613. #define NORID RID_UNUSED
  614.  
  615. #ifdef OBJCPLUS
  616.  
  617. /* C code produced by gperf version 2.5 (GNU C++ version) */
  618. /* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$ objcplus.gperf  */
  619.  
  620. struct resword { 
  621.     char *name; 
  622.     short token;     
  623.     enum rid rid; 
  624.     enum languages lang; 
  625.     char *save; 
  626. };
  627.  
  628. #define TOTAL_KEYWORDS 84
  629. #define MIN_WORD_LENGTH 2
  630. #define MAX_WORD_LENGTH 20
  631. #define MIN_HASH_VALUE 4
  632. #define MAX_HASH_VALUE 147
  633. /* maximum key range = 144, duplicates = 0 */
  634.  
  635. #ifdef __GNUC__
  636. inline
  637. #endif
  638. static unsigned int
  639. hash (str, len)
  640.      register char *str;
  641.      register int unsigned len;
  642. {
  643.   static unsigned char asso_values[] =
  644.     {
  645.      148, 148, 148, 148, 148, 148, 148, 148, 148, 148,
  646.      148, 148, 148, 148, 148, 148, 148, 148, 148, 148,
  647.      148, 148, 148, 148, 148, 148, 148, 148, 148, 148,
  648.      148, 148, 148, 148, 148, 148, 148, 148, 148, 148,
  649.      148, 148, 148, 148, 148, 148, 148, 148, 148, 148,
  650.      148, 148, 148, 148, 148, 148, 148, 148, 148, 148,
  651.      148, 148, 148, 148,   9, 148, 148, 148, 148, 148,
  652.      148, 148, 148, 148, 148, 148, 148, 148, 148, 148,
  653.      148, 148, 148, 148, 148, 148, 148, 148, 148, 148,
  654.      148, 148, 148, 148, 148,   0, 148,  69,   3,  27,
  655.       43,   0,  47,  17,  25,   5, 148,   9,  71,   1,
  656.       62,  15,   9, 148,  31,   5,  26,   1,   1,   0,
  657.      148,   4, 148, 148, 148, 148, 148, 148,
  658.     };
  659.   register int hval = len;
  660.  
  661.   switch (hval)
  662.     {
  663.       default:
  664.       case 4:
  665.         hval += asso_values[str[3]];
  666.       case 3:
  667.       case 2:
  668.       case 1:
  669.         hval += asso_values[str[0]];
  670.     }
  671.   return hval + asso_values[str[len - 1]];
  672. }
  673.  
  674. static struct resword wordlist[] =
  675.     {
  676.       {"",}, {"",}, {"",}, {"",}, 
  677.       {"else",  ELSE, NORID, lang_c},
  678.       {"",}, 
  679.       {"enum",  ENUM, NORID, lang_c},
  680.       {"",}, {"",}, {"",}, {"",}, 
  681.       {"__asm",  ASM, NORID, lang_c},
  682.       {"__asm__",  ASM, NORID, lang_c},
  683.       {"",}, 
  684.       {"__typeof__",  TYPEOF, NORID, lang_c},
  685.       {"__signed__",  TYPESPEC, RID_SIGNED, lang_c},
  686.       {"inline",  SCSPEC, RID_INLINE, lang_c},
  687.       {"private",  PRIVATE, NORID, lang_cplusplus},
  688.       {"",}, {"",}, {"",}, {"",}, 
  689.       {"@private",  PRIVATE, NORID, lang_objc},
  690.       {"",}, 
  691.       {"__const__",  TYPE_QUAL, RID_CONST, lang_c},
  692.       {"__volatile",  TYPE_QUAL, RID_VOLATILE, lang_c},
  693.       {"",}, 
  694.       {"__volatile__",  TYPE_QUAL, RID_VOLATILE, lang_c},
  695.       {"",}, {"",}, {"",}, 
  696.       {"case",  CASE, NORID, lang_c},
  697.       {"except",  EXCEPT, NORID, lang_cplusplus        /* Extension */},
  698.       {"try",  TRY, NORID, lang_cplusplus        /* Extension */},
  699.       {"int",  TYPESPEC, RID_INT, lang_c},
  700.       {"@compatibility_alias",  ALIAS, NORID, lang_objc},
  701.       {"",}, 
  702.       {"__attribute",  ATTRIBUTE, NORID, lang_c},
  703.       {"struct",  AGGR, RID_RECORD, lang_c},
  704.       {"__attribute__",  ATTRIBUTE, NORID, lang_c},
  705.       {"this",  THIS, NORID, lang_cplusplus},
  706.       {"raise",  RAISE, NORID, lang_cplusplus        /* Extension */},
  707.       {"class",  AGGR, RID_CLASS, lang_cplusplus},
  708.       {"@encode",  ENCODE, NORID, lang_objc},
  709.       {"",}, 
  710.       {"@interface",  INTERFACE, NORID, lang_objc},
  711.       {"@public",  PUBLIC, NORID, lang_objc},
  712.       {"raises",  RAISES, NORID, lang_cplusplus        /* Extension */},
  713.       {"__const",  TYPE_QUAL, RID_CONST, lang_c},
  714.       {"delete",  DELETE, NORID, lang_cplusplus},
  715.       {"id",  OBJECTNAME, RID_ID, lang_objc},
  716.       {"goto",  GOTO, NORID, lang_c},
  717.       {"double",  TYPESPEC, RID_DOUBLE, lang_c},
  718.       {"",}, 
  719.       {"if",  IF, NORID, lang_c},
  720.       {"",}, 
  721.       {"__signed",  TYPESPEC, RID_SIGNED, lang_c},
  722.       {"unsigned",  TYPESPEC, RID_UNSIGNED, lang_c},
  723.       {"sizeof",  SIZEOF, NORID, lang_c},
  724.       {"__typeof",  TYPEOF, NORID, lang_c},
  725.       {"do",  DO, NORID, lang_c},
  726.       {"continue",  CONTINUE, NORID, lang_c},
  727.       {"switch",  SWITCH, NORID, lang_c},
  728.       {"const",  TYPE_QUAL, RID_CONST, lang_c},
  729.       {"static",  SCSPEC, RID_STATIC, lang_c},
  730.       {"new",  NEW, NORID, lang_cplusplus},
  731.       {"@defs",  DEFS, NORID, lang_objc},
  732.       {"short",  TYPESPEC, RID_SHORT, lang_c},
  733.       {"extern",  SCSPEC, RID_EXTERN, lang_c},
  734.       {"",}, 
  735.       {"__inline",  SCSPEC, RID_INLINE, lang_c},
  736.       {"exception",  AGGR, RID_EXCEPTION, lang_cplusplus /* Extension */},
  737.       {"__inline__",  SCSPEC, RID_INLINE, lang_c},
  738.       {"asm",  ASM, NORID, lang_c},
  739.       {"",}, 
  740.       {"register",  SCSPEC, RID_REGISTER, lang_c},
  741.       {"while",  WHILE, NORID, lang_c},
  742.       {"@protected",  PROTECTED, NORID, lang_objc},
  743.       {"volatile",  TYPE_QUAL, RID_VOLATILE, lang_c},
  744.       {"typeof",  TYPEOF, NORID, lang_c},
  745.       {"typedef",  SCSPEC, RID_TYPEDEF, lang_c},
  746.       {"for",  FOR, NORID, lang_c},
  747.       {"__alignof__",  ALIGNOF, NORID, lang_c},
  748.       {"union",  AGGR, RID_UNION, lang_c},
  749.       {"catch",  CATCH, NORID, lang_cplusplus},
  750.       {"operator",  OPERATOR, NORID, lang_cplusplus},
  751.       {"break",  BREAK, NORID, lang_c},
  752.       {"protected",  PROTECTED, NORID, lang_cplusplus},
  753.       {"",}, 
  754.       {"@class",  CLASS, NORID, lang_objc},
  755.       {"",}, 
  756.       {"void",  TYPESPEC, RID_VOID, lang_c},
  757.       {"",}, 
  758.       {"char",  TYPESPEC, RID_CHAR, lang_c},
  759.       {"",}, 
  760.       {"@implementation",  IMPLEMENTATION, NORID, lang_objc},
  761.       {"friend",  SCSPEC, RID_FRIEND, lang_cplusplus},
  762.       {"overload",  OVERLOAD, NORID, lang_cplusplus},
  763.       {"",}, 
  764.       {"@end",  END, NORID, lang_objc},
  765.       {"return",  RETURN, NORID, lang_c},
  766.       {"",}, {"",}, 
  767.       {"auto",  SCSPEC, RID_AUTO, lang_c},
  768.       {"@protocol",  PROTOCOL, NORID, lang_objc},
  769.       {"virtual",  SCSPEC, RID_VIRTUAL, lang_cplusplus},
  770.       {"",}, 
  771.       {"reraise",  RERAISE, NORID, lang_cplusplus    /* Extension */},
  772.       {"",}, 
  773.       {"long",  TYPESPEC, RID_LONG, lang_c},
  774.       {"",}, {"",}, {"",}, 
  775.       {"public",  PUBLIC, NORID, lang_cplusplus},
  776.       {"",}, {"",}, 
  777.       {"signed",  TYPESPEC, RID_SIGNED, lang_c},
  778.       {"",}, {"",}, {"",}, 
  779.       {"@selector",  SELECTOR, NORID, lang_objc},
  780.       {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
  781.       {"__alignof",  ALIGNOF, NORID, lang_c},
  782.       {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
  783.       {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
  784.       {"all",  ALL, NORID, lang_cplusplus        /* Extension */},
  785.       {"",}, 
  786.       {"default",  DEFAULT, NORID, lang_cplusplus},
  787.       {"dynamic",  DYNAMIC, NORID, lang_cplusplus},
  788.       {"float",  TYPESPEC, RID_FLOAT, lang_c},
  789.     };
  790.  
  791. #ifdef __GNUC__
  792. inline
  793. #endif
  794. struct resword *
  795. is_reserved_word (str, len)
  796.      register char *str;
  797.      register unsigned int len;
  798. {
  799.   if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
  800.     {
  801.       register int key = hash (str, len);
  802.  
  803.       if (key <= MAX_HASH_VALUE && key >= 0)
  804.         {
  805.           register char *s = wordlist[key].name;
  806.  
  807.           if (*s == *str && !strcmp (str + 1, s + 1))
  808.             return &wordlist[key];
  809.         }
  810.     }
  811.   return 0;
  812. }
  813.  
  814. void install_reserved_words (enum languages lang)
  815. {
  816.   int i, n = sizeof (wordlist) / sizeof (struct resword);
  817.  
  818.   for (i = 0; i < n; i++)
  819.     {
  820.       if (wordlist[i].name && *wordlist[i].name != '\0')
  821.     {
  822.       if (lang == lang_c || lang == lang_objc)
  823.         {
  824.           /* favor Objective-C for now...only suspend C++ keywords */
  825.           if (wordlist[i].lang == lang_cplusplus)
  826.         {
  827.           wordlist[i].save = wordlist[i].name;
  828.           wordlist[i].name = "";
  829.         }
  830.         }
  831.     }
  832.       else if (wordlist[i].save && *wordlist[i].save != '\0')
  833.     {
  834.       /* the keyword is currently suspended...
  835.          see if we should re-install it */
  836.     
  837.       if (lang == lang_cplusplus)
  838.         {
  839.           if (wordlist[i].lang == lang_cplusplus)
  840.         {
  841.           wordlist[i].name = wordlist[i].save;
  842.           wordlist[i].save = "";
  843.         }
  844.         }
  845.     }
  846.     }
  847. }
  848.  
  849. void
  850. forget_protocol_qualifiers ()
  851. {
  852.   int i, n = sizeof wordlist / sizeof (struct resword);
  853.  
  854.   for (i = 0; i < n; i++)
  855.     {
  856.       if (wordlist[i].rid >= RID_IN && wordlist[i].rid <= RID_ONEWAY)
  857.         wordlist[i].name = "";
  858.     }
  859. }
  860.  
  861. void
  862. remember_protocol_qualifiers ()
  863. {
  864.   int i, n = sizeof wordlist / sizeof (struct resword);
  865.  
  866.   for (i = 0; i < n; i++)
  867.     {
  868.       if (wordlist[i].rid == RID_IN)
  869.         wordlist[i].name = "in";
  870.       else if (wordlist[i].rid == RID_OUT)
  871.         wordlist[i].name = "out";
  872.       else if (wordlist[i].rid == RID_INOUT)
  873.         wordlist[i].name = "inout";
  874.       else if (wordlist[i].rid == RID_BYCOPY)
  875.         wordlist[i].name = "bycopy";
  876.       else if (wordlist[i].rid == RID_ONEWAY)
  877.         wordlist[i].name = "oneway";   
  878.     }
  879. }
  880.  
  881. #else /* OBJCPLUS */
  882.  
  883. /* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$ gplus.gperf  */
  884. struct resword { char *name; short token; enum rid rid;};
  885.  
  886. #define MIN_WORD_LENGTH 2
  887. #define MAX_WORD_LENGTH 13
  888. #define MIN_HASH_VALUE 4
  889. #define MAX_HASH_VALUE 147
  890. /*
  891.    71 keywords
  892.   144 is the maximum key range
  893. */
  894.  
  895. #ifdef __GNUC__
  896. inline
  897. #endif
  898. static int
  899. hash (str, len)
  900.      register char *str;
  901.      register int unsigned len;
  902. {
  903.   static unsigned char hash_table[] =
  904.     {
  905.      147, 147, 147, 147, 147, 147, 147, 147, 147, 147,
  906.      147, 147, 147, 147, 147, 147, 147, 147, 147, 147,
  907.      147, 147, 147, 147, 147, 147, 147, 147, 147, 147,
  908.      147, 147, 147, 147, 147, 147, 147, 147, 147, 147,
  909.      147, 147, 147, 147, 147, 147, 147, 147, 147, 147,
  910.      147, 147, 147, 147, 147, 147, 147, 147, 147, 147,
  911.      147, 147, 147, 147, 147, 147, 147, 147, 147, 147,
  912.      147, 147, 147, 147, 147, 147, 147, 147, 147, 147,
  913.      147, 147, 147, 147, 147, 147, 147, 147, 147, 147,
  914.      147, 147, 147, 147, 147,   0, 147,  19,   6,  27,
  915.       37,   0,  12,   1,  15,  63, 147,   4,   0,  56,
  916.       20,  15,  42, 147,  31,   5,  26,  39,  32,  10,
  917.      147,  40, 147, 147, 147, 147, 147, 147,
  918.     };
  919.   register int hval = len ;
  920.  
  921.   switch (hval)
  922.     {
  923.       default:
  924.       case 4:
  925.         hval += hash_table[str[3]];
  926.       case 3:
  927.       case 2:
  928.       case 1:
  929.         hval += hash_table[str[0]];
  930.     }
  931.   return hval + hash_table[str[len - 1]] ;
  932. }
  933.  
  934. #ifdef __GNUC__
  935. inline
  936. #endif
  937. struct resword *
  938. is_reserved_word (str, len)
  939.      register char *str;
  940.      register unsigned int len;
  941. {
  942.  
  943.   static struct resword  wordlist[] =
  944.     {
  945.       {"",}, {"",}, {"",}, {"",}, 
  946.       {"else",  ELSE, NORID,},
  947.       {"",}, 
  948.       {"long",  TYPESPEC, RID_LONG,},
  949.       {"",}, {"",}, {"",}, {"",}, 
  950.       {"__alignof__",  ALIGNOF, NORID},
  951.       {"__asm__",  ASM, NORID},
  952.       {"",}, {"",}, 
  953.       {"while",  WHILE, NORID,},
  954.       {"",}, {"",}, {"",}, {"",}, {"",}, 
  955.       {"__alignof",  ALIGNOF, NORID},
  956.       {"all",  ALL, NORID            /* Extension */,},
  957.       {"sizeof",  SIZEOF, NORID,},
  958.       {"__const__",  TYPE_QUAL, RID_CONST},
  959.       {"__volatile",  TYPE_QUAL, RID_VOLATILE},
  960.       {"extern",  SCSPEC, RID_EXTERN,},
  961.       {"__volatile__",  TYPE_QUAL, RID_VOLATILE},
  962.       {"__inline",  SCSPEC, RID_INLINE},
  963.       {"exception",  AGGR, RID_EXCEPTION    /* Extension */,},
  964.       {"__inline__",  SCSPEC, RID_INLINE},
  965.       {"case",  CASE, NORID,},
  966.       {"except",  EXCEPT, NORID        /* Extension */,},
  967.       {"new",  NEW, NORID,},
  968.       {"break",  BREAK, NORID,},
  969.       {"goto",  GOTO, NORID,},
  970.       {"",}, 
  971.       {"__attribute",  ATTRIBUTE, NORID},
  972.       {"",}, 
  973.       {"__attribute__",  ATTRIBUTE, NORID},
  974.       {"this",  THIS, NORID,},
  975.       {"raise",  RAISE, NORID        /* Extension */,},
  976.       {"class",  AGGR, RID_CLASS,},
  977.       {"delete",  DELETE, NORID,},
  978.       {"typeof",  TYPEOF, NORID,},
  979.       {"typedef",  SCSPEC, RID_TYPEDEF,},
  980.       {"for",  FOR, NORID,},
  981.       {"raises",  RAISES, NORID        /* Extension */,},
  982.       {"__const",  TYPE_QUAL, RID_CONST},
  983.       {"double",  TYPESPEC, RID_DOUBLE,},
  984.       {"__typeof__",  TYPEOF, NORID},
  985.       {"",}, 
  986.       {"switch",  SWITCH, NORID,},
  987.       {"auto",  SCSPEC, RID_AUTO,},
  988.       {"do",  DO, NORID,},
  989.       {"friend",  SCSPEC, RID_FRIEND,},
  990.       {"",}, 
  991.       {"reraise",  RERAISE, NORID        /* Extension */,},
  992.       {"",}, 
  993.       {"volatile",  TYPE_QUAL, RID_VOLATILE,},
  994.       {"__typeof",  TYPEOF, NORID},
  995.       {"continue",  CONTINUE, NORID,},
  996.       {"float",  TYPESPEC, RID_FLOAT,},
  997.       {"const",  TYPE_QUAL, RID_CONST,},
  998.       {"static",  SCSPEC, RID_STATIC,},
  999.       {"virtual",  SCSPEC, RID_VIRTUAL,},
  1000.       {"__asm",  ASM, NORID},
  1001.       {"short",  TYPESPEC, RID_SHORT,},
  1002.       {"signed",  TYPESPEC, RID_SIGNED,},
  1003.       {"try",  TRY, NORID            /* Extension */,},
  1004.       {"",}, {"",}, {"",}, 
  1005.       {"__signed__",  TYPESPEC, RID_SIGNED},
  1006.       {"catch",  CATCH, NORID,},
  1007.       {"public",  PUBLIC, NORID,},
  1008.       {"struct",  AGGR, RID_RECORD,},
  1009.       {"if",  IF, NORID,},
  1010.       {"asm",  ASM, NORID,},
  1011.       {"union",  AGGR, RID_UNION,},
  1012.       {"",}, 
  1013.       {"private",  PRIVATE, NORID,},
  1014.       {"",}, {"",}, {"",}, 
  1015.       {"operator",  OPERATOR, NORID,},
  1016.       {"",}, {"",}, {"",}, 
  1017.       {"default",  DEFAULT, NORID,},
  1018.       {"dynamic",  DYNAMIC, NORID,},
  1019.       {"overload",  OVERLOAD, NORID,},
  1020.       {"int",  TYPESPEC, RID_INT,},
  1021.       {"char",  TYPESPEC, RID_CHAR,},
  1022.       {"",}, {"",}, 
  1023.       {"return",  RETURN, NORID,},
  1024.       {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
  1025.       {"",}, {"",}, 
  1026.       {"__signed",  TYPESPEC, RID_SIGNED},
  1027.       {"",}, 
  1028.       {"void",  TYPESPEC, RID_VOID,},
  1029.       {"",}, {"",}, {"",}, 
  1030.       {"protected",  PROTECTED, NORID,},
  1031.       {"",}, 
  1032.       {"enum",  ENUM, NORID,},
  1033.       {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
  1034.       {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
  1035.       {"inline",  SCSPEC, RID_INLINE,},
  1036.       {"register",  SCSPEC, RID_REGISTER,},
  1037.       {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
  1038.       {"",}, {"",}, {"",}, {"",}, 
  1039.       {"unsigned",  TYPESPEC, RID_UNSIGNED,},
  1040.     };
  1041.  
  1042.   if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
  1043.     {
  1044.       register int key = hash (str, len);
  1045.  
  1046.       if (key <= MAX_HASH_VALUE && key >= MIN_HASH_VALUE)
  1047.         {
  1048.           register char *s = wordlist[key].name;
  1049.  
  1050.           if (*s == *str && !strcmp (str + 1, s + 1))
  1051.             return &wordlist[key];
  1052.         }
  1053.     }
  1054.   return 0;
  1055. }
  1056.  
  1057. #endif /* OBJCPLUS */
  1058.  
  1059. /* The elements of `ridpointers' are identifier nodes
  1060.    for the reserved type names and storage classes.
  1061.    It is indexed by a RID_... value.  */
  1062.  
  1063. tree ridpointers[(int) RID_MAX];
  1064.  
  1065. int check_newline ();
  1066.  
  1067. static int skip_white_space ();
  1068.  
  1069. static tree
  1070. get_time_identifier (name)
  1071.      char *name;
  1072. {
  1073.   tree time_identifier;
  1074.   int len = strlen (name);
  1075.   char *buf = (char *)alloca (len + 6);
  1076.   strcpy (buf, "file ");
  1077.   bcopy (name, buf+5, len);
  1078.   buf[len+5] = '\0';
  1079.   time_identifier = get_identifier (buf);
  1080.   if (IDENTIFIER_LOCAL_VALUE (time_identifier) == NULL_TREE)
  1081.     {
  1082.       int temp = allocation_temporary_p ();
  1083.       if (temp)
  1084.     end_temporary_allocation ();
  1085.       IDENTIFIER_LOCAL_VALUE (time_identifier) = build_int_2 (0, 0);
  1086.       IDENTIFIER_CLASS_VALUE (time_identifier) = build_int_2 (0, 1);
  1087.       IDENTIFIER_GLOBAL_VALUE (time_identifier) = filename_times;
  1088.       filename_times = time_identifier;
  1089.       if (temp)
  1090.     resume_temporary_allocation ();
  1091.     }
  1092.   return time_identifier;
  1093. }
  1094.  
  1095. #ifdef __GNUC__
  1096. __inline
  1097. #endif
  1098. static int
  1099. my_gettime ()
  1100. {
  1101.   int old_quiet_flag = quiet_flag;
  1102.   int this_time;
  1103.   quiet_flag = 0;
  1104.   this_time = gettime ();
  1105.   quiet_flag = old_quiet_flag;
  1106.   return this_time;
  1107. }
  1108.  
  1109. /* Table indexed by tree code giving a string containing a character
  1110.    classifying the tree code.  Possibilities are
  1111.    t, d, s, c, r and e.  See cplus-tree.def for details.  */
  1112.  
  1113. #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
  1114.  
  1115. char *cplus_tree_code_type[] = {
  1116.   "x",
  1117. #include "cplus-tree.def"
  1118. };
  1119. #undef DEFTREECODE
  1120.  
  1121. /* Table indexed by tree code giving number of expression
  1122.    operands beyond the fixed part of the node structure.
  1123.    Not used for types or decls.  */
  1124.  
  1125. #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
  1126.  
  1127. int cplus_tree_code_length[] = {
  1128.   0,
  1129. #include "cplus-tree.def"
  1130. };
  1131. #undef DEFTREECODE
  1132.  
  1133. /* Names of tree components.
  1134.    Used for printing out the tree and error messages.  */
  1135. #define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
  1136.  
  1137. char *cplus_tree_code_name[] = {
  1138.   "@@dummy",
  1139. #include "cplus-tree.def"
  1140. };
  1141. #undef DEFTREECODE
  1142.  
  1143. void
  1144. init_filename_times ()
  1145. {
  1146.   this_filename_time = get_time_identifier ("<top level>");
  1147.   if (flag_detailed_statistics)
  1148.     {
  1149.       header_time = 0;
  1150.       body_time = my_gettime ();
  1151.       TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time)) = body_time;
  1152.     }
  1153. }
  1154.  
  1155. /* Change by Bryan Boreham, Kewill, Thu Jul 27 09:46:05 1989.
  1156.    Stuck this hack in to get the files open correctly; this is called
  1157.    in place of init_lex if we are an unexec'd binary.    */
  1158. void
  1159. reinit_lex_for_unexec ()
  1160. {
  1161.   finput1 = finput;
  1162.   finput2 = fopen (NULL_FILE, "r");
  1163.   init_filename_times ();
  1164. }
  1165.  
  1166. void
  1167. init_lex ()
  1168. {
  1169.   extern int *init_parse ();
  1170.   extern char *(*decl_printable_name) ();
  1171.   extern char *lang_printable_name ();
  1172.   extern struct rtx_def *(*lang_expand_expr) ();
  1173.   extern struct rtx_def *cplus_expand_expr ();
  1174.  
  1175.   int i;
  1176.  
  1177.   /* Make identifier nodes long enough for the language-specific slots.  */
  1178.   set_identifier_size (sizeof (struct lang_identifier));
  1179.   decl_printable_name = lang_printable_name;
  1180.   lang_expand_expr = cplus_expand_expr;
  1181.  
  1182.   tree_code_type
  1183.     = (char **) realloc (tree_code_type,
  1184.              sizeof (char *) * LAST_CPLUS_TREE_CODE);
  1185.   tree_code_length
  1186.     = (int *) realloc (tree_code_length,
  1187.                sizeof (int) * LAST_CPLUS_TREE_CODE);
  1188.   tree_code_name
  1189.     = (char **) realloc (tree_code_name,
  1190.              sizeof (char *) * LAST_CPLUS_TREE_CODE);
  1191.   bcopy (cplus_tree_code_type,
  1192.      tree_code_type + LAST_AND_UNUSED_TREE_CODE,
  1193.      (LAST_CPLUS_TREE_CODE - LAST_AND_UNUSED_TREE_CODE) * sizeof (char *));
  1194.   bcopy (cplus_tree_code_length,
  1195.      tree_code_length + LAST_AND_UNUSED_TREE_CODE,
  1196.      (LAST_CPLUS_TREE_CODE - LAST_AND_UNUSED_TREE_CODE) * sizeof (int));
  1197.   bcopy (cplus_tree_code_name,
  1198.      tree_code_name + LAST_AND_UNUSED_TREE_CODE,
  1199.      (LAST_CPLUS_TREE_CODE - LAST_AND_UNUSED_TREE_CODE) * sizeof (char *));
  1200.  
  1201.   node_table = (tree *)oballoc (LAST_CPLUS_TREE_CODE * sizeof (tree));
  1202.   opname_tab = (char **)oballoc (LAST_CPLUS_TREE_CODE * sizeof (char *));
  1203.   assignop_tab = (char **)oballoc (LAST_CPLUS_TREE_CODE * sizeof (char *));
  1204.  
  1205.   for (i = 0; i < LAST_CPLUS_TREE_CODE; i++)
  1206.     /* Our only interest is _ref and _expr.  */
  1207.     if (tree_code_type[i][0] == 'r' || tree_code_type[i][0] == 'e')
  1208.       {
  1209.     char *end = (char *)strrchr (tree_code_name[i], '_');
  1210.     if (end)
  1211.       opname_end[i] = end - tree_code_name[i];
  1212. #ifndef __GNUC__
  1213.     else
  1214.       opname_end[i] = strlen (tree_code_name[i]);
  1215. #endif
  1216.       }
  1217. #ifndef __GNUC__
  1218.     else
  1219.       opname_end[i] = strlen (tree_code_name[i]);
  1220. #endif
  1221.  
  1222.   init_method ();
  1223.   obstack_init (&inline_text_obstack);
  1224.   inline_text_firstobj = (char *) obstack_alloc (&inline_text_obstack, 0);
  1225.  
  1226.   /* Start it at 0, because check_newline is called at the very beginning
  1227.      and will increment it to 1.  */
  1228.   lineno = 0;
  1229.   finput1 = finput;
  1230.   finput2 = fopen (NULL_FILE, "r");
  1231.   current_function_decl = NULL;
  1232.  
  1233.   maxtoken = 40;
  1234.   token_buffer = (char *) xmalloc (maxtoken + 2);
  1235.   max_wide = 40;
  1236.   wide_buffer = (int *) xmalloc (max_wide + 1);
  1237.  
  1238.   ridpointers[(int) RID_INT] = get_identifier ("int");
  1239.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_INT],
  1240.               build_tree_list (NULL_TREE, ridpointers[(int) RID_INT]));
  1241.   ridpointers[(int) RID_CHAR] = get_identifier ("char");
  1242.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_CHAR],
  1243.               build_tree_list (NULL_TREE, ridpointers[(int) RID_CHAR]));
  1244.   ridpointers[(int) RID_VOID] = get_identifier ("void");
  1245.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VOID],
  1246.               build_tree_list (NULL_TREE, ridpointers[(int) RID_VOID]));
  1247.   ridpointers[(int) RID_FLOAT] = get_identifier ("float");
  1248.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_FLOAT],
  1249.               build_tree_list (NULL_TREE, ridpointers[(int) RID_FLOAT]));
  1250.   ridpointers[(int) RID_DOUBLE] = get_identifier ("double");
  1251.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_DOUBLE],
  1252.               build_tree_list (NULL_TREE, ridpointers[(int) RID_DOUBLE]));
  1253.   ridpointers[(int) RID_SHORT] = get_identifier ("short");
  1254.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_SHORT],
  1255.               build_tree_list (NULL_TREE, ridpointers[(int) RID_SHORT]));
  1256.   ridpointers[(int) RID_LONG] = get_identifier ("long");
  1257.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_LONG],
  1258.               build_tree_list (NULL_TREE, ridpointers[(int) RID_LONG]));
  1259.   ridpointers[(int) RID_UNSIGNED] = get_identifier ("unsigned");
  1260.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_UNSIGNED],
  1261.               build_tree_list (NULL_TREE, ridpointers[(int) RID_UNSIGNED]));
  1262.   ridpointers[(int) RID_SIGNED] = get_identifier ("signed");
  1263.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_SIGNED],
  1264.               build_tree_list (NULL_TREE, ridpointers[(int) RID_SIGNED]));
  1265.   ridpointers[(int) RID_INLINE] = get_identifier ("inline");
  1266.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_INLINE],
  1267.               build_tree_list (NULL_TREE, ridpointers[(int) RID_INLINE]));
  1268.   ridpointers[(int) RID_CONST] = get_identifier ("const");
  1269.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_CONST],
  1270.               build_tree_list (NULL_TREE, ridpointers[(int) RID_CONST]));
  1271.   ridpointers[(int) RID_VOLATILE] = get_identifier ("volatile");
  1272.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VOLATILE],
  1273.               build_tree_list (NULL_TREE, ridpointers[(int) RID_VOLATILE]));
  1274.   ridpointers[(int) RID_AUTO] = get_identifier ("auto");
  1275.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_AUTO],
  1276.               build_tree_list (NULL_TREE, ridpointers[(int) RID_AUTO]));
  1277.   ridpointers[(int) RID_STATIC] = get_identifier ("static");
  1278.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_STATIC],
  1279.               build_tree_list (NULL_TREE, ridpointers[(int) RID_STATIC]));
  1280.   ridpointers[(int) RID_EXTERN] = get_identifier ("extern");
  1281.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_EXTERN],
  1282.               build_tree_list (NULL_TREE, ridpointers[(int) RID_EXTERN]));
  1283.   ridpointers[(int) RID_TYPEDEF] = get_identifier ("typedef");
  1284.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_TYPEDEF],
  1285.               build_tree_list (NULL_TREE, ridpointers[(int) RID_TYPEDEF]));
  1286.   ridpointers[(int) RID_REGISTER] = get_identifier ("register");
  1287.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_REGISTER],
  1288.               build_tree_list (NULL_TREE, ridpointers[(int) RID_REGISTER]));
  1289.  
  1290. #ifdef OBJCPLUS
  1291.   /* protocol additions */
  1292.   ridpointers[(int) RID_ID] = get_identifier ("id");
  1293.   ridpointers[(int) RID_IN] = get_identifier ("in");
  1294.   ridpointers[(int) RID_OUT] = get_identifier ("out");
  1295.   ridpointers[(int) RID_INOUT] = get_identifier ("inout");
  1296.   ridpointers[(int) RID_BYCOPY] = get_identifier ("bycopy");
  1297.   ridpointers[(int) RID_ONEWAY] = get_identifier ("oneway");
  1298.   forget_protocol_qualifiers ();
  1299. #endif /* OBJCPLUS */
  1300.  
  1301.   /* C++ extensions. These are probably not correctly named. */
  1302.   class_type_node = build_int_2 (class_type, 0);
  1303.   TREE_TYPE (class_type_node) = class_type_node;
  1304.   ridpointers[(int) RID_CLASS] = class_type_node;
  1305.  
  1306.   record_type_node = build_int_2 (record_type, 0);
  1307.   TREE_TYPE (record_type_node) = record_type_node;
  1308.   ridpointers[(int) RID_RECORD] = record_type_node;
  1309.  
  1310.   union_type_node = build_int_2 (union_type, 0);
  1311.   TREE_TYPE (union_type_node) = union_type_node;
  1312.   ridpointers[(int) RID_UNION] = union_type_node;
  1313.  
  1314.   enum_type_node = build_int_2 (enum_type, 0);
  1315.   TREE_TYPE (enum_type_node) = enum_type_node;
  1316.   ridpointers[(int) RID_ENUM] = enum_type_node;
  1317.  
  1318.   ridpointers[(int) RID_VIRTUAL] = get_identifier ("virtual");
  1319.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_VIRTUAL],
  1320.               build_tree_list (NULL_TREE, ridpointers[(int) RID_VIRTUAL]));
  1321.   ridpointers[(int) RID_FRIEND] = get_identifier ("friend");
  1322.   SET_IDENTIFIER_AS_LIST (ridpointers[(int) RID_FRIEND],
  1323.               build_tree_list (NULL_TREE, ridpointers[(int) RID_FRIEND]));
  1324.  
  1325.   /* Exception handling extensions.  */
  1326.   exception_type_node = build_int_2 (exception_type, 0);
  1327.   TREE_TYPE (exception_type_node) = exception_type_node;
  1328.   ridpointers[(int) RID_EXCEPTION] = exception_type_node;
  1329.  
  1330.   opname_tab[(int) COMPONENT_REF] = "->";
  1331.   opname_tab[(int) METHOD_CALL_EXPR] = "->()";
  1332.   opname_tab[(int) INDIRECT_REF] = "(unary *)";
  1333.   opname_tab[(int) ARRAY_REF] = "[]";
  1334.   opname_tab[(int) MODIFY_EXPR] = "=";
  1335.   opname_tab[(int) NEW_EXPR] = "new";
  1336.   opname_tab[(int) DELETE_EXPR] = "delete";
  1337.   opname_tab[(int) COND_EXPR] = "... ? ... : ...";
  1338.   opname_tab[(int) CALL_EXPR] = "()";
  1339.   opname_tab[(int) PLUS_EXPR] = "+";
  1340.   opname_tab[(int) MINUS_EXPR] = "-";
  1341.   opname_tab[(int) MULT_EXPR] = "*";
  1342.   opname_tab[(int) TRUNC_DIV_EXPR] = "/";
  1343.   opname_tab[(int) CEIL_DIV_EXPR] = "(ceiling /)";
  1344.   opname_tab[(int) FLOOR_DIV_EXPR] = "(floor /)";
  1345.   opname_tab[(int) ROUND_DIV_EXPR] = "(round /)";
  1346.   opname_tab[(int) TRUNC_MOD_EXPR] = "%";
  1347.   opname_tab[(int) CEIL_MOD_EXPR] = "(ceiling %)";
  1348.   opname_tab[(int) FLOOR_MOD_EXPR] = "(floor %)";
  1349.   opname_tab[(int) ROUND_MOD_EXPR] = "(round %)";
  1350.   opname_tab[(int) NEGATE_EXPR] = "-";
  1351.   opname_tab[(int) MIN_EXPR] = "<?";
  1352.   opname_tab[(int) MAX_EXPR] = ">?";
  1353.   opname_tab[(int) ABS_EXPR] = "abs";
  1354.   opname_tab[(int) FFS_EXPR] = "ffs";
  1355.   opname_tab[(int) LSHIFT_EXPR] = "<<";
  1356.   opname_tab[(int) RSHIFT_EXPR] = ">>";
  1357.   opname_tab[(int) BIT_IOR_EXPR] = "|";
  1358.   opname_tab[(int) BIT_XOR_EXPR] = "^";
  1359.   opname_tab[(int) BIT_AND_EXPR] = "&";
  1360.   opname_tab[(int) BIT_ANDTC_EXPR] = "&~";
  1361.   opname_tab[(int) BIT_NOT_EXPR] = "~";
  1362.   opname_tab[(int) TRUTH_ANDIF_EXPR] = "&&";
  1363.   opname_tab[(int) TRUTH_ORIF_EXPR] = "||";
  1364.   opname_tab[(int) TRUTH_AND_EXPR] = "strict &&";
  1365.   opname_tab[(int) TRUTH_OR_EXPR] = "strict ||";
  1366.   opname_tab[(int) TRUTH_NOT_EXPR] = "!";
  1367.   opname_tab[(int) LT_EXPR] = "<";
  1368.   opname_tab[(int) LE_EXPR] = "<=";
  1369.   opname_tab[(int) GT_EXPR] = ">";
  1370.   opname_tab[(int) GE_EXPR] = ">=";
  1371.   opname_tab[(int) EQ_EXPR] = "==";
  1372.   opname_tab[(int) NE_EXPR] = "!=";
  1373.   opname_tab[(int) IN_EXPR] = "in";
  1374.   opname_tab[(int) SET_LE_EXPR] = "subset";
  1375.   opname_tab[(int) CARD_EXPR] = "#";
  1376.   opname_tab[(int) RANGE_EXPR] = "..";
  1377.   opname_tab[(int) CONVERT_EXPR] = "(unary +)";
  1378.   opname_tab[(int) ADDR_EXPR] = "(unary &)";
  1379.   opname_tab[(int) PREDECREMENT_EXPR] = "--";
  1380.   opname_tab[(int) PREINCREMENT_EXPR] = "++";
  1381.   opname_tab[(int) POSTDECREMENT_EXPR] = "--";
  1382.   opname_tab[(int) POSTINCREMENT_EXPR] = "++";
  1383.   opname_tab[(int) COMPOUND_EXPR] = ",";
  1384.   assignop_tab[(int) NOP_EXPR] = "=";
  1385.   assignop_tab[(int) PLUS_EXPR] =  "+=";
  1386.   assignop_tab[(int) MINUS_EXPR] = "-=";
  1387.   assignop_tab[(int) MULT_EXPR] = "*=";
  1388.   assignop_tab[(int) TRUNC_DIV_EXPR] = "/=";
  1389.   assignop_tab[(int) CEIL_DIV_EXPR] = "(ceiling /=)";
  1390.   assignop_tab[(int) FLOOR_DIV_EXPR] = "(floor /=)";
  1391.   assignop_tab[(int) ROUND_DIV_EXPR] = "(round /=)";
  1392.   assignop_tab[(int) TRUNC_MOD_EXPR] = "%=";
  1393.   assignop_tab[(int) CEIL_MOD_EXPR] = "(ceiling %=)";
  1394.   assignop_tab[(int) FLOOR_MOD_EXPR] = "(floor %=)";
  1395.   assignop_tab[(int) ROUND_MOD_EXPR] = "(round %=)";
  1396.   assignop_tab[(int) MIN_EXPR] = "<?=";
  1397.   assignop_tab[(int) MAX_EXPR] = ">?=";
  1398.   assignop_tab[(int) LSHIFT_EXPR] = "<<=";
  1399.   assignop_tab[(int) RSHIFT_EXPR] = ">>=";
  1400.   assignop_tab[(int) BIT_IOR_EXPR] = "|=";
  1401.   assignop_tab[(int) BIT_XOR_EXPR] = "^=";
  1402.   assignop_tab[(int) BIT_AND_EXPR] = "&=";
  1403.  
  1404.   init_filename_times ();
  1405.  
  1406. #define UNSET_RESERVED_WORD(STRING) \
  1407.   do { is_reserved_word (STRING, sizeof (STRING) - 1)->name = ""; } while (0)
  1408.  
  1409.   if (! flag_handle_exceptions)
  1410.     {
  1411.       /* Easiest way to not reconize exception
  1412.      handling extenions...  */
  1413.       UNSET_RESERVED_WORD ("all");
  1414.       UNSET_RESERVED_WORD ("except");
  1415.       UNSET_RESERVED_WORD ("exception");
  1416.       UNSET_RESERVED_WORD ("raise");
  1417.       UNSET_RESERVED_WORD ("raises");
  1418.       UNSET_RESERVED_WORD ("reraise");
  1419.       UNSET_RESERVED_WORD ("try");
  1420.     }
  1421.   if (flag_no_asm)
  1422.     UNSET_RESERVED_WORD ("asm");
  1423.   if (flag_no_asm || flag_traditional)
  1424.     UNSET_RESERVED_WORD ("typeof");
  1425.   token_count = init_parse ();
  1426.   interface_unknown = 1;
  1427. }
  1428.  
  1429. void
  1430. reinit_parse_for_function ()
  1431. {
  1432.   current_base_init_list = NULL_TREE;
  1433.   current_member_init_list = NULL_TREE;
  1434. }
  1435.  
  1436. /* Functions and data structures for #pragma interface.
  1437.  
  1438.    `#pragma implementation' means that the main file being compiled
  1439.    is considered to implement (provide) the classes that appear in
  1440.    its main body.  I.e., if this is file "foo.cc", and class `bar'
  1441.    is defined in "foo.cc", then we say that "foo.cc implements bar".
  1442.  
  1443.    All main input files "implement" themselves automagically.
  1444.  
  1445.    `#pragma interface' means that unless this file (of the form "foo.h"
  1446.    is not presently being included by file "foo.cc", the
  1447.    CLASSTYPE_INTERFACE_ONLY bit gets set.  The effect is that none
  1448.    of the vtables nor any of the inline functions defined in foo.h
  1449.    will every be output.
  1450.  
  1451.    There are cases when we want to link files such as "defs.h" and
  1452.    "main.cc".  In this case, we give "defs.h" a `#pragma interface',
  1453.    and "main.cc" has `#pragma implementation "defs.h"'.  */
  1454.  
  1455. struct impl_files
  1456. {
  1457.   char *filename;
  1458.   struct impl_files *next;
  1459. };
  1460.  
  1461. static struct impl_files *impl_file_chain;
  1462.  
  1463. /* Helper function to load global variables with interface
  1464.    information.  */
  1465. static void
  1466. extract_interface_info ()
  1467. {
  1468.   tree fileinfo = get_time_identifier (input_filename);
  1469.   fileinfo = IDENTIFIER_CLASS_VALUE (fileinfo);
  1470.   interface_only = TREE_INT_CST_LOW (fileinfo);
  1471.   interface_unknown = TREE_INT_CST_HIGH (fileinfo);
  1472. }
  1473.  
  1474. /* Return nonzero if S and T are not considered part of an
  1475.    INTERFACE/IMPLEMENTATION pair.  Otherwise, return 0.  */
  1476. static int
  1477. interface_strcmp (s)
  1478.      char *s;
  1479. {
  1480.   /* Set the interface/implementation bits for this scope.  */
  1481.   struct impl_files *ifiles;
  1482.   char *s1 = strrchr (s, '/');
  1483.   if (s1++ == 0)
  1484.     s1 = s;
  1485.   s = s1;
  1486.  
  1487.   for (ifiles = impl_file_chain; ifiles; ifiles = ifiles->next)
  1488.     {
  1489.       char *t1 = ifiles->filename;
  1490.       s1 = s;
  1491.  
  1492.       if (*s1 != *t1 || *s1 == 0)
  1493.     continue;
  1494.  
  1495.       while (*s1 == *t1 && *s1 != 0)
  1496.     s1++, t1++;
  1497.  
  1498.       /* A match.  */
  1499.       if (*s1 == *t1)
  1500.     return 0;
  1501.  
  1502.       /* Don't get faked out by xxx.yyy.cc vs xxx.zzz.cc.  */
  1503.       if (strchr (s1, '.'))
  1504.     continue;
  1505.  
  1506.       if (*s1 == '\0' || s1[-1] != '.' || t1[-1] != '.')
  1507.     continue;
  1508.  
  1509.       /* A match.  */
  1510.       return 0;
  1511.     }
  1512.  
  1513.   /* No matches.  */
  1514.   return 1;
  1515. }
  1516.  
  1517. void
  1518. set_typedecl_interface_info (prev, vars)
  1519.      tree prev, vars;
  1520. {
  1521.   tree id = get_time_identifier (DECL_SOURCE_FILE (vars));
  1522.   tree fileinfo = IDENTIFIER_CLASS_VALUE (id);
  1523.   tree type = TREE_TYPE (vars);
  1524.  
  1525.   CLASSTYPE_INTERFACE_ONLY (type) = TREE_INT_CST_LOW (fileinfo)
  1526.     = interface_strcmp (DECL_SOURCE_FILE (vars));
  1527. }
  1528.  
  1529. void
  1530. set_vardecl_interface_info (prev, vars)
  1531.      tree prev, vars;
  1532. {
  1533. #if 0
  1534.   tree type = DECL_VPARENT (vars);
  1535. #else
  1536.   tree type = DECL_CONTEXT (vars);
  1537. #endif
  1538.  
  1539.   if (CLASSTYPE_INTERFACE_UNKNOWN (type) == 0)
  1540.     {
  1541.       if (CLASSTYPE_INTERFACE_ONLY (type))
  1542.     set_typedecl_interface_info (prev, TYPE_NAME (type));
  1543.       TREE_EXTERNAL (vars) = CLASSTYPE_INTERFACE_ONLY (type);
  1544.       TREE_PUBLIC (vars) = ! CLASSTYPE_INTERFACE_ONLY (type);
  1545.       CLASSTYPE_VTABLE_NEEDS_WRITING (type) |= TREE_PUBLIC (vars);
  1546.     }
  1547. }
  1548.  
  1549. /* Called from the top level: if there are any pending inlines to
  1550.    do, set up to process them now.  */
  1551. void
  1552. do_pending_inlines ()
  1553. {
  1554.   if (finput == finput1)
  1555.     {
  1556.       struct pending_inline *prev = 0, *tail;
  1557.       struct pending_inline *t =
  1558.     (struct pending_inline *) obstack_alloc (&inline_text_obstack,
  1559.                          sizeof (struct pending_inline));
  1560.  
  1561.       /* Record state we were in when we decided to process
  1562.      inline functions instead.  */
  1563.       t->next = pending_inlines;
  1564.       pending_inlines = t;
  1565.       t->lineno = lineno;
  1566.       t->filename = input_filename;
  1567.       t->fndecl = NULL_TREE;
  1568.       t->token = yychar;
  1569.       t->token_value = yylval.itype;
  1570.  
  1571.       /* Reverse the pending inline functions, since
  1572.      they were cons'd instead of appended.  */
  1573.  
  1574.       for (; t; t = tail)
  1575.     {
  1576.       tail = t->next;
  1577.       t->next = prev;
  1578.       prev = t;
  1579.     }
  1580.       pending_inlines = prev;
  1581.  
  1582.       /* Now start processing the first inline function.  */
  1583.       t = pending_inlines;
  1584.       pending_inlines = pending_inlines->next;
  1585.       finput = finput2;
  1586. #ifdef MASSCOMP
  1587.       setbuf (finput2, t->buf);
  1588.       finput2->_cnt = t->len-1;
  1589. #else
  1590. #if defined(i386) && !defined(sequent) && !defined(sun386)
  1591.       finput2->_ptr = finput2->_base = t->buf;
  1592.       _bufend(finput2) = t->buf + t->len;
  1593.       finput2->_flag = _IOFBF | _IOREAD;
  1594.       finput2->_cnt = t->len - 1;
  1595. #else
  1596. #ifndef hp9000s300
  1597. #ifdef USG_STDIO
  1598.       setvbuf(finput2,t->buf,_IOFBF,t->len);
  1599.       finput2->_cnt = t->len-1;
  1600. #else
  1601. #ifdef VMS
  1602.       setvbuf(finput2,t->buf,_IOFBF,t->len);
  1603.       (*finput2)->_cnt = t->len-1;
  1604. #else
  1605.       setbuffer (finput2, t->buf, t->len);
  1606.       finput2->_cnt = finput2->_bufsiz - 1;
  1607. #endif                /* VMS */
  1608. #endif                /* USG_STDIO */
  1609. #else
  1610.       setvbuf(finput2,t->buf,_IOFBF,t->len);
  1611.       finput2->_cnt = t->len-1;
  1612. #endif
  1613. #endif
  1614. #endif
  1615.       lineno = t->lineno;
  1616.       input_filename = t->filename;
  1617.       yychar = PRE_PARSED_FUNCTION_DECL;
  1618.       yylval.ttype = t->fndecl;
  1619.       if (flag_default_inline)
  1620.     TREE_INLINE (t->fndecl) = 1;
  1621.     }
  1622. }
  1623.  
  1624. /* Since inline methods can refer to text which has not yet been seen,
  1625.    we store the text of the method in a structure which is placed in the
  1626.    DECL_PENDING_INLINE_INFO field of the FUNCTION_DECL.
  1627.    After parsing the body of the class definition, the FUNCTION_DECL's are
  1628.    scanned to see which ones have this field set.  Those are then digested
  1629.    one at a time.
  1630.  
  1631.    This function's FUNCTION_DECL will have a bit set in its common so
  1632.    that we know to watch out for it.  */
  1633.  
  1634. void
  1635. consume_string (this_obstack)
  1636.      register struct obstack *this_obstack;
  1637. {
  1638.   register char c;
  1639.   do
  1640.     {
  1641.       c = getc (finput);
  1642.       if (c == '\\')
  1643.     {
  1644.       obstack_1grow (this_obstack, c);
  1645.       c = getch ();
  1646.       obstack_1grow (this_obstack, c);
  1647.       continue;
  1648.     }
  1649.       if (c == '\n')
  1650.     {
  1651.       if (pedantic)
  1652.         warning ("ANSI C forbids newline in string constant");
  1653.       lineno++;
  1654.     }
  1655.       obstack_1grow (this_obstack, c);
  1656.     }
  1657.   while (c != '\"');
  1658. }
  1659.  
  1660. static int nextchar = -1;
  1661. static int nextyychar = -1;
  1662. static YYSTYPE nextyylval;
  1663. static tree nextlastiddecl;
  1664.  
  1665. /* Get input from stream.  When compiling under Cadillac,
  1666.    the bytes must be coaxed out via their read protocol.
  1667.    Otherwise, they come easily via standard input interface.  */
  1668. int
  1669. getch ()
  1670. {
  1671.   register int ch = getc (finput);
  1672.   return ch;
  1673. }
  1674.  
  1675. /* Return next non-whitespace input character, which may come
  1676.    from `finput', or from `nextchar'.  */
  1677. static int
  1678. yynextch ()
  1679. {
  1680.   int c;
  1681.  
  1682.   if (nextchar >= 0)
  1683.     {
  1684.       c = nextchar;
  1685.       nextchar = -1;
  1686.     }
  1687.   else c = getc (finput);
  1688.   return skip_white_space (c);
  1689. }
  1690.  
  1691. /* Unget character CH from the input stream.
  1692.    If RESCAN is non-zero, then we want to `see' this
  1693.    character as the next input token.  */
  1694. void
  1695. yyungetc (ch, rescan)
  1696.      int ch;
  1697.      int rescan;
  1698. {
  1699.   /* Unget a characater from the input stream.  */
  1700.   if (yychar == YYEMPTY || rescan == 0)
  1701.     ungetc (ch, finput);
  1702.   else
  1703.     {
  1704.       if (nextyychar >= 0)
  1705.     abort ();
  1706.       nextyychar = yychar;
  1707.       nextyylval = yylval;
  1708.       yychar = ch;
  1709.     }
  1710. }
  1711.  
  1712. void
  1713. reinit_parse_for_method (yychar, decl)
  1714.      int yychar;
  1715.      tree decl;
  1716. {
  1717.   register char c = 0;
  1718.   int blev = 1;
  1719.   tree fndecl = decl;
  1720.   int starting_lineno = lineno;
  1721.   char *starting_filename = input_filename;
  1722.   int len;
  1723.  
  1724.   if (yychar != '{')
  1725.     {
  1726.       if (yychar != ':' && yychar != RETURN)
  1727.     {
  1728.       yyerror ("parse error in method specification");
  1729.       yychar = '{';
  1730.     }
  1731.       obstack_1grow (&inline_text_obstack, yychar);
  1732.       while (c >= 0)
  1733.     {
  1734.       int this_lineno = lineno;
  1735.  
  1736.       c = yynextch ();
  1737.  
  1738.       /* Don't lose our cool if there are lots of comments.  */
  1739.       if (lineno - this_lineno)
  1740.         if (lineno - this_lineno == 1)
  1741.           obstack_1grow (&inline_text_obstack, '\n');
  1742.         else
  1743.           {
  1744.         char buf[12];
  1745.         sprintf (buf, "\n# %d \"", lineno);
  1746.         len = strlen (buf);
  1747.         obstack_grow (&inline_text_obstack, buf, len);
  1748.  
  1749.         len = strlen (input_filename);
  1750.         obstack_grow (&inline_text_obstack, input_filename, len);
  1751.         obstack_1grow (&inline_text_obstack, '\"');
  1752.         obstack_1grow (&inline_text_obstack, '\n');
  1753.           }
  1754.  
  1755.       /* strings must be read differently than text.  */
  1756.       if (c == '\"')
  1757.         {
  1758.           obstack_1grow (&inline_text_obstack, c);
  1759.           consume_string (&inline_text_obstack);
  1760.           c = yynextch ();
  1761.         }
  1762.       while (c > ' ')    /* ASCII dependent! */
  1763.         {
  1764.           obstack_1grow (&inline_text_obstack, c);
  1765.           if (c == '{') goto main_loop;
  1766.           if (c == '\"')
  1767.         consume_string (&inline_text_obstack);
  1768.           if (c == ';')
  1769.         {
  1770.           error ("function body for constructor missing");
  1771.           obstack_1grow (&inline_text_obstack, '{');
  1772.           obstack_1grow (&inline_text_obstack, '}');
  1773.           len += 2;
  1774.           goto done;
  1775.         }
  1776.           c = getch ();
  1777.         }
  1778.       if (c == '\n')
  1779.         lineno++;
  1780.       obstack_1grow (&inline_text_obstack, c);
  1781.     }
  1782.       if (c == EOF)
  1783.     {
  1784.       error_with_file_and_line (starting_filename,
  1785.                     starting_lineno,
  1786.                     "parse error in method specification");
  1787.     }      
  1788.     }
  1789.   else obstack_1grow (&inline_text_obstack, '{');
  1790.  
  1791.  main_loop:
  1792.   while (c >= 0)
  1793.     {
  1794.       int this_lineno = lineno;
  1795.  
  1796.       c = skip_white_space (getc (finput));
  1797.  
  1798.       /* Don't lose our cool if there are lots of comments.  */
  1799.       if (lineno - this_lineno)
  1800.     if (lineno - this_lineno == 1)
  1801.       obstack_1grow (&inline_text_obstack, '\n');
  1802.     else
  1803.       {
  1804.         char buf[12];
  1805.         sprintf (buf, "\n# %d \"", lineno);
  1806.         len = strlen (buf);
  1807.         obstack_grow (&inline_text_obstack, buf, len);
  1808.  
  1809.         len = strlen (input_filename);
  1810.         obstack_grow (&inline_text_obstack, input_filename, len);
  1811.         obstack_1grow (&inline_text_obstack, '\"');
  1812.         obstack_1grow (&inline_text_obstack, '\n');
  1813.       }
  1814.  
  1815.       while (c > ' ')
  1816.     {
  1817.       obstack_1grow (&inline_text_obstack, c);
  1818.       if (c == '{') blev++;
  1819.       else if (c == '}')
  1820.         {
  1821.           blev--;
  1822.           if (blev == 0)
  1823.         goto done;
  1824.         }
  1825.       else if (c == '\"')
  1826.         consume_string (&inline_text_obstack);
  1827.       c = getch ();
  1828.     }
  1829.       if (c == '\n')
  1830.     lineno++;
  1831.       obstack_1grow (&inline_text_obstack, c);
  1832.     }
  1833.  done:
  1834.   current_base_init_list = NULL_TREE;
  1835.   current_member_init_list = NULL_TREE;
  1836.  
  1837. #ifdef USG_STDIO
  1838.   len = obstack_object_size (&inline_text_obstack);
  1839.   /* If the buffer given to setvbuf is shorter than eight bytes long,
  1840.      setvbuf will (in violation of its man page) ignore the buffer
  1841.      and call malloc to get a bigger one.  */
  1842.   while (len < 8)
  1843.     {
  1844.       len++;
  1845.       obstack_1grow (&inline_text_obstack, ' ');
  1846.     }
  1847. #endif
  1848.  
  1849.   obstack_1grow (&inline_text_obstack, '\0');
  1850.   len = obstack_object_size (&inline_text_obstack);
  1851.  
  1852.   if (fndecl == void_type_node)
  1853.     {
  1854.       /* Happens when we get two declarations of the same
  1855.      function in the same scope.  */
  1856.       char *buf = obstack_base (&inline_text_obstack);
  1857.       obstack_free (&inline_text_obstack, buf);
  1858.       return;
  1859.     }
  1860.   else
  1861.     {
  1862.       struct pending_inline *t;
  1863.       char *buf = obstack_base (&inline_text_obstack);
  1864.  
  1865.       obstack_finish (&inline_text_obstack);
  1866.  
  1867.       t = (struct pending_inline *) obstack_alloc (&inline_text_obstack,
  1868.                            sizeof (struct pending_inline));
  1869.       t->buf = buf;
  1870.       t->len = len;
  1871.       t->lineno = starting_lineno;
  1872.       t->filename = starting_filename;
  1873.       t->token = YYEMPTY;
  1874.       DECL_PENDING_INLINE_INFO (fndecl) = t;
  1875.     }
  1876. }
  1877.  
  1878. /* Build a default function named NAME for type TYPE.
  1879.    KIND says what to build.  Currently only two kinds of default functions
  1880.    are recognized:
  1881.  
  1882.    When KIND == 0, build default X(X&) constructor.
  1883.    When KIND == 1, build default destructor.  */
  1884.  
  1885. tree
  1886. cons_up_default_function (type, name, kind)
  1887.      tree type, name;
  1888.      int kind;
  1889. {
  1890.   extern tree void_list_node;
  1891.   int len;
  1892.   tree fn, args;
  1893.   tree argtype;
  1894.  
  1895.   switch (kind)
  1896.     {
  1897.     case 0:
  1898.       /* Destructor.  */
  1899.       name = build_parse_node (BIT_NOT_EXPR, name);
  1900.       /* Fall through...  */
  1901.     case 2:
  1902.       /* Default constructor.  */
  1903.       args = void_list_node;
  1904.       break;
  1905.  
  1906.     case 3:
  1907.       type = build_type_variant (type, 1, 0);
  1908.       /* Fall through...  */
  1909.     case 1:
  1910.       argtype = build_reference_type (type);
  1911.       args = tree_cons (NULL_TREE,
  1912.             build_tree_list (hash_tree_chain (argtype, NULL_TREE),
  1913.                      get_identifier ("arg")),
  1914.             void_list_node);
  1915.       break;
  1916.  
  1917.     default:
  1918.       abort ();
  1919.     }
  1920.  
  1921.   fn = start_method (NULL_TREE,
  1922.              build_parse_node (CALL_EXPR, name, args, NULL_TREE),
  1923.              NULL_TREE);
  1924.   if (fn == void_type_node)
  1925.     return fn;
  1926.  
  1927.   obstack_1grow (&inline_text_obstack, '{');
  1928.   obstack_1grow (&inline_text_obstack, '}');
  1929. #ifdef USG_STDIO
  1930.   len = 2;
  1931.   while (len++ < 8)
  1932.     obstack_1grow (&inline_text_obstack, ' ');
  1933. #endif
  1934.  
  1935.   obstack_1grow (&inline_text_obstack, '\0');
  1936.   current_base_init_list = NULL_TREE;
  1937.   current_member_init_list = NULL_TREE;
  1938.  
  1939.   len = obstack_object_size (&inline_text_obstack);
  1940.  
  1941.   {
  1942.     struct pending_inline *t;
  1943.     char *buf = obstack_base (&inline_text_obstack);
  1944.  
  1945.     obstack_finish (&inline_text_obstack);
  1946.  
  1947.     t = (struct pending_inline *) obstack_alloc (&inline_text_obstack,
  1948.                          sizeof (struct pending_inline));
  1949.     t->buf = buf;
  1950.     t->len = len;
  1951.     t->lineno = lineno;
  1952.     t->filename = input_filename;
  1953.     t->token = YYEMPTY;
  1954.     DECL_PENDING_INLINE_INFO (fn) = t;
  1955.     /* We make this declaration private (static in the C sense).  */
  1956.     TREE_PUBLIC (fn) = 0;
  1957.   }
  1958.   finish_method (fn);
  1959.   DECL_COMPILER_GENERATED_P (fn) = 1;
  1960.   return fn;
  1961. }
  1962.  
  1963. /* Heuristic to tell whether the user is missing a semicolon
  1964.    after a struct or enum declaration.  Emit an error message
  1965.    if we know the user has blown it.  */
  1966. void
  1967. check_for_missing_semicolon (type)
  1968.      tree type;
  1969. {
  1970.   if (yychar < 0)
  1971.     yychar = yylex ();
  1972.  
  1973.   if (yychar > 255
  1974.       && yychar != IDENTIFIER
  1975.       && yychar != TYPENAME)
  1976.     {
  1977.       if (ANON_AGGRNAME_P (DECL_NAME (TYPE_NAME (type))))
  1978.     error ("semicolon missing after %s declaration",
  1979.            TREE_CODE (type) == ENUMERAL_TYPE ? "enum" : "struct");
  1980.       else
  1981.     error ("semicolon missing after declaration of `%s'",
  1982.            TYPE_NAME_STRING (type));
  1983.       shadow_tag (build_tree_list (0, type));
  1984.     }
  1985.   /* Could probably also hack cases where class { ... } f (); appears.  */
  1986. }
  1987.  
  1988. void
  1989. note_got_semicolon (type)
  1990.      tree type;
  1991. {
  1992.   if (IS_AGGR_TYPE (type))
  1993.     CLASSTYPE_GOT_SEMICOLON (type) = 1;
  1994. }
  1995.  
  1996. /* If C is not whitespace, return C.
  1997.    Otherwise skip whitespace and return first nonwhite char read.  */
  1998.  
  1999. static int
  2000. skip_white_space (c)
  2001.      register int c;
  2002. {
  2003. #if 0
  2004.   register int inside;
  2005. #endif
  2006.  
  2007.   for (;;)
  2008.     {
  2009.       switch (c)
  2010.     {
  2011.       /* Don't recognize comments in cc1: all comments are removed by cpp,
  2012.          and cpp output can include / and * consecutively as operators.  */
  2013. #if 0
  2014.     case '/':
  2015.       c = getc (finput);
  2016.       if (c != '*' && c != '/')
  2017.         {
  2018.           ungetc (c, finput);
  2019.           return '/';
  2020.         }
  2021.  
  2022.       if (c == '/')
  2023.         {
  2024.           while (c != EOF)
  2025.         {
  2026.           c = getch ();
  2027.           if (c == '\n')
  2028.             {
  2029.               ungetc (c, finput);
  2030.               break;
  2031.             }
  2032.         }
  2033.           if (c == EOF)
  2034.         {
  2035.           error ("unterminated comment");
  2036.           return EOF;
  2037.         }
  2038.           c = getch ();
  2039.           break;
  2040.         }
  2041.  
  2042.       c = getch ();
  2043.  
  2044.       inside = 1;
  2045.       while (inside)
  2046.         {
  2047.           if (c == '*')
  2048.         {
  2049.           while (c == '*')
  2050.             c = getch ();
  2051.  
  2052.           if (c == '/')
  2053.             {
  2054.               inside = 0;
  2055.               c = getch ();
  2056.             }
  2057.         }
  2058.           else if (c == '\n')
  2059.         {
  2060.           lineno++;
  2061.           c = getch ();
  2062.         }
  2063.           else if (c == EOF)
  2064.         {
  2065.           error ("unterminated comment");
  2066.           break;
  2067.         }
  2068.           else
  2069.         c = getch ();
  2070.         }
  2071.  
  2072.       break;
  2073. #endif
  2074.  
  2075.     case '\n':
  2076.       c = check_newline ();
  2077.       break;
  2078.  
  2079.     case ' ':
  2080.     case '\t':
  2081.     case '\f':
  2082.     case '\r':
  2083.     case '\v':
  2084.     case '\b':
  2085.       do
  2086.         c = getc (finput);
  2087.       while (c == ' ' || c == '\t');
  2088.       break;
  2089.  
  2090.     case '\\':
  2091.       c = getch ();
  2092.       if (c == '\n')
  2093.         lineno++;
  2094.       else
  2095.         error ("stray '\\' in program");
  2096.       c = getch ();
  2097.       break;
  2098.  
  2099.     default:
  2100.       return (c);
  2101.     }
  2102.     }
  2103. }
  2104.  
  2105.  
  2106.  
  2107. /* Make the token buffer longer, preserving the data in it.
  2108.    P should point to just beyond the last valid character in the old buffer.
  2109.    The value we return is a pointer to the new buffer
  2110.    at a place corresponding to P.  */
  2111.  
  2112. static char *
  2113. extend_token_buffer (p)
  2114.      char *p;
  2115. {
  2116.   int offset = p - token_buffer;
  2117.  
  2118.   maxtoken = maxtoken * 2 + 10;
  2119.   token_buffer = (char *) xrealloc (token_buffer, maxtoken + 2);
  2120.  
  2121.   return token_buffer + offset;
  2122. }
  2123.  
  2124. #ifndef MERGED
  2125. /* This includes code from write_segment, stolen from unexec.c */
  2126.  
  2127. void dump_data()
  2128. {
  2129.   int new;
  2130.   register caddr_t ptr, end;
  2131.   register int i, nwrite, ret;
  2132.   char buf[80];
  2133.   extern int errno;
  2134.   char zeros[128];
  2135.  
  2136.   extern int been_here_before, just_done_unexec, my_edata;
  2137.   extern char *dump_source_name;
  2138.   extern char *asm_file_name, previous_asm_file_name[];
  2139.   char dump_file_name[256];    /* Fixed-sized buffer -- sigh. */
  2140.   caddr_t end_of_data, end_of_heap;
  2141.   int data_size, token;
  2142.   register int c;
  2143.  
  2144.   bzero (zeros, sizeof zeros);
  2145.  
  2146.   /* Here we have just seen `#pragma dump '.
  2147.      The name to dump to, a string constant, may follow.  */
  2148.  
  2149.   do
  2150.     c = getch ();
  2151.   while (c == ' ' || c == '\t');
  2152.  
  2153.   /* If no argument, default to something like "dumped-cc1plus".  */
  2154.   if (c == '\n')
  2155.     {
  2156.       char *tmp;
  2157.       strcpy (dump_file_name, "dumped-");
  2158.       if (tmp = strrchr (dump_source_name, '/'))
  2159.     dump_source_name = tmp + 1;
  2160.       strcat (dump_file_name, dump_source_name);
  2161.     }
  2162.   else
  2163.     {
  2164.       ungetc (c, finput);
  2165.       token = yylex ();
  2166.       if (token != STRING
  2167.       || TREE_CODE (yylval.ttype) != STRING_CST)
  2168.     {
  2169.       error ("invalid #pragma dump");
  2170.       return;
  2171.     }
  2172.  
  2173.       strcpy (dump_file_name, TREE_STRING_POINTER (yylval.ttype));
  2174.     }
  2175.  
  2176.   been_here_before = 1;        /* Raise the flag! */
  2177.   strcpy(previous_asm_file_name, asm_file_name);
  2178.   printf("\nDumping %s to %s...\n", dump_source_name, dump_file_name);
  2179.  
  2180.   end_of_heap = (caddr_t)sbrk(0);
  2181.   end_of_data = (caddr_t)((int)(&my_edata)&~(getpagesize()-1));
  2182.   data_size = (int)(end_of_heap-end_of_data);
  2183.   printf("Data size = %d\n", data_size);
  2184.           
  2185.   new = creat (dump_file_name, 0666);
  2186.  
  2187.   ptr = end_of_data;
  2188.   end = end_of_heap;
  2189.  
  2190.   for (i = 0; ptr < end;)
  2191.     {
  2192.       /* distance to next multiple of 128.  */
  2193.       nwrite = (((int) ptr + 128) & -128) - (int) ptr;
  2194.       /* But not beyond specified end.  */
  2195.       if (nwrite > end - ptr) nwrite = end - ptr;
  2196.       ret = write (new, ptr, nwrite);
  2197.       /* If write gets a page fault, it means we reached
  2198.      a gap between the old text segment and the old data segment.
  2199.      This gap has probably been remapped into part of the text segment.
  2200.      So write zeros for it.  */
  2201.       if (ret == -1 && errno == EFAULT)
  2202.     write (new, zeros, nwrite);
  2203.       else if (nwrite != ret)
  2204.     {
  2205.       sprintf (buf,
  2206.            "unexec write failure: addr 0x%x, fileno %d, size 0x%x, wrote 0x%x, errno %d",
  2207.            ptr, new, nwrite, ret, errno);
  2208.       perror (buf);
  2209.       return;
  2210.     }
  2211.       i += nwrite;
  2212.       ptr += nwrite;
  2213.     }
  2214.  
  2215.   close (new);
  2216.  
  2217.   just_done_unexec = 1;        /* Tell toplev not to output ending. */
  2218. }
  2219. #endif
  2220.  
  2221. static int
  2222. get_last_nonwhite_on_line ()
  2223. {
  2224.   register int c;
  2225.  
  2226.   /* Is this the last nonwhite stuff on the line?  */
  2227.   if (nextchar >= 0)
  2228.     c = nextchar, nextchar = -1;
  2229.   else
  2230.     c = getc (finput);
  2231.  
  2232.   while (c == ' ' || c == '\t')
  2233.     c = getc (finput);
  2234.   return c;
  2235. }
  2236.  
  2237. /* At the beginning of a line, increment the line number
  2238.    and process any #-directive on this line.
  2239.    If the line is a #-directive, read the entire line and return a newline.
  2240.    Otherwise, return the line's first non-whitespace character.  */
  2241.  
  2242. int
  2243. check_newline ()
  2244. {
  2245.   register int c;
  2246.   register int token;
  2247.  
  2248.   lineno++;
  2249.  
  2250.   /* Read first nonwhite char on the line.  */
  2251.  
  2252.   do
  2253.     c = getc (finput);
  2254.   while (c == ' ' || c == '\t');
  2255.  
  2256.   if (c != '#')
  2257.     {
  2258.       /* If not #, return it so caller will use it.  */
  2259.       return c;
  2260.     }
  2261.  
  2262.   /* Read first nonwhite char after the `#'.  */
  2263.  
  2264.   do
  2265.     c = getch ();
  2266.   while (c == ' ' || c == '\t');
  2267.  
  2268.   /* If a letter follows, then if the word here is `line', skip
  2269.      it and ignore it; otherwise, ignore the line, with an error
  2270.      if the word isn't `pragma'.  */
  2271.  
  2272.   if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
  2273.     {
  2274.       if (c == 'p')
  2275.     {
  2276.       if (getch () == 'r'
  2277.           && getch () == 'a'
  2278.           && getch () == 'g'
  2279.           && getch () == 'm'
  2280.           && getch () == 'a')
  2281. /* Change by Bryan Boreham, Kewill, Sun Jul 23 15:53:24 1989.
  2282.    This whole section added to support dumping of
  2283.    compilations in the middle. */
  2284.         {
  2285.           /* Read first nonwhite char after the `#pragma'.  */
  2286.  
  2287.           do
  2288.         c = getch ();
  2289.           while (c == ' ' || c == '\t');
  2290.  
  2291. #ifndef MERGED
  2292.           /* See if it is "dump" */
  2293.  
  2294.           if (c == 'd'
  2295.           && getch () == 'u'
  2296.           && getch () == 'm'
  2297.           && getch () == 'p'
  2298.           && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
  2299.         {
  2300. #ifdef VMS
  2301.             ;        /* Are you crazy? */
  2302. #else
  2303.           ungetc (c, finput);
  2304.           dump_data();
  2305.           longjmp (toplevel, 1);
  2306. #endif
  2307.         }
  2308.           else
  2309. #endif
  2310.         if (c == 'v'
  2311.                && getch () == 't'
  2312.                && getch () == 'a'
  2313.                && getch () == 'b'
  2314.                && getch () == 'l'
  2315.                && getch () == 'e'
  2316.                && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
  2317.         {
  2318.           extern tree pending_vtables;
  2319.  
  2320.           /* More follows: it must be a string constant (class name).  */
  2321.           token = yylex ();
  2322.           if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
  2323.             {
  2324.               error ("invalid #pragma vtable");
  2325.               goto skipline;
  2326.             }
  2327.           if (write_virtuals != 2)
  2328.             {
  2329.               warning ("use `+e2' option to enable #pragma vtable");
  2330.               goto skipline;
  2331.             }
  2332.           pending_vtables = perm_tree_cons (NULL_TREE, get_identifier (TREE_STRING_POINTER (yylval.ttype)), pending_vtables);
  2333.           if (nextchar < 0)
  2334.             nextchar = getch ();
  2335.           c = nextchar;
  2336.           if (c != '\n')
  2337.             warning ("trailing characters ignored");
  2338.         }
  2339.           else if (c == 'u'
  2340.                && getch () == 'n'
  2341.                && getch () == 'i'
  2342.                && getch () == 't'
  2343.                && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
  2344.         {
  2345.           /* More follows: it must be a string constant (unit name).  */
  2346.           token = yylex ();
  2347.           if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
  2348.             {
  2349.               error ("invalid #pragma unit");
  2350.               goto skipline;
  2351.             }
  2352.           current_unit_name = get_identifier (TREE_STRING_POINTER (yylval.ttype));
  2353.           current_unit_language = current_lang_name;
  2354.           if (nextchar < 0)
  2355.             nextchar = getch ();
  2356.           c = nextchar;
  2357.           if (c != '\n')
  2358.             warning ("trailing characters ignored");
  2359.         }
  2360.           else if (c == 'i')
  2361.         {
  2362.           tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename));
  2363.           c = getch ();
  2364.  
  2365.           if (c == 'n'
  2366.               && getch () == 't'
  2367.               && getch () == 'e'
  2368.               && getch () == 'r'
  2369.               && getch () == 'f'
  2370.               && getch () == 'a'
  2371.               && getch () == 'c'
  2372.               && getch () == 'e'
  2373.               && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
  2374.             {
  2375.               /* read to newline.  */
  2376.               while (c != '\n')
  2377.             c = getch ();
  2378.  
  2379.               write_virtuals = 3;
  2380.  
  2381.               if (impl_file_chain == 0)
  2382.             {
  2383.               char *filename;
  2384.               tree fi;
  2385.  
  2386.               /* If this is zero at this point, then we are
  2387.                  auto-implementing.  */
  2388.               if (main_input_filename == 0)
  2389.                 main_input_filename = input_filename;
  2390.  
  2391.               filename = strrchr (main_input_filename, '/');
  2392.               if (filename++ == 0)
  2393.                 filename = main_input_filename;
  2394.               fi = get_time_identifier (filename);
  2395.               fi = IDENTIFIER_CLASS_VALUE (fi);
  2396.               TREE_INT_CST_LOW (fi) = 0;
  2397.               TREE_INT_CST_LOW (fi) = 0;
  2398.               /* Get default.  */
  2399.               impl_file_chain = (struct impl_files *)permalloc (sizeof (struct impl_files));
  2400.               impl_file_chain->filename = filename;
  2401.               impl_file_chain->next = 0;
  2402.             }
  2403.  
  2404.               interface_only = interface_strcmp (input_filename);
  2405.               interface_unknown = 0;
  2406.               TREE_INT_CST_LOW (fileinfo) = interface_only;
  2407.               TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
  2408.             }
  2409.           else if (c == 'm'
  2410.                && getch () == 'p'
  2411.                && getch () == 'l'
  2412.                && getch () == 'e'
  2413.                && getch () == 'm'
  2414.                && getch () == 'e'
  2415.                && getch () == 'n'
  2416.                && getch () == 't'
  2417.                && getch () == 'a'
  2418.                && getch () == 't'
  2419.                && getch () == 'i'
  2420.                && getch () == 'o'
  2421.                && getch () == 'n'
  2422.                && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
  2423.             {
  2424.               char *main_filename = main_input_filename ? main_input_filename : input_filename;
  2425.               char *tmp;
  2426.  
  2427.               while (c == ' ' || c == '\t')
  2428.             c = getch ();
  2429.               if (c != '\n')
  2430.             {
  2431.               ungetc (c, finput);
  2432.               token = yylex ();
  2433.               if (token != STRING
  2434.                   || TREE_CODE (yylval.ttype) != STRING_CST)
  2435.                 {
  2436.                   error ("invalid `#pragma implementation'");
  2437.                   goto skipline;
  2438.                 }
  2439.               main_filename = TREE_STRING_POINTER (yylval.ttype);
  2440.             }
  2441.               tmp = strrchr (main_filename, '/');
  2442.               if (tmp++)
  2443.             main_filename = tmp;
  2444.  
  2445.               /* read to newline.  */
  2446.               while (c != '\n')
  2447.             c = getch ();
  2448.  
  2449.               if (write_virtuals == 3)
  2450.             {
  2451.               struct impl_files *ifiles = impl_file_chain;
  2452.               while (ifiles)
  2453.                 {
  2454.                   if (! strcmp (ifiles->filename, main_filename))
  2455.                 break;
  2456.                   ifiles = ifiles->next;
  2457.                 }
  2458.               if (ifiles == 0)
  2459.                 {
  2460.                   ifiles = (struct impl_files*) permalloc (sizeof (struct impl_files));
  2461.                   ifiles->filename = main_filename;
  2462.                   ifiles->next = impl_file_chain;
  2463.                   impl_file_chain = ifiles;
  2464.                 }
  2465.             }
  2466.               else if (main_input_filename == input_filename
  2467.                    || ! strcmp (input_filename, main_filename))
  2468.             {
  2469.               write_virtuals = 3;
  2470.               if (impl_file_chain == 0)
  2471.                 {
  2472.                   impl_file_chain = (struct impl_files*) permalloc (sizeof (struct impl_files));
  2473.                   impl_file_chain->filename = main_filename;
  2474.                   impl_file_chain->next = 0;
  2475.                 }
  2476.             }
  2477.               else
  2478.             error ("`#pragma implementation' can only appear at top-level");
  2479.               interface_only = 0;
  2480.               interface_unknown = 0;
  2481.               TREE_INT_CST_LOW (fileinfo) = interface_only;
  2482.               TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
  2483.             }
  2484.         }
  2485.         }
  2486.       goto skipline;
  2487.     }
  2488.  
  2489.       else if (c == 'l')
  2490.     {
  2491.       if (getch () == 'i'
  2492.           && getch () == 'n'
  2493.           && getch () == 'e'
  2494.           && ((c = getch ()) == ' ' || c == '\t'))
  2495.         goto linenum;
  2496.     }
  2497.       else if (c == 'i')
  2498.     {
  2499.       if (getch () == 'd'
  2500.           && getch () == 'e'
  2501.           && getch () == 'n'
  2502.           && getch () == 't'
  2503.           && ((c = getch ()) == ' ' || c == '\t'))
  2504.         {
  2505.           /* Conditionally used.  */
  2506.               extern FILE *asm_out_file;
  2507.  
  2508.           if (pedantic)
  2509.         error ("ANSI C does not allow #ident");
  2510.  
  2511.           /* Here we have just seen `#ident '.
  2512.          A string constant should follow.  */
  2513.  
  2514.           while (c == ' ' || c == '\t')
  2515.         c = getch ();
  2516.  
  2517.           /* If no argument, ignore the line.  */
  2518.           if (c == '\n')
  2519.         return c;
  2520.  
  2521.           ungetc (c, finput);
  2522.           token = yylex ();
  2523.           if (token != STRING
  2524.           || TREE_CODE (yylval.ttype) != STRING_CST)
  2525.         {
  2526.           error ("invalid #ident");
  2527.           goto skipline;
  2528.         }
  2529.  
  2530. #ifdef ASM_OUTPUT_IDENT
  2531.           ASM_OUTPUT_IDENT (asm_out_file, TREE_STRING_POINTER (yylval.ttype));
  2532. #endif
  2533.  
  2534.           /* Skip the rest of this line.  */
  2535.           goto skipline;
  2536.         }
  2537.     }
  2538.       else if (c == 'n')
  2539.     {
  2540.       if (getch () == 'e'
  2541.           && getch () == 'w'
  2542.           && getch () == 'w'
  2543.           && getch () == 'o'
  2544.           && getch () == 'r'
  2545.           && getch () == 'l'
  2546.           && getch () == 'd'
  2547.           && ((c = getch ()) == ' ' || c == '\t'))
  2548.         {
  2549.           /* Used to test incremental compilation.  */
  2550.           sorry ("#pragma newworld");
  2551.           goto skipline;
  2552.         }
  2553.     }
  2554.       error ("undefined or invalid # directive");
  2555.       goto skipline;
  2556.     }
  2557.  
  2558. linenum:
  2559.   /* Here we have either `#line' or `# <nonletter>'.
  2560.      In either case, it should be a line number; a digit should follow.  */
  2561.  
  2562.   while (c == ' ' || c == '\t')
  2563.     c = getch ();
  2564.  
  2565.   /* If the # is the only nonwhite char on the line,
  2566.      just ignore it.  Check the new newline.  */
  2567.   if (c == '\n')
  2568.     return c;
  2569.  
  2570.   /* Something follows the #; read a token.  */
  2571.  
  2572.   ungetc (c, finput);
  2573.   token = yylex ();
  2574.  
  2575.   if (token == CONSTANT
  2576.       && TREE_CODE (yylval.ttype) == INTEGER_CST)
  2577.     {
  2578.       int old_lineno = lineno;
  2579.       /* subtract one, because it is the following line that
  2580.      gets the specified number */
  2581.  
  2582.       int l = TREE_INT_CST_LOW (yylval.ttype) - 1;
  2583.       c = get_last_nonwhite_on_line ();
  2584.       if (c == '\n')
  2585.     {
  2586.       /* No more: store the line number and check following line.  */
  2587.       lineno = l;
  2588.       return c;
  2589.     }
  2590.       ungetc (c, finput);
  2591.  
  2592.       /* More follows: it must be a string constant (filename).  */
  2593.  
  2594.       token = yylex ();
  2595.       if (token != STRING || TREE_CODE (yylval.ttype) != STRING_CST)
  2596.     {
  2597.       error ("invalid #line");
  2598.       goto skipline;
  2599.     }
  2600.  
  2601.       /* Changing files again.  This means currently collected time
  2602.      is charged against header time, and body time starts back
  2603.      at 0.  */
  2604.       if (flag_detailed_statistics)
  2605.     {
  2606.       int this_time = my_gettime ();
  2607.       tree time_identifier = get_time_identifier (TREE_STRING_POINTER (yylval.ttype));
  2608.       header_time += this_time - body_time;
  2609.       TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time))
  2610.         += this_time - body_time;
  2611.       this_filename_time = time_identifier;
  2612.       body_time = this_time;
  2613.     }
  2614.  
  2615.       if (flag_cadillac)
  2616.     cadillac_note_source ();
  2617.  
  2618.       input_filename
  2619.     = (char *) permalloc (TREE_STRING_LENGTH (yylval.ttype) + 1);
  2620.       strcpy (input_filename, TREE_STRING_POINTER (yylval.ttype));
  2621.       lineno = l;
  2622. #ifdef FIELD_XREF
  2623.       FIELD_xref_file(input_filename);
  2624. #endif
  2625.  
  2626.       if (main_input_filename == 0)
  2627.     {
  2628.       extern int been_here_before;
  2629.       struct impl_files *ifiles = impl_file_chain;
  2630.  
  2631.       if (ifiles)
  2632.         {
  2633.           while (ifiles->next)
  2634.         ifiles = ifiles->next;
  2635.           ifiles->filename = (char *)strrchr (input_filename, '/');
  2636.           if (ifiles->filename++ == 0)
  2637.         ifiles->filename = input_filename;
  2638.         }
  2639.  
  2640.       main_input_filename = input_filename;
  2641.       if (write_virtuals == 3)
  2642.         walk_vtables (set_typedecl_interface_info, set_vardecl_interface_info);
  2643.     }
  2644.  
  2645.       extract_interface_info ();
  2646.  
  2647.       c = get_last_nonwhite_on_line ();
  2648.       if (c == '\n')
  2649.     {
  2650.       if (flag_cadillac)
  2651.         cadillac_switch_source (-1);
  2652.       return c;
  2653.     }
  2654.       ungetc (c, finput);
  2655.  
  2656.       token = yylex ();
  2657.  
  2658.       /* `1' after file name means entering new file.
  2659.      `2' after file name means just left a file.  */
  2660.  
  2661.       if (token == CONSTANT
  2662.       && TREE_CODE (yylval.ttype) == INTEGER_CST)
  2663.     {
  2664.       if (TREE_INT_CST_LOW (yylval.ttype) == 1)
  2665.         {
  2666.           struct file_stack *p
  2667.         = (struct file_stack *) xmalloc (sizeof (struct file_stack));
  2668.           input_file_stack->line = old_lineno;
  2669.           p->next = input_file_stack;
  2670.           p->name = input_filename;
  2671.           input_file_stack = p;
  2672.           input_file_stack_tick++;
  2673.  
  2674.           if (flag_cadillac)
  2675.         cadillac_push_source ();
  2676.         }
  2677.       else if (input_file_stack->next)
  2678.         {
  2679.           struct file_stack *p = input_file_stack;
  2680.  
  2681.           if (flag_cadillac)
  2682.         cadillac_pop_source ();
  2683.  
  2684.           input_file_stack = p->next;
  2685.           free (p);
  2686.           input_file_stack_tick++;
  2687.         }
  2688.       else
  2689.         error ("#-lines for entering and leaving files don't match");
  2690.     }
  2691.       else if (flag_cadillac)
  2692.     cadillac_switch_source (-1);
  2693.  
  2694.       /* If NEXTCHAR is not end of line, we don't care what it is.  */
  2695.       if (nextchar == '\n')
  2696.     return '\n';
  2697.     }
  2698.   else
  2699.     error ("invalid #-line");
  2700.  
  2701.   /* skip the rest of this line.  */
  2702.  skipline:
  2703.   if (c == '\n')
  2704.     return c;
  2705.   while ((c = getch ()) != EOF && c != '\n');
  2706.   return c;
  2707. }
  2708.  
  2709. #if 0
  2710. #define isalnum(char) (char >= 'a' ? char <= 'z' : char >= '0' ? char <= '9' || (char >= 'A' && char <= 'Z') : 0)
  2711. #define isdigit(char) (char >= '0' && char <= '9')
  2712. #else
  2713. #include <ctype.h>
  2714. #endif
  2715.  
  2716. #define ENDFILE -1  /* token that represents end-of-file */
  2717.  
  2718. static int
  2719. readescape ()
  2720. {
  2721.   register int c = getc (finput);
  2722.   register int count, code;
  2723.   int firstdig;
  2724.  
  2725.   switch (c)
  2726.     {
  2727.     case 'x':
  2728.       code = 0;
  2729.       count = 0;
  2730.       while (1)
  2731.     {
  2732.       c = getch ();
  2733.       if (! isxdigit (c))
  2734.         {
  2735.           ungetc (c, finput);
  2736.           break;
  2737.         }
  2738.       code *= 16;
  2739.       if (c >= 'a' && c <= 'f')
  2740.         code += c - 'a' + 10;
  2741.       if (c >= 'A' && c <= 'F')
  2742.         code += c - 'A' + 10;
  2743.       if (c >= '0' && c <= '9')
  2744.         code += c - '0';
  2745.       if (count == 0)
  2746.         firstdig = code;
  2747.       count++;
  2748.     }
  2749.       if (count == 0)
  2750.     error ("\\x used with no following hex digits");
  2751.       else if ((count - 1) * 4 >= TYPE_PRECISION (integer_type_node)
  2752.            || ((1 << (TYPE_PRECISION (integer_type_node) - (count - 1) * 4))
  2753.            <= firstdig))
  2754.     warning ("hex escape out of range");
  2755.       return code;
  2756.  
  2757.     case '0':  case '1':  case '2':  case '3':  case '4':
  2758.     case '5':  case '6':  case '7':
  2759.       code = 0;
  2760.       count = 0;
  2761.       while ((c <= '7') && (c >= '0') && (count++ < 3))
  2762.     {
  2763.       code = (code * 8) + (c - '0');
  2764.       c = getch ();
  2765.     }
  2766.       ungetc (c, finput);
  2767.       return code;
  2768.  
  2769.     case '\\': case '\'': case '"':
  2770.       return c;
  2771.  
  2772.     case '\n':
  2773.       lineno++;
  2774.       return -1;
  2775.  
  2776.     case 'n':
  2777.       return TARGET_NEWLINE;
  2778.  
  2779.     case 't':
  2780.       return TARGET_TAB;
  2781.  
  2782.     case 'r':
  2783.       return TARGET_CR;
  2784.  
  2785.     case 'f':
  2786.       return TARGET_FF;
  2787.  
  2788.     case 'b':
  2789.       return TARGET_BS;
  2790.  
  2791.     case 'a':
  2792.       return TARGET_BELL;
  2793.  
  2794.     case 'v':
  2795.       return TARGET_VT;
  2796.  
  2797.     case 'E':
  2798.       return 033;
  2799.  
  2800.     case '?':
  2801.       /* `\(', etc, are used at beginning of line to avoid confusing Emacs.  */
  2802.     case '(':
  2803.     case '{':
  2804.     case '[':
  2805.       return c;
  2806.     }
  2807.   if (c >= 040 && c <= 0177)
  2808.     warning ("unknown escape sequence `\\%c'", c);
  2809.   else
  2810.     warning ("unknown escape sequence: `\\' followed by char code 0x%x", c);
  2811.   return c;
  2812. }
  2813.  
  2814. /* Value is 1 if we should try to make the next identifier look like a
  2815.    typename (when it may be a local variable or a class variable).
  2816.    Value is 0 if we treat this name in a default fashion.
  2817.    Value is -1 if we must not see a type name.  */
  2818. int looking_for_typename = 0;
  2819.  
  2820. void
  2821. dont_see_typename ()
  2822. {
  2823.   looking_for_typename = -1;
  2824. #ifdef OBJCPLUS
  2825.   if (yychar == TYPENAME || yychar == OBJECTNAME || yychar == CLASSNAME)
  2826. #else /* OBJPLUS */
  2827.   if (yychar == TYPENAME)
  2828. #endif /* OBJCPLUS */
  2829.     {
  2830.       yychar = IDENTIFIER;
  2831.       lastiddecl = 0;
  2832.     }
  2833. }
  2834.  
  2835. void
  2836. see_typename ()
  2837. {
  2838.   looking_for_typename = 0;
  2839.   if (yychar == IDENTIFIER)
  2840.     {
  2841.       lastiddecl = lookup_name (yylval.ttype);
  2842.       if (lastiddecl == 0 && flag_labels_ok)
  2843.     lastiddecl = IDENTIFIER_LABEL_VALUE (yylval.ttype);
  2844.       else if (lastiddecl != 0
  2845.            && TREE_CODE (lastiddecl) == TYPE_DECL)
  2846.     yychar = TYPENAME;
  2847.     }
  2848. }
  2849.  
  2850. tree do_identifier (token)
  2851.      register tree token;
  2852. {
  2853.   register tree id = lastiddecl;
  2854.  
  2855.   if (yychar == YYEMPTY)
  2856.     yychar = yylex ();
  2857.   /* Scope class declarations before global
  2858.      declarations.  */
  2859.   if (id == IDENTIFIER_GLOBAL_VALUE (token)
  2860.       && current_class_type != 0
  2861.       && TYPE_SIZE (current_class_type) == 0)
  2862.     {
  2863.       /* Could be from one of the base classes.  */
  2864.       tree field = lookup_field (current_class_type, token, 1);
  2865.       if (field == 0)
  2866.     ;
  2867.       else if (field == error_mark_node)
  2868.     /* We have already generated the error message.
  2869.        But we still want to return this value.  */
  2870.     id = lookup_field (current_class_type, token, 0);
  2871.       else if (TREE_CODE (field) == VAR_DECL
  2872.            || TREE_CODE (field) == CONST_DECL)
  2873.     id = field;
  2874.       else if (TREE_CODE (field) != FIELD_DECL)
  2875.     abort ();
  2876.       else
  2877.     {
  2878.       error_with_decl (field, "invalid use of member `%s' from base class `%s'",
  2879.                TYPE_NAME_STRING (DECL_FIELD_CONTEXT (field)));
  2880.       id = error_mark_node;
  2881.       return id;
  2882.     }
  2883.     }
  2884.  
  2885.   if (!id || id == error_mark_node)
  2886.     {
  2887.       if (yychar == '(' || yychar == LEFT_RIGHT)
  2888.     {
  2889. #ifdef OBJCPLUS
  2890.       if (!objc_receiver_context ||
  2891.           (objc_receiver_context &&
  2892.            strcmp (IDENTIFIER_POINTER (token), "super")))
  2893.         {
  2894.           if (objc_method_context && is_ivar (objc_ivar_chain, token))
  2895.         id = build_ivar_reference (token);
  2896.           else
  2897.         {
  2898.           id = implicitly_declare (token);
  2899.           assemble_external (id);
  2900.           TREE_USED (id) = 1;
  2901.         }
  2902.         }
  2903.       else /* we have a message to super */
  2904.         {
  2905.           id = get_super_receiver ();
  2906.         }
  2907. #else /* OBJCPLUS */
  2908.       id = implicitly_declare (token);
  2909.       assemble_external (id);
  2910.       TREE_USED (id) = 1;
  2911. #endif /* OBJCPLUS */
  2912.     }
  2913.       else if (current_function_decl == 0)
  2914.     {
  2915.       error ("`%s' undeclared, outside of functions",
  2916.          IDENTIFIER_POINTER (token));
  2917.       id = error_mark_node;
  2918.     }
  2919.       else
  2920.     {
  2921. #ifdef OBJCPLUS
  2922.       if (!objc_receiver_context ||
  2923.           (objc_receiver_context &&
  2924.            strcmp (IDENTIFIER_POINTER (token), "super")))
  2925.         {
  2926.           if (objc_method_context && is_ivar (objc_ivar_chain, token))
  2927.         id = build_ivar_reference (token);
  2928.           else /* undeclared */
  2929.         {
  2930.           if (IDENTIFIER_GLOBAL_VALUE (token) != error_mark_node
  2931.               || IDENTIFIER_ERROR_LOCUS (token) != current_function_decl)
  2932.             {
  2933.               extern int undeclared_variable_notice;
  2934.     
  2935.               error ("`%s' undeclared (first use this function)",
  2936.                   IDENTIFIER_POINTER (token));
  2937.     
  2938.               if (! undeclared_variable_notice)
  2939.             {
  2940.               error ("(Each undeclared identifier is reported only once");
  2941.               error ("for each function it appears in.)");
  2942.               undeclared_variable_notice = 1;
  2943.             }
  2944.             }
  2945.           id = error_mark_node;
  2946.           /* Prevent repeated error messages.  */
  2947.           IDENTIFIER_GLOBAL_VALUE (token) = error_mark_node;
  2948.           SET_IDENTIFIER_ERROR_LOCUS (token, current_function_decl);
  2949.         }
  2950.         }
  2951.       else /* we have a message to super */
  2952.         {
  2953.           id = get_super_receiver ();
  2954.         }
  2955. #else /* OBJCPLUS */
  2956.       if (IDENTIFIER_GLOBAL_VALUE (token) != error_mark_node
  2957.           || IDENTIFIER_ERROR_LOCUS (token) != current_function_decl)
  2958.         {
  2959.           extern int undeclared_variable_notice;
  2960.  
  2961.           error ("`%s' undeclared (first use this function)",
  2962.              IDENTIFIER_POINTER (token));
  2963.  
  2964.           if (! undeclared_variable_notice)
  2965.         {
  2966.           error ("(Each undeclared identifier is reported only once");
  2967.           error ("for each function it appears in.)");
  2968.           undeclared_variable_notice = 1;
  2969.         }
  2970.         }
  2971.       id = error_mark_node;
  2972.       /* Prevent repeated error messages.  */
  2973.       IDENTIFIER_GLOBAL_VALUE (token) = error_mark_node;
  2974.       SET_IDENTIFIER_ERROR_LOCUS (token, current_function_decl);
  2975. #endif /* OBJCPLUS */
  2976.     }
  2977.     }
  2978. #ifdef OBJCPLUS
  2979.   else
  2980.     {
  2981.       /* we have a definition - still check if iVariable */
  2982.     
  2983.       if (!objc_receiver_context ||
  2984.       (objc_receiver_context &&
  2985.         strcmp (IDENTIFIER_POINTER (token), "super")))
  2986.     {
  2987.       if (objc_method_context && is_ivar (objc_ivar_chain, token))
  2988.         {
  2989.           if (IDENTIFIER_LOCAL_VALUE (token))
  2990.         warning ("local declaration of `%s' " 
  2991.               "hides instance variable",
  2992.               IDENTIFIER_POINTER (token));
  2993.           else
  2994.         id = build_ivar_reference (token);
  2995.         }
  2996.     }
  2997.       else /* we have a message to super */
  2998.     id = get_super_receiver ();
  2999.     }
  3000. #endif /* OBJCPLUS */
  3001.  
  3002.   /* TREE_USED is set in `hack_identifier'.  */
  3003.   if (TREE_CODE (id) == CONST_DECL)
  3004.     {
  3005.       if (IDENTIFIER_CLASS_VALUE (token) == id)
  3006.     {
  3007.       /* Check visibility.  */
  3008.       enum visibility_type visibility
  3009.         = compute_visibility (CLASSTYPE_AS_LIST (current_class_type), id);
  3010.       if (visibility == visibility_private)
  3011.         error_with_decl (id, "enum `%s' is private");
  3012.       /* protected is OK, since it's an enum of `this'.  */
  3013.     }
  3014.       id = DECL_INITIAL (id);
  3015.     }
  3016.   else id = hack_identifier (id, token, yychar);
  3017.   return id;
  3018. }
  3019.  
  3020. int
  3021. yylex ()
  3022. {
  3023.   tree tmp;
  3024.   register int c;
  3025.   register int value;
  3026.   int wide_flag = 0;
  3027. #ifdef OBJCPLUS
  3028.   int objc_flag = 0;
  3029. #endif /*  OBJCPLUS */
  3030.   int dollar_seen = 0;
  3031.  
  3032.  relex:
  3033.   if (nextyychar >= 0)
  3034.     {
  3035.       value = nextyychar;
  3036.       yylval = nextyylval;
  3037.       lastiddecl = nextlastiddecl;
  3038.       nextyychar = -1;
  3039.       if (value == IDENTIFIER)
  3040.     {
  3041.       tmp = yylval.ttype;
  3042.       goto resume_identifier_processing;
  3043.     }
  3044.       goto done;
  3045.     }
  3046.   if (nextchar >= 0)
  3047.     c = nextchar, nextchar = -1;
  3048.   else
  3049.     c = getc (finput);
  3050.  
  3051.   /* Effectively do c = skip_white_space (c)
  3052.      but do it faster in the usual cases.  */
  3053.   while (1)
  3054.     switch (c)
  3055.       {
  3056.       case ' ':
  3057.       case '\t':
  3058.       case '\f':
  3059.       case '\r':
  3060.       case '\v':
  3061.       case '\b':
  3062.     c = getc (finput);
  3063.     break;
  3064.  
  3065.       case '\n':
  3066.       case '/':
  3067.       case '\\':
  3068.     c = skip_white_space (c);
  3069.       default:
  3070.     goto found_nonwhite;
  3071.       }
  3072.  found_nonwhite:
  3073.  
  3074.   token_buffer[0] = c;
  3075.   token_buffer[1] = 0;
  3076.  
  3077. /*  yylloc.first_line = lineno; */
  3078.  
  3079.   switch (c)
  3080.     {
  3081.     case EOF:
  3082.       token_buffer[0] = '\0';
  3083.       if (pending_inlines)
  3084.     {
  3085.       struct pending_inline *t;
  3086.  
  3087.       t = pending_inlines;
  3088. #ifdef DO_METHODS_THE_OLD_WAY
  3089.       yylval.itype = t->token_value;
  3090.       value = t->token;
  3091. #else
  3092.       if (t->fndecl == 0)
  3093.         {
  3094.           yylval.itype = t->token_value;
  3095.           value = t->token;
  3096.         }
  3097.       else
  3098.         {
  3099.           yylval.ttype = t->fndecl;
  3100.           value = PRE_PARSED_FUNCTION_DECL;
  3101.         }
  3102. #endif
  3103.  
  3104.       lineno = t->lineno;
  3105. /*        yylloc.first_line = lineno; */
  3106.       input_filename = t->filename;
  3107.  
  3108.       if (t->next)
  3109.         {
  3110.           /* The buffer we used will be freed at the
  3111.          end of this function.  */
  3112.           pending_inlines = pending_inlines->next;
  3113. #ifdef MASSCOMP
  3114.           setbuf (finput2, t->buf);
  3115.           finput2->_cnt = t->len-1;
  3116. #else
  3117. #if defined(i386) && !defined(sequent) && !defined(sun386)
  3118.           finput2->_ptr = finput2->_base = t->buf;
  3119.           _bufend(finput2) = t->buf + t->len;
  3120.           finput2->_flag = _IOFBF | _IOREAD;
  3121.           finput2->_cnt = t->len - 1;
  3122. #else
  3123. #ifndef hp9000s300
  3124. #ifdef USG_STDIO
  3125.                 setvbuf(finput2,t->buf,_IOFBF,t->len);
  3126.                  finput2->_cnt = t->len-1;
  3127. #else
  3128. #ifdef VMS
  3129.                 setvbuf(finput2,t->buf,_IOFBF,t->len);
  3130.                  (*finput2)->_cnt = t->len-1;
  3131. #else
  3132.             setbuffer (finput2, t->buf, t->len);
  3133.             finput2->_cnt = finput2->_bufsiz - 1;
  3134. #endif                /* VMS */
  3135. #endif                /* USG_STDIO */
  3136. #else
  3137.                 setvbuf(finput2,t->buf,_IOFBF,t->len);
  3138.                  finput2->_cnt = t->len-1;
  3139. #endif
  3140. #endif
  3141. #endif
  3142.         }
  3143.       else
  3144.         {
  3145.           pending_inlines = NULL;
  3146.           finput = finput1;
  3147.           obstack_free (&inline_text_obstack, inline_text_firstobj);
  3148.         }
  3149.       /* The space used by T will be freed after all inline
  3150.          functions have been processed.  */
  3151.       if (value <= 0)
  3152.         goto relex;
  3153.       else
  3154.         goto done;
  3155.     }
  3156.       end_of_file = 1;
  3157.       value = ENDFILE;
  3158.       break;
  3159.  
  3160.     case '$':
  3161.       if (dollars_in_ident)
  3162.     {
  3163.       dollar_seen = 1;
  3164.       goto letter;
  3165.     }
  3166.       value = '$';
  3167.       goto done;
  3168.  
  3169.     case 'L':
  3170.       /* Capital L may start a wide-string or wide-character constant.  */
  3171.       {
  3172.     register int c = getch ();
  3173.     if (c == '\'')
  3174.       {
  3175.         wide_flag = 1;
  3176.         goto char_constant;
  3177.       }
  3178.     if (c == '"')
  3179.       {
  3180.         wide_flag = 1;
  3181.         goto string_constant;
  3182.       }
  3183.     ungetc (c, finput);
  3184.       }
  3185.  
  3186. #ifdef OBJCPLUS
  3187.     case '@':
  3188.       /* '@' may start a constant string object.  */
  3189.       {
  3190.     register int c = getc (finput);
  3191.     if (c == '"')
  3192.       {
  3193.         objc_flag = 1;
  3194.         goto string_constant;
  3195.       }
  3196.     ungetc (c, finput);
  3197.       }
  3198. #endif /* OBJCPLUS */
  3199.  
  3200.     case 'A':  case 'B':  case 'C':  case 'D':  case 'E':
  3201.     case 'F':  case 'G':  case 'H':  case 'I':  case 'J':
  3202.     case 'K':          case 'M':  case 'N':  case 'O':
  3203.     case 'P':  case 'Q':  case 'R':  case 'S':  case 'T':
  3204.     case 'U':  case 'V':  case 'W':  case 'X':  case 'Y':
  3205.     case 'Z':
  3206.     case 'a':  case 'b':  case 'c':  case 'd':  case 'e':
  3207.     case 'f':  case 'g':  case 'h':  case 'i':  case 'j':
  3208.     case 'k':  case 'l':  case 'm':  case 'n':  case 'o':
  3209.     case 'p':  case 'q':  case 'r':  case 's':  case 't':
  3210.     case 'u':  case 'v':  case 'w':  case 'x':  case 'y':
  3211.     case 'z':
  3212.     case '_':
  3213.     letter:
  3214.       {
  3215.     register char *p;
  3216.  
  3217.     p = token_buffer;
  3218. #ifdef OBJCPLUS
  3219.         while (isalnum (c) || c == '_' || c == '$' || c == '@')
  3220. #else /* OBJCPLUS */
  3221.     while (isalnum(c) || (c == '_') || c == '$')
  3222. #endif /* OBJCPLUS */
  3223.       {
  3224.         if (p >= token_buffer + maxtoken)
  3225.           p = extend_token_buffer (p);
  3226.         if (c == '$' && ! dollars_in_ident)
  3227.           break;
  3228.  
  3229.         *p++ = c;
  3230.         c = getc (finput);
  3231.       }
  3232.  
  3233.     *p = 0;
  3234.     nextchar = c;
  3235.  
  3236.     value = IDENTIFIER;
  3237.     yylval.itype = 0;
  3238.  
  3239.       /* Try to recognize a keyword.  Uses minimum-perfect hash function */
  3240.  
  3241.     {
  3242.       register struct resword *ptr;
  3243.  
  3244.       if (ptr = is_reserved_word (token_buffer, p - token_buffer))
  3245.         {
  3246.           if (current_lang_name != lang_name_cplusplus)
  3247.         {
  3248.           if (ptr->rid != 0
  3249.               && (ptr->rid == RID_CLASS
  3250.               || ptr->rid == RID_FRIEND
  3251.               || ptr->rid == RID_VIRTUAL
  3252.               || (flag_no_asm && ptr->rid == RID_INLINE)))
  3253.             {
  3254.               ptr = 0;
  3255.               goto not_reserved_word_after_all;
  3256.             }
  3257.           if (flag_traditional
  3258.               && ((int) ptr->token == TYPEOF
  3259.               || ptr->rid == RID_SIGNED
  3260.               || ptr->rid == RID_INLINE))
  3261.             {
  3262.               ptr = 0;
  3263.               goto not_reserved_word_after_all;
  3264.             }  
  3265.         }
  3266.           if (ptr->rid)
  3267.         {
  3268.           tree old_ttype = ridpointers[(int) ptr->rid];
  3269.  
  3270.           /* If this provides a type for us, then revert lexical
  3271.              state to standard state.  */
  3272.           if (TREE_CODE (old_ttype) == IDENTIFIER_NODE
  3273.               && IDENTIFIER_GLOBAL_VALUE (old_ttype) != 0
  3274.               && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (old_ttype)) == TYPE_DECL)
  3275.             looking_for_typename = 0;
  3276.  
  3277.           /* Check if this is a language-type declaration.
  3278.              Just glimpse the next non-white character.  */
  3279.           nextchar = skip_white_space (nextchar);
  3280.           if (nextchar == '"')
  3281.             {
  3282.               /* We are looking at a string.  Complain
  3283.              if the token before the string is no `extern'.
  3284.              
  3285.              Could cheat some memory by placing this string
  3286.              on the temporary_, instead of the saveable_
  3287.              obstack.  */
  3288.  
  3289.               if (ptr->rid != RID_EXTERN)
  3290.             error ("invalid modifier `%s' for language string",
  3291.                    ptr->name);
  3292.               yylex ();
  3293.               value = EXTERN_LANG_STRING;
  3294.               yylval.ttype = get_identifier (TREE_STRING_POINTER (yylval.ttype));
  3295.               break;
  3296.             }
  3297.           yylval.ttype = old_ttype;
  3298.         }
  3299.           value = (int) ptr->token;
  3300. #ifdef OBJCPLUS
  3301.         /* Only return OBJECTNAME if it is a typedef.  */
  3302.         if (value == OBJECTNAME)
  3303.           {
  3304.         lastiddecl = lookup_name (yylval.ttype);
  3305.  
  3306.         if (doing_objc_thang && lastiddecl
  3307.             && TREE_CODE (lastiddecl) == TYPE_DECL)
  3308.           value = OBJECTNAME;
  3309.         else
  3310.           value = IDENTIFIER;
  3311.           }
  3312. #endif /* OBJCPLUS */
  3313.         }
  3314.       not_reserved_word_after_all:
  3315.       ;
  3316.     }
  3317.  
  3318.     /* If we did not find a keyword, look for an identifier
  3319.        (or a typename).  */
  3320.  
  3321. #ifdef FIELD_XREF
  3322.     if (value == IDENTIFIER || value == TYPESPEC)
  3323.       FIELD_xref_ref(current_function_decl,token_buffer);
  3324. #endif
  3325.     if (value == IDENTIFIER)
  3326.       {
  3327. #ifdef OBJCPLUS
  3328.         if (token_buffer[0] == '@')
  3329.           error ("illegal identifier `%s'", token_buffer);
  3330. #endif /* OBJCPLUS */
  3331.         tmp = get_identifier (token_buffer);
  3332. #ifndef VMS
  3333.         /* Make sure that user does not collide with our internal
  3334.            naming scheme.  */
  3335.         if (JOINER == '$'
  3336.         && dollar_seen
  3337.         && (THIS_NAME_P (tmp)
  3338.             || VPTR_NAME_P (tmp)
  3339.             || DESTRUCTOR_NAME_P (tmp)
  3340.             || WRAPPER_OR_ANTI_WRAPPER_NAME_P (tmp)
  3341.             || OPERATOR_NAME_P (tmp)
  3342.             || VTABLE_NAME_P (tmp)
  3343.             || OPERATOR_TYPENAME_P (tmp)
  3344.             || TEMP_NAME_P (tmp)
  3345.             || ANON_AGGRNAME_P (tmp)
  3346.             || ANON_PARMNAME_P (tmp)))
  3347.           warning ("identifier name `%s' conflicts with GNU C++ internal naming strategy",
  3348.                token_buffer);
  3349. #endif
  3350.  
  3351.         /* Come into here if we must reprocess an identifier.  */
  3352.       resume_identifier_processing:
  3353.  
  3354.         if (looking_for_typename == 1
  3355.         && TREE_TYPE (tmp) != 0)
  3356.           lastiddecl = TREE_TYPE (tmp);
  3357.         else lastiddecl = lookup_name (tmp);
  3358.  
  3359.         if (lastiddecl && TREE_CODE (lastiddecl) == TYPE_DECL
  3360.         && looking_for_typename >= 0)
  3361.           {
  3362.         /* This call could blow away yylval.  */
  3363.  
  3364.         c = skip_white_space (nextchar);
  3365.         if (c == ':')
  3366.           {
  3367.             c = getch ();
  3368.             if (c == ':')
  3369.               {
  3370.             nextchar = -1;
  3371.             value = TYPENAME_SCOPE;
  3372.               }
  3373.             else
  3374.               {
  3375.             nextchar = c;
  3376.             value = TYPENAME_COLON;
  3377.               }
  3378.           }
  3379.         else if (c == '.'
  3380.              && current_function_decl == NULL_TREE
  3381.              && current_class_type == NULL_TREE)
  3382.           {
  3383.             c = getch ();
  3384.             if (c == '.')
  3385.               {
  3386.             nextchar = -1;
  3387.             c = getch ();
  3388.             if (c != '.')
  3389.               error ("missing '.' in `...'");
  3390.             value = TYPENAME_ELLIPSIS;
  3391.             tmp = build_tree_list (NULL_TREE, build_tree_list (TREE_TYPE (lastiddecl), NULL_TREE));
  3392.               }
  3393.             else
  3394.               {
  3395.             nextchar = c;
  3396.             warning ("use of obsolete scope operator `.'; use `::' instead");
  3397.             value = TYPENAME_SCOPE;
  3398.               }
  3399.             looking_for_typename = 0;
  3400.           }
  3401.         else
  3402.           {
  3403.             nextchar = c;
  3404.             value = TYPENAME;
  3405.             if (looking_for_typename == 1)
  3406.               {
  3407.             looking_for_typename = 0;
  3408. #if 0
  3409.             yylval.ttype = TREE_TYPE (lastiddecl);
  3410.             break;
  3411. #endif
  3412.               }
  3413.           }
  3414.           }
  3415. #ifdef OBJCPLUS
  3416.         else if (doing_objc_thang && is_class_name (tmp))
  3417.           value = CLASSNAME;
  3418. #endif /* OBJCPLUS */
  3419.         else if (lastiddecl == 0 && flag_labels_ok)
  3420.           lastiddecl = IDENTIFIER_LABEL_VALUE (tmp);
  3421.  
  3422.         yylval.ttype = tmp;
  3423.       }
  3424.     if (value == NEW && ! global_bindings_p ())
  3425.       {
  3426.         looking_for_typename = 1;
  3427.         value = NEW;
  3428.         goto done;
  3429.       }
  3430.       }
  3431.       break;
  3432.  
  3433.     case '0':  case '1':  case '2':  case '3':  case '4':
  3434.     case '5':  case '6':  case '7':  case '8':  case '9':
  3435.     case '.':
  3436.       {
  3437.     register char *p;
  3438.     int base = 10;
  3439.     int count = 0;
  3440.     int largest_digit = 0;
  3441.     int numdigits = 0;
  3442.     /* for multi-precision arithmetic,
  3443.        we store only 8 live bits in each short,
  3444.        giving us 64 bits of reliable precision */
  3445.     short shorts[8];
  3446.  
  3447.     enum anon1 { NOT_FLOAT, AFTER_POINT, TOO_MANY_POINTS} floatflag
  3448.       = NOT_FLOAT;
  3449.  
  3450.     p = token_buffer;
  3451.     *p++ = c;
  3452.  
  3453.     /* Optimize for most frequent case.  */
  3454.     if (c == '0' || c == '1')
  3455.       {
  3456.         register int c1 = getch ();
  3457.         if (! isalnum (c1) && c1 != '.')
  3458.           {
  3459.         /* Terminate string.  */
  3460.         *p = 0;
  3461.         if (c == '0')
  3462.           yylval.ttype = integer_zero_node;
  3463.         else
  3464.           yylval.ttype = integer_one_node;
  3465.         nextchar = c1;
  3466.         value = CONSTANT;
  3467.         goto done;
  3468.           }
  3469.         ungetc (c1, finput);
  3470.       }
  3471.  
  3472.     for (count = 0; count < 8; count++)
  3473.       shorts[count] = 0;
  3474.  
  3475.     if (c == '0')
  3476.       {
  3477.         *p++ = (c = getch ());
  3478.         if ((c == 'x') || (c == 'X'))
  3479.           {
  3480.         base = 16;
  3481.         *p++ = (c = getch ());
  3482.           }
  3483.         else
  3484.           {
  3485.         base = 8;
  3486.         numdigits++;
  3487.           }
  3488.       }
  3489.  
  3490.     /* Read all the digits-and-decimal-points.  */
  3491.  
  3492.     while (c == '.'
  3493.            || (isalnum (c) && (c != 'l') && (c != 'L')
  3494.            && (c != 'u') && (c != 'U')
  3495.            && (floatflag == NOT_FLOAT || ((c != 'f') && (c != 'F')))))
  3496.       {
  3497.         if (c == '.')
  3498.           {
  3499.         if (base == 16)
  3500.           error ("floating constant may not be in radix 16");
  3501.         if (floatflag == AFTER_POINT)
  3502.           {
  3503.             error ("malformed floating constant");
  3504.             floatflag = TOO_MANY_POINTS;
  3505.           }
  3506.         else
  3507.           floatflag = AFTER_POINT;
  3508.  
  3509.         base = 10;
  3510.         *p++ = c = getch ();
  3511.         /* Accept '.' as the start of a floating-point number
  3512.            only when it is followed by a digit.
  3513.            Otherwise, unread the following non-digit
  3514.            and use the '.' as a structural token.  */
  3515.         if (p == token_buffer + 2 && !isdigit (c))
  3516.           {
  3517.             if (c == '.')
  3518.               {
  3519.             c = getch ();
  3520.             if (c == '.')
  3521.               {
  3522.                 *p++ = '.';
  3523.                 *p = '\0';
  3524.                 value = ELLIPSIS;
  3525.                 goto done;
  3526.               }
  3527.             nextchar = c;
  3528.             token_buffer[2] = '\0';
  3529.             value = RANGE;
  3530.             goto done;
  3531.               }
  3532.             nextchar = c;
  3533.             token_buffer[1] = '\0';
  3534.             value = '.';
  3535.             goto done;
  3536.           }
  3537.           }
  3538.         else
  3539.           {
  3540.         /* It is not a decimal point.
  3541.            It should be a digit (perhaps a hex digit).  */
  3542.  
  3543.         if (isdigit (c))
  3544.           {
  3545.             c = c - '0';
  3546.           }
  3547.         else if (base <= 10)
  3548.           {
  3549.             if ((c&~040) == 'E')
  3550.               {
  3551.             base = 10;
  3552.             floatflag = AFTER_POINT;
  3553.             break;   /* start of exponent */
  3554.               }
  3555.             error ("nondigits in number and not hexadecimal");
  3556.             c = 0;
  3557.           }
  3558.         else if (c >= 'a')
  3559.           {
  3560.             c = c - 'a' + 10;
  3561.           }
  3562.         else
  3563.           {
  3564.             c = c - 'A' + 10;
  3565.           }
  3566.         if (c >= largest_digit)
  3567.           largest_digit = c;
  3568.         numdigits++;
  3569.  
  3570.         for (count = 0; count < 8; count++)
  3571.           {
  3572.             (shorts[count] *= base);
  3573.             if (count)
  3574.               {
  3575.             shorts[count] += (shorts[count-1] >> 8);
  3576.             shorts[count-1] &= (1<<8)-1;
  3577.               }
  3578.             else shorts[0] += c;
  3579.           }
  3580.  
  3581.         if (p >= token_buffer + maxtoken - 3)
  3582.           p = extend_token_buffer (p);
  3583.         *p++ = (c = getch ());
  3584.           }
  3585.       }
  3586.  
  3587.     if (numdigits == 0)
  3588.       error ("numeric constant with no digits");
  3589.  
  3590.     if (largest_digit >= base)
  3591.       error ("numeric constant contains digits beyond the radix");
  3592.  
  3593.     /* Remove terminating char from the token buffer and delimit the string */
  3594.     *--p = 0;
  3595.  
  3596.     if (floatflag != NOT_FLOAT)
  3597.       {
  3598.         tree type = double_type_node;
  3599.         char f_seen = 0;
  3600.         char l_seen = 0;
  3601.         double value;
  3602.  
  3603.         /* Read explicit exponent if any, and put it in tokenbuf.  */
  3604.  
  3605.         if ((c == 'e') || (c == 'E'))
  3606.           {
  3607.         if (p >= token_buffer + maxtoken - 3)
  3608.           p = extend_token_buffer (p);
  3609.         *p++ = c;
  3610.         c = getch ();
  3611.         if ((c == '+') || (c == '-'))
  3612.           {
  3613.             *p++ = c;
  3614.             c = getch ();
  3615.           }
  3616.         if (! isdigit (c))
  3617.           error ("floating constant exponent has no digits");
  3618.             while (isdigit (c))
  3619.           {
  3620.             if (p >= token_buffer + maxtoken - 3)
  3621.               p = extend_token_buffer (p);
  3622.             *p++ = c;
  3623.             c = getch ();
  3624.           }
  3625.           }
  3626.  
  3627.         *p = 0;
  3628.         errno = 0;
  3629.         value = atof (token_buffer);
  3630. #ifdef ERANGE
  3631.         if (errno == ERANGE && !flag_traditional)
  3632.           {
  3633.         char *p1 = token_buffer;
  3634.         /* Check for "0.0" and variants;
  3635.            Sunos 4 spuriously returns ERANGE for them.  */
  3636.         while (*p1 == '0') p1++;
  3637.         if (*p1 == '.') p1++;
  3638.         while (*p1 == '0') p1++;
  3639.         if (*p1 != 0)
  3640.           warning ("floating point number exceeds range of `double'");
  3641.           }
  3642. #endif
  3643.  
  3644.         /* Read the suffixes to choose a data type.  */
  3645.         while (1)
  3646.           {
  3647.         if (c == 'f' || c == 'F')
  3648.           {
  3649.             if (f_seen)
  3650.               error ("two `f's in floating constant");
  3651.             f_seen = 1;
  3652.             type = float_type_node;
  3653.           }
  3654.         else if (c == 'l' || c == 'L')
  3655.           {
  3656.             if (l_seen)
  3657.               error ("two `l's in floating constant");
  3658.             l_seen = 1;
  3659.             type = long_double_type_node;
  3660.           }
  3661.         else
  3662.           {
  3663.             if (isalnum (c))
  3664.               {
  3665.             error ("garbage at end of number");
  3666.             while (isalnum (c))
  3667.               {
  3668.                 if (p >= token_buffer + maxtoken - 3)
  3669.                   p = extend_token_buffer (p);
  3670.                 *p++ = c;
  3671.                 c = getch ();
  3672.               }
  3673.               }
  3674.             break;
  3675.           }
  3676.         if (p >= token_buffer + maxtoken - 3)
  3677.           p = extend_token_buffer (p);
  3678.         *p++ = c;
  3679.         c = getch ();
  3680.           }
  3681.  
  3682.         /* Create a node with determined type and value.  */
  3683.         yylval.ttype = build_real (type, value);
  3684.  
  3685.         ungetc (c, finput);
  3686.         *p = 0;
  3687.       }
  3688.     else
  3689.       {
  3690.         tree type;
  3691.         int spec_unsigned = 0;
  3692.         int spec_long = 0;
  3693.  
  3694.         while (1)
  3695.           {
  3696.         if (c == 'u' || c == 'U')
  3697.           {
  3698.             if (spec_unsigned)
  3699.               error ("two `u's in integer constant");
  3700.             spec_unsigned = 1;
  3701.           }
  3702.         else if (c == 'l' || c == 'L')
  3703.           {
  3704.             if (spec_long)
  3705.               error ("two `l's in integer constant");
  3706.             spec_long = 1;
  3707.           }
  3708.         else
  3709.           {
  3710.             if (isalnum (c))
  3711.               {
  3712.             error ("garbage at end of number");
  3713.             while (isalnum (c))
  3714.               {
  3715.                 if (p >= token_buffer + maxtoken - 3)
  3716.                   p = extend_token_buffer (p);
  3717.                 *p++ = c;
  3718.                 c = getch ();
  3719.               }
  3720.               }
  3721.             break;
  3722.           }
  3723.         if (p >= token_buffer + maxtoken - 3)
  3724.           p = extend_token_buffer (p);
  3725.         *p++ = c;
  3726.         c = getch ();
  3727.           }
  3728.  
  3729.         ungetc (c, finput);
  3730.  
  3731.         if (shorts[7] | shorts[6] | shorts[5] | shorts[4])
  3732.           warning ("integer constant out of range");
  3733.  
  3734.         /* This is simplified by the fact that our constant
  3735.            is always positive.  */
  3736.         yylval.ttype
  3737.           = build_int_2 ((shorts[3]<<24) + (shorts[2]<<16) + (shorts[1]<<8) + shorts[0],
  3738.                  0);
  3739.  
  3740.         if (!spec_long && !spec_unsigned
  3741.         && int_fits_type_p (yylval.ttype, integer_type_node))
  3742.           type = integer_type_node;
  3743.  
  3744.         else if (!spec_long && base != 10
  3745.              && int_fits_type_p (yylval.ttype, unsigned_type_node))
  3746.           type = unsigned_type_node;
  3747.  
  3748.         else if (!spec_unsigned
  3749.              && int_fits_type_p (yylval.ttype, long_integer_type_node))
  3750.           type = long_integer_type_node;
  3751.  
  3752.         else
  3753.           {
  3754.         type = long_unsigned_type_node;
  3755.         if (! int_fits_type_p (yylval.ttype, long_unsigned_type_node))
  3756.           warning ("integer constant out of range");
  3757.           }
  3758.         TREE_TYPE (yylval.ttype) = type;
  3759.       }
  3760.  
  3761.     value = CONSTANT; break;
  3762.       }
  3763.  
  3764.     case '\'':
  3765.     char_constant:
  3766.       {
  3767.     register int result = 0;
  3768.     register num_chars = 0;
  3769.     int width = TYPE_PRECISION (char_type_node);
  3770.     int max_chars;
  3771.  
  3772.     if (wide_flag) width = TYPE_PRECISION (integer_type_node);
  3773.  
  3774.     max_chars = TYPE_PRECISION (integer_type_node) / width;
  3775.  
  3776.     while (1)
  3777.       {
  3778.       tryagain:
  3779.  
  3780.         c = getch ();
  3781.  
  3782.         if (c == '\'' || c == EOF)
  3783.           break;
  3784.  
  3785.         if (c == '\\')
  3786.           {
  3787.         c = readescape ();
  3788.         if (c < 0)
  3789.           goto tryagain;
  3790.         if (width < HOST_BITS_PER_INT
  3791.             && (unsigned) c >= (1 << width))
  3792.           warning ("escape sequence out of range for character");
  3793.           }
  3794.         else if (c == '\n')
  3795.           {
  3796.         if (pedantic)
  3797.           warning ("ANSI C forbids newline in character constant");
  3798.         lineno++;
  3799.           }
  3800.  
  3801.         num_chars++;
  3802.         if (num_chars > maxtoken - 4)
  3803.           extend_token_buffer (token_buffer);
  3804.  
  3805.         token_buffer[num_chars] = c;
  3806.  
  3807.         /* Merge character into result; ignore excess chars.  */
  3808.         if (num_chars < max_chars + 1)
  3809.           {
  3810.         if (width < HOST_BITS_PER_INT)
  3811.           result = (result << width) | (c & ((1 << width) - 1));
  3812.         else
  3813.           result = c;
  3814.           }
  3815.       }
  3816.  
  3817.     token_buffer[num_chars + 1] = '\'';
  3818.     token_buffer[num_chars + 2] = 0;
  3819.  
  3820.     if (c != '\'')
  3821.       error ("malformatted character constant");
  3822.     else if (num_chars == 0)
  3823.       error ("empty character constant");
  3824.     else if (num_chars > max_chars)
  3825.       {
  3826.         num_chars = max_chars;
  3827.         error ("character constant too long");
  3828.       }
  3829.     else if (num_chars != 1 && ! flag_traditional)
  3830.       warning ("multi-character character constant");
  3831.  
  3832.     /* If char type is signed, sign-extend the constant.  */
  3833.     if (! wide_flag)
  3834.       {
  3835.         int num_bits = num_chars * width;
  3836.         if (TREE_UNSIGNED (char_type_node)
  3837.         || ((result >> (num_bits - 1)) & 1) == 0)
  3838.           yylval.ttype
  3839.         = build_int_2 (result & ((unsigned) ~0
  3840.                      >> (HOST_BITS_PER_INT - num_bits)),
  3841.                    0);
  3842.         else
  3843.           yylval.ttype
  3844.         = build_int_2 (result | ~((unsigned) ~0
  3845.                       >> (HOST_BITS_PER_INT - num_bits)),
  3846.                    -1);
  3847.         TREE_TYPE (yylval.ttype) = char_type_node;
  3848.       }
  3849.     else
  3850.       {
  3851.         yylval.ttype = build_int_2 (result, 0);
  3852.         TREE_TYPE (yylval.ttype) = integer_type_node;
  3853.       }
  3854.     value = CONSTANT; break;
  3855.       }
  3856.  
  3857.     case '"':
  3858.     string_constant:
  3859.       {
  3860.     int *widep;
  3861.     register char *p;
  3862.  
  3863.     c = getch ();
  3864.     p = token_buffer + 1;
  3865.  
  3866.     if (wide_flag)
  3867.       widep = wide_buffer;
  3868.  
  3869.     while (c != '"' && c >= 0)
  3870.       {
  3871.         if (c == '\\')
  3872.           {
  3873.         c = readescape ();
  3874.         if (c < 0)
  3875.           goto skipnewline;
  3876.         if (!wide_flag && c >= (1 << BITS_PER_UNIT))
  3877.           warning ("escape sequence out of range for character");
  3878.           }
  3879.         else if (c == '\n')
  3880.           {
  3881.         if (pedantic)
  3882.           warning ("ANSI C forbids newline in string constant");
  3883.         lineno++;
  3884.           }
  3885.  
  3886.         /* Store the char in C into the appropriate buffer.  */
  3887.  
  3888.         if (wide_flag)
  3889.           {
  3890.         if (widep == wide_buffer + max_wide)
  3891.           {
  3892.             int n = widep - wide_buffer;
  3893.             max_wide *= 2;
  3894.             wide_buffer = (int *) xrealloc (wide_buffer, max_wide + 1);
  3895.             widep = wide_buffer + n;
  3896.           }
  3897.         *widep++ = c;
  3898.           }
  3899.         else
  3900.           {
  3901.         if (p == token_buffer + maxtoken)
  3902.           p = extend_token_buffer (p);
  3903.         *p++ = c;
  3904.           }
  3905.  
  3906.       skipnewline:
  3907.         c = getch ();
  3908.         if (c == EOF) {
  3909.         error("Unterminated string");
  3910.         break;
  3911.         }
  3912.       }
  3913.  
  3914.     /* We have read the entire constant.
  3915.        Construct a STRING_CST for the result.  */
  3916.  
  3917.     if (wide_flag)
  3918.       {
  3919.         /* If this is a L"..." wide-string, make a vector
  3920.            of the ints in wide_buffer.  */
  3921.         *widep = 0;
  3922.         /* We have not implemented the case where `int'
  3923.            on the target and on the execution machine differ in size.  */
  3924.         assert (TYPE_PRECISION (integer_type_node) == sizeof (int) * BITS_PER_UNIT);
  3925.         yylval.ttype = build_string ((widep - wide_buffer) * sizeof (int),
  3926.                      (char *)wide_buffer);
  3927.         TREE_TYPE (yylval.ttype) = int_array_type_node;
  3928. #ifdef OBJCPLUS
  3929.         value = STRING;
  3930. #endif /* OBJCPLUS */
  3931.       }
  3932. #ifdef OBJCPLUS
  3933.     else if (objc_flag)
  3934.       {
  3935.         /* Return an Objective-C @"..." constant string object.  */
  3936.         *p = 0;
  3937.         yylval.ttype = build_objc_string (p - token_buffer,
  3938.                           token_buffer + 1);
  3939.         value = OBJC_STRING;
  3940.       }
  3941. #endif /* OBJCPLUS */
  3942.     else
  3943.       {
  3944.         *p = 0;
  3945.         yylval.ttype = build_string (p - token_buffer, token_buffer + 1);
  3946.         TREE_TYPE (yylval.ttype) = char_array_type_node;
  3947. #ifdef OBJCPLUS
  3948.         value = STRING;
  3949. #endif /* OBJCPLUS */
  3950.       }
  3951.  
  3952.     *p++ = '"';
  3953.     *p = 0;
  3954.  
  3955. #ifdef OBJCPLUS
  3956.     break;
  3957. #else /* OBJCPLUS */
  3958.     value = STRING; break;
  3959. #endif /* OBJCPLUS */
  3960.       }
  3961.  
  3962.     case '+':
  3963.     case '-':
  3964.     case '&':
  3965.     case '|':
  3966.     case '<':
  3967.     case '>':
  3968.     case '*':
  3969.     case '/':
  3970.     case '%':
  3971.     case '^':
  3972.     case '!':
  3973.     case '=':
  3974.       {
  3975.     register int c1;
  3976.  
  3977.       combine:
  3978.  
  3979.     switch (c)
  3980.       {
  3981.       case '+':
  3982.         yylval.code = PLUS_EXPR; break;
  3983.       case '-':
  3984.         yylval.code = MINUS_EXPR; break;
  3985.       case '&':
  3986.         yylval.code = BIT_AND_EXPR; break;
  3987.       case '|':
  3988.         yylval.code = BIT_IOR_EXPR; break;
  3989.       case '*':
  3990.         yylval.code = MULT_EXPR; break;
  3991.       case '/':
  3992.         yylval.code = TRUNC_DIV_EXPR; break;
  3993.       case '%':
  3994.         yylval.code = TRUNC_MOD_EXPR; break;
  3995.       case '^':
  3996.         yylval.code = BIT_XOR_EXPR; break;
  3997.       case LSHIFT:
  3998.         yylval.code = LSHIFT_EXPR; break;
  3999.       case RSHIFT:
  4000.         yylval.code = RSHIFT_EXPR; break;
  4001.       case '<':
  4002.         yylval.code = LT_EXPR; break;
  4003.       case '>':
  4004.         yylval.code = GT_EXPR; break;
  4005.       }
  4006.  
  4007.     token_buffer[1] = c1 = getch ();
  4008.     token_buffer[2] = 0;
  4009.  
  4010.     if (c1 == '=')
  4011.       {
  4012.         switch (c)
  4013.           {
  4014.           case '<':
  4015.         value = ARITHCOMPARE; yylval.code = LE_EXPR; goto done;
  4016.           case '>':
  4017.         value = ARITHCOMPARE; yylval.code = GE_EXPR; goto done;
  4018.           case '!':
  4019.         value = EQCOMPARE; yylval.code = NE_EXPR; goto done;
  4020.           case '=':
  4021.         value = EQCOMPARE; yylval.code = EQ_EXPR; goto done;
  4022.           }
  4023.         value = ASSIGN; goto done;
  4024.       }
  4025.     else if (c == c1)
  4026.       switch (c)
  4027.         {
  4028.         case '+':
  4029.           value = PLUSPLUS; goto done;
  4030.         case '-':
  4031.           value = MINUSMINUS; goto done;
  4032.         case '&':
  4033.           value = ANDAND; goto done;
  4034.         case '|':
  4035.           value = OROR; goto done;
  4036.         case '<':
  4037.           c = LSHIFT;
  4038.           goto combine;
  4039.         case '>':
  4040.           c = RSHIFT;
  4041.           goto combine;
  4042.         }
  4043.     else if ((c == '-') && (c1 == '>'))
  4044.       {
  4045.         nextchar = skip_white_space (getch ());
  4046.         if (nextchar == '(')
  4047.           {
  4048.         int next_c = skip_white_space (getch ());
  4049.         if (next_c == ')')
  4050.           {
  4051.             nextchar = -1;
  4052.             value = POINTSAT_LEFT_RIGHT;
  4053.             goto done;
  4054.           }
  4055.         ungetc (next_c, finput);
  4056.           }
  4057.         value = POINTSAT;
  4058.         goto done;
  4059.       }
  4060.     else if (c1 == '?' && (c == '<' || c == '>'))
  4061.       {
  4062.         token_buffer[3] = 0;
  4063.  
  4064.         c1 = getch ();
  4065.         yylval.code = (c == '<' ? MIN_EXPR : MAX_EXPR);
  4066.         if (c1 == '=')
  4067.           {
  4068.         /* <?= or >?= expression.  */
  4069.         token_buffer[2] = c1;
  4070.         value = ASSIGN;
  4071.           }
  4072.         else
  4073.           {
  4074.         value = MIN_MAX;
  4075.         nextchar = c1;
  4076.           }
  4077.         if (pedantic)
  4078.           error ("use of `operator %s' is not standard C++",
  4079.              token_buffer);
  4080.         goto done;
  4081.       }
  4082.  
  4083.     nextchar = c1;
  4084.     token_buffer[1] = 0;
  4085.  
  4086.     if ((c == '<') || (c == '>'))
  4087.       value = ARITHCOMPARE;
  4088.     else value = c;
  4089.     goto done;
  4090.       }
  4091.  
  4092.     case ':':
  4093.       c = getch ();
  4094.       if (c == ':')
  4095.     {
  4096.       token_buffer[1] = ':';
  4097.       token_buffer[2] = '\0';
  4098.       value = SCOPE;
  4099.       yylval.itype = 1;
  4100.     }
  4101.       else
  4102.     {
  4103.       nextchar = c;
  4104.       value = ':';
  4105.     }
  4106.       break;
  4107.  
  4108.     case 0:
  4109.       /* Don't make yyparse think this is eof.  */
  4110.       value = 1;
  4111.       break;
  4112.  
  4113.     case '(':
  4114.       /* try, weakly, to handle casts to pointers to functions.  */
  4115.       nextchar = skip_white_space (getch ());
  4116.       if (nextchar == '*')
  4117.     {
  4118.       int next_c = skip_white_space (getch ());
  4119.       if (next_c == ')')
  4120.         {
  4121.           nextchar = -1;
  4122.           yylval.ttype = build1 (INDIRECT_REF, 0, 0);
  4123.           value = PAREN_STAR_PAREN;
  4124.         }
  4125.       else
  4126.         {
  4127.           ungetc (next_c, finput);
  4128.           value = c;
  4129.         }
  4130.     }
  4131.       /* Go down for a (X::*) or (X::&).  */
  4132.       else if (isalpha (nextchar) || nextchar == '_' || nextchar == '$')
  4133.     {
  4134.       YYSTYPE this_yylval = yylval;
  4135.       tree this_lastiddecl = lastiddecl;
  4136.       nextyychar = yylex ();
  4137.       if (nextyychar == TYPENAME_SCOPE)
  4138.         {
  4139.           if (nextchar < 0)
  4140.         nextchar = skip_white_space (getch ());
  4141.           if (nextchar == '*' || nextchar == '&')
  4142.         {
  4143.           int next_c = skip_white_space (getch ());
  4144.           if (next_c == ')')
  4145.             {
  4146.               nextyychar = -1;
  4147.               if (nextchar == '*')
  4148.             {
  4149.               value = PAREN_X_SCOPE_STAR_PAREN;
  4150.               yylval.ttype = build_parse_node (SCOPE_REF, yylval.ttype,
  4151.                                build_parse_node (INDIRECT_REF, 0));
  4152.             }
  4153.               else
  4154.             {
  4155.               value = PAREN_X_SCOPE_REF_PAREN;
  4156.               yylval.ttype = build_parse_node (SCOPE_REF, yylval.ttype,
  4157.                                build_parse_node (ADDR_EXPR, 0));
  4158.             }
  4159.               nextchar = -1;
  4160.             }
  4161.           else
  4162.             {
  4163.               ungetc (next_c, finput);
  4164.               nextyylval = yylval;
  4165.               nextlastiddecl = lastiddecl;
  4166.               yylval = this_yylval;
  4167.               lastiddecl = this_lastiddecl;
  4168.               value = c;
  4169.             }
  4170.         }
  4171.           else
  4172.         {
  4173.           nextyylval = yylval;
  4174.           nextlastiddecl = lastiddecl;
  4175.           yylval = this_yylval;
  4176.           lastiddecl = this_lastiddecl;
  4177.           value = c;
  4178.         }
  4179.         }
  4180.       else
  4181.         {
  4182.           nextyylval = yylval;
  4183.           nextlastiddecl = lastiddecl;
  4184.           yylval = this_yylval;
  4185.           lastiddecl = this_lastiddecl;
  4186.           value = c;
  4187.         }
  4188.     }
  4189.       else if (nextchar == ')')
  4190.     {
  4191.       nextchar = -1;
  4192.       yylval.ttype = NULL_TREE;
  4193.       value = LEFT_RIGHT;
  4194.     }
  4195.       else value = c;
  4196.       break;
  4197.  
  4198.     default:
  4199.       value = c;
  4200.     }
  4201.  
  4202. done:
  4203. /*  yylloc.last_line = lineno; */
  4204. #ifdef GATHER_STATISTICS
  4205.   token_count[value] += 1;
  4206. #endif
  4207.  
  4208.   return value;
  4209. }
  4210.  
  4211. typedef enum
  4212. {
  4213.   d_kind, t_kind, s_kind, r_kind, e_kind, c_kind,
  4214.   id_kind, op_id_kind, perm_list_kind, temp_list_kind,
  4215.   x_kind, lang_decl, lang_type, all_kinds
  4216. } tree_node_kind;
  4217. extern int tree_node_kinds[];
  4218. extern int tree_node_sizes[];
  4219. extern char *tree_node_kind_names[];
  4220.  
  4221. /* Place to save freed lang_decls which were allocated on the
  4222.    permanent_obstack.  @@ Not currently used.  */
  4223. tree free_lang_decl_chain;
  4224.  
  4225. tree
  4226. build_lang_decl (code, name, type)
  4227.      enum tree_code code;
  4228.      tree name;
  4229.      tree type;
  4230. {
  4231.   extern struct obstack *current_obstack, *saveable_obstack;
  4232.   extern struct obstack permanent_obstack;
  4233.   register tree t = build_decl (code, name, type);
  4234.   struct obstack *obstack = current_obstack;
  4235.   register int i = sizeof (struct lang_decl) / sizeof (int);
  4236.   register int *pi;
  4237.  
  4238.   if (! TREE_PERMANENT (t))
  4239.     obstack = saveable_obstack;
  4240.  
  4241. #ifdef LANG_DECL_PERMANENT
  4242.   if (free_lang_decl_chain && obstack == &permanent_obstack)
  4243.     {
  4244.       pi = (int *)free_lang_decl_chain;
  4245.       free_lang_decl_chain = TREE_CHAIN (free_lang_decl_chain);
  4246.     }
  4247.   else
  4248.     pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl));
  4249. #else
  4250.   pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl));
  4251. #endif
  4252.  
  4253.   while (i > 0)
  4254.     pi[--i] = 0;
  4255.  
  4256.   DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi;
  4257. #ifdef LANG_DECL_PERMANENT
  4258.   LANG_DECL_PERMANENT ((struct lang_decl *) pi)
  4259.     = obstack == &permanent_obstack;
  4260. #endif
  4261.   DECL_MAIN_VARIANT (t) = t;
  4262.   DECL_ORIGINAL_NAME (t) = name;
  4263.   if (current_lang_name == lang_name_cplusplus)
  4264.     {
  4265.       DECL_LANGUAGE (t) = lang_cplusplus;
  4266.  
  4267. #ifndef NO_AUTO_OVERLOAD
  4268.       if (code == FUNCTION_DECL && name != 0
  4269.       && ! (IDENTIFIER_LENGTH (name) == 4
  4270.         && IDENTIFIER_POINTER (name)[0] == 'm'
  4271.         && strcmp (IDENTIFIER_POINTER (name), "main") == 0)
  4272.       && ! (IDENTIFIER_LENGTH (name) > 10
  4273.         && IDENTIFIER_POINTER (name)[0] == '_'
  4274.         && IDENTIFIER_POINTER (name)[1] == '_'
  4275.         && strncmp (IDENTIFIER_POINTER (name)+2, "builtin_", 8) == 0))
  4276.     TREE_OVERLOADED (name) = 1;
  4277. #endif
  4278.     }
  4279.   else if (current_lang_name == lang_name_c)
  4280.     DECL_LANGUAGE (t) = lang_c;
  4281.   else abort ();
  4282.  
  4283. #ifdef GATHER_STATISTICS
  4284.   tree_node_kinds[(int)lang_decl] += 1;
  4285.   tree_node_sizes[(int)lang_decl] += sizeof(struct lang_decl);
  4286. #endif
  4287.  
  4288.   return t;
  4289. }
  4290.  
  4291. tree
  4292. build_lang_field_decl (code, name, type)
  4293.      enum tree_code code;
  4294.      tree name;
  4295.      tree type;
  4296. {
  4297.   extern struct obstack *current_obstack, *saveable_obstack;
  4298.   register tree t = build_decl (code, name, type);
  4299.   struct obstack *obstack = current_obstack;
  4300.   register int i = sizeof (struct lang_decl_flags) / sizeof (int);
  4301.   register int *pi;
  4302.  
  4303.   if (! TREE_PERMANENT (t))
  4304.     obstack = saveable_obstack;
  4305.  
  4306.   pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl_flags));
  4307.   while (i > 0)
  4308.     pi[--i] = 0;
  4309.  
  4310.   DECL_LANG_SPECIFIC (t) = (struct lang_decl *) pi;
  4311.   return t;
  4312. }
  4313.  
  4314. tree
  4315. make_lang_type (code)
  4316.      enum tree_code code;
  4317. {
  4318.   extern struct obstack *current_obstack, *saveable_obstack;
  4319.   register tree t = make_node (code);
  4320.   struct obstack *obstack = current_obstack;
  4321.   register int i = sizeof (struct lang_type) / sizeof (int);
  4322.   register int *pi;
  4323.  
  4324.   if (! TREE_PERMANENT (t))
  4325.     obstack = saveable_obstack;
  4326.  
  4327.   pi = (int *) obstack_alloc (obstack, sizeof (struct lang_type));
  4328.   while (i > 0)
  4329.     pi[--i] = 0;
  4330.  
  4331.   TYPE_LANG_SPECIFIC (t) = (struct lang_type *) pi;
  4332.   CLASSTYPE_MAIN_VARIANT (t) = t;
  4333.   CLASSTYPE_AS_LIST (t) = build_tree_list (NULL_TREE, t);
  4334.   CLASSTYPE_INTERFACE_UNKNOWN (t) = interface_unknown;
  4335.   CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
  4336.  
  4337.   /* Make sure this is laid out, for ease of use later.
  4338.      In the presence of parse errors, the normal was of assuring
  4339.      this might not ever get executed, so we lay it out *immediately*.  */
  4340.   build_pointer_type (t);
  4341.  
  4342. #ifdef GATHER_STATISTICS
  4343.   tree_node_kinds[(int)lang_type] += 1;
  4344.   tree_node_sizes[(int)lang_type] += sizeof(struct lang_type);
  4345. #endif
  4346.  
  4347.   return t;
  4348. }
  4349.  
  4350. void
  4351. copy_decl_lang_specific (decl)
  4352.      tree decl;
  4353. {
  4354.   extern struct obstack *current_obstack, *saveable_obstack;
  4355.   register int *old = (int *)DECL_LANG_SPECIFIC (decl);
  4356.   struct obstack *obstack = current_obstack;
  4357.   register int i = sizeof (struct lang_decl) / sizeof (int);
  4358.   register int *pi;
  4359.  
  4360.   if (! TREE_PERMANENT (decl))
  4361.     obstack = saveable_obstack;
  4362.  
  4363.   pi = (int *) obstack_alloc (obstack, sizeof (struct lang_decl));
  4364.   while (i-- > 0)
  4365.     pi[i] = old[i];
  4366.  
  4367.   DECL_LANG_SPECIFIC (decl) = (struct lang_decl *) pi;
  4368.  
  4369. #ifdef GATHER_STATISTICS
  4370.   tree_node_kinds[(int)lang_decl] += 1;
  4371.   tree_node_sizes[(int)lang_decl] += sizeof(struct lang_decl);
  4372. #endif
  4373. }
  4374.  
  4375. void
  4376. copy_type_lang_specific (type)
  4377.      tree type;
  4378. {
  4379.   extern struct obstack *current_obstack, *saveable_obstack;
  4380.   register int *old = (int *)TYPE_LANG_SPECIFIC (type);
  4381.   struct obstack *obstack = current_obstack;
  4382.   register int i = sizeof (struct lang_type) / sizeof (int);
  4383.   register int *pi;
  4384.  
  4385.   if (! TREE_PERMANENT (type))
  4386.     obstack = saveable_obstack;
  4387.  
  4388.   pi = (int *) obstack_alloc (obstack, sizeof (struct lang_type));
  4389.   while (i-- > 0)
  4390.     pi[i] = old[i];
  4391.  
  4392.   TYPE_LANG_SPECIFIC (type) = (struct lang_type *) pi;
  4393.   CLASSTYPE_AS_LIST (type) = build_tree_list (NULL_TREE, type);
  4394.   if (CLASSTYPE_N_BASECLASSES (type) > 0)
  4395.     CLASSTYPE_BASECLASSES (type) = (tree *)obstack_copy (obstack, CLASSTYPE_BASECLASSES (type), (CLASSTYPE_N_BASECLASSES (type)+1) * sizeof (tree));
  4396.  
  4397. #ifdef GATHER_STATISTICS
  4398.   tree_node_kinds[(int)lang_type] += 1;
  4399.   tree_node_sizes[(int)lang_type] += sizeof(struct lang_type);
  4400. #endif
  4401. }
  4402.  
  4403. tree
  4404. build_with_cleanup (exp, type, rtl)
  4405.      tree exp;
  4406.      tree type;
  4407.      struct rtx_def *rtl;
  4408. {
  4409.   if (type != NULL_TREE || TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (exp)))
  4410.     {
  4411.       tree rval = make_node (WITH_CLEANUP_EXPR);
  4412.  
  4413.       if (type == NULL_TREE)
  4414.     type = TREE_TYPE (exp);
  4415.  
  4416.       TREE_OPERAND (rval, 0) = exp;
  4417.       TREE_OPERAND (rval, 1) = make_node (RTL_EXPR);
  4418.       TREE_OPERAND (rval, 2) = build_delete (TYPE_POINTER_TO (type),
  4419.                          build1 (ADDR_EXPR, TYPE_POINTER_TO (type), TREE_OPERAND (rval, 1)),
  4420.                          integer_two_node, LOOKUP_NORMAL, 0);
  4421.       if (rtl != 0)
  4422.     RTL_EXPR_RTL (TREE_OPERAND (rval, 1)) = rtl;
  4423.       if (TREE_CODE (exp) == CALL_EXPR
  4424.       && TREE_VALUE (TREE_OPERAND (exp, 1)) == NULL_TREE)
  4425.     TREE_VALUE (TREE_OPERAND (exp, 1)) = TREE_OPERAND (rval, 1);
  4426.       TREE_TYPE (rval) = type;
  4427.       return rval;
  4428.     }
  4429.   return NULL_TREE;
  4430. }
  4431.  
  4432. void
  4433. dump_time_statistics ()
  4434. {
  4435.   register tree prev = 0, decl, next;
  4436.   int this_time = my_gettime ();
  4437.   TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time))
  4438.     += this_time - body_time;
  4439.  
  4440.   fprintf (stderr, "\n******\n");
  4441.   print_time ("header files (total)", header_time);
  4442.   print_time ("main file (total)", this_time - body_time);
  4443.   fprintf (stderr, "ratio = %g : 1\n",
  4444.        (double)header_time / (double)(this_time - body_time));
  4445.   fprintf (stderr, "\n******\n");
  4446.  
  4447.   for (decl = filename_times; decl; decl = next)
  4448.     {
  4449.       next = IDENTIFIER_GLOBAL_VALUE (decl);
  4450.       IDENTIFIER_GLOBAL_VALUE (decl) = prev;
  4451.       prev = decl;
  4452.     }
  4453.  
  4454.   for (decl = prev; decl; decl = IDENTIFIER_GLOBAL_VALUE (decl))
  4455.     print_time (IDENTIFIER_POINTER (decl),
  4456.         TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (decl)));
  4457. }
  4458.  
  4459. void
  4460. compiler_error (s, v, v2)
  4461.      char *s;
  4462.      int v, v2;            /* @@also used as pointer */
  4463. {
  4464.   char buf[1024];
  4465.   sprintf (buf, s, v, v2);
  4466.   error_with_file_and_line (input_filename, lineno, "%s (compiler error)", buf);
  4467. }
  4468.  
  4469. void
  4470. compiler_error_with_decl (decl, s)
  4471.      tree decl;
  4472.      char *s;
  4473. {
  4474.   char *name;
  4475.   count_error (0);
  4476.  
  4477.   report_error_function (0);
  4478.  
  4479.   if (TREE_CODE (decl) == PARM_DECL)
  4480.     fprintf (stderr, "%s:%d: ",
  4481.          DECL_SOURCE_FILE (DECL_CONTEXT (decl)),
  4482.          DECL_SOURCE_LINE (DECL_CONTEXT (decl)));
  4483.   else
  4484.     fprintf (stderr, "%s:%d: ",
  4485.          DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
  4486.  
  4487.   name = lang_printable_name (decl);
  4488.   if (name)
  4489.     fprintf (stderr, s, name);
  4490.   else
  4491.     fprintf (stderr, s, "((anonymous))");
  4492.   fprintf (stderr, " (compiler error)\n");
  4493. }
  4494.