1 /* Symbol table manager for Bison. 
   3    Copyright (C) 1984, 1989, 2000, 2001, 2002, 2004, 2005, 2006 Free 
   4    Software Foundation, Inc. 
   6    This file is part of Bison, the GNU Compiler Compiler. 
   8    Bison is free software; you can redistribute it and/or modify 
   9    it under the terms of the GNU General Public License as published by 
  10    the Free Software Foundation; either version 2, or (at your option) 
  13    Bison is distributed in the hope that it will be useful, 
  14    but WITHOUT ANY WARRANTY; without even the implied warranty of 
  15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  16    GNU General Public License for more details. 
  18    You should have received a copy of the GNU General Public License 
  19    along with Bison; see the file COPYING.  If not, write to 
  20    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
  21    Boston, MA 02110-1301, USA.  */ 
  33 /*------------------------. 
  34 | Distinguished symbols.  | 
  35 `------------------------*/ 
  37 symbol 
*errtoken 
= NULL
; 
  38 symbol 
*undeftoken 
= NULL
; 
  39 symbol 
*endtoken 
= NULL
; 
  40 symbol 
*accept 
= NULL
; 
  41 symbol 
*startsymbol 
= NULL
; 
  42 location startsymbol_location
; 
  44 /*-----------------------------------. 
  45 | Default %destructor and %printer.  | 
  46 `-----------------------------------*/ 
  48 static const char *default_destructor 
= NULL
; 
  49 static location default_destructor_location
; 
  50 static const char *default_printer 
= NULL
; 
  51 static location default_printer_location
; 
  53 /*---------------------------------. 
  54 | Create a new symbol, named TAG.  | 
  55 `---------------------------------*/ 
  58 symbol_new (uniqstr tag
, location loc
) 
  60   symbol 
*res 
= xmalloc (sizeof *res
); 
  66   res
->type_name 
= NULL
; 
  67   res
->destructor 
= NULL
; 
  70   res
->number 
= NUMBER_UNDEFINED
; 
  72   res
->assoc 
= undef_assoc
; 
  73   res
->user_token_number 
= USER_NUMBER_UNDEFINED
; 
  76   res
->class = unknown_sym
; 
  77   res
->declared 
= false; 
  79   if (nsyms 
== SYMBOL_NUMBER_MAXIMUM
) 
  80     fatal (_("too many symbols in input grammar (limit is %d)"), 
  81            SYMBOL_NUMBER_MAXIMUM
); 
  86 /*----------------------------------------. 
  87 | Create a new semantic type, named TAG.  | 
  88 `----------------------------------------*/ 
  90 static semantic_type 
* 
  91 semantic_type_new (uniqstr tag
) 
  93   semantic_type 
*res 
= xmalloc (sizeof *res
); 
  97   res
->destructor 
= NULL
; 
 108 #define SYMBOL_ATTR_PRINT(Attr)                         \ 
 110     fprintf (f, " %s { %s }", #Attr, s->Attr) 
 113 symbol_print (symbol 
*s
, FILE *f
) 
 117       fprintf (f
, "\"%s\"", s
->tag
); 
 118       SYMBOL_ATTR_PRINT (type_name
); 
 119       SYMBOL_ATTR_PRINT (destructor
); 
 120       SYMBOL_ATTR_PRINT (printer
); 
 123     fprintf (f
, "<NULL>"); 
 126 #undef SYMBOL_ATTR_PRINT 
 128 /*------------------------------------------------------------------. 
 129 | Complain that S's WHAT is redeclared at SECOND, and was first set | 
 131 `------------------------------------------------------------------*/ 
 134 symbol_redeclaration (symbol 
*s
, const char *what
, location first
, 
 137   complain_at (second
, _("%s redeclaration for %s"), what
, s
->tag
); 
 138   complain_at (first
, _("previous declaration")); 
 142 semantic_type_redeclaration (semantic_type 
*s
, const char *what
, location first
, 
 145   complain_at (second
, _("%s redeclaration for <%s>"), what
, s
->tag
); 
 146   complain_at (first
, _("previous declaration")); 
 150 /*-----------------------------------------------------------------. 
 151 | Set the TYPE_NAME associated with SYM.  Does nothing if passed 0 | 
 153 `-----------------------------------------------------------------*/ 
 156 symbol_type_set (symbol 
*sym
, uniqstr type_name
, location loc
) 
 161         symbol_redeclaration (sym
, "%type", sym
->type_location
, loc
); 
 162       uniqstr_assert (type_name
); 
 163       sym
->type_name 
= type_name
; 
 164       sym
->type_location 
= loc
; 
 169 /*------------------------------------------------------------------. 
 170 | Set the DESTRUCTOR associated with SYM.  Do nothing if passed 0.  | 
 171 `------------------------------------------------------------------*/ 
 174 symbol_destructor_set (symbol 
*sym
, const char *destructor
, location loc
) 
 179         symbol_redeclaration (sym
, "%destructor", sym
->destructor_location
, 
 181       sym
->destructor 
= destructor
; 
 182       sym
->destructor_location 
= loc
; 
 186 /*-------------------------------------------------------------------. 
 187 | Set the DESTRUCTOR associated with TYPE.  Do nothing if passed 0.  | 
 188 `-------------------------------------------------------------------*/ 
 191 semantic_type_destructor_set (semantic_type 
*type
, const char *destructor
, 
 196       if (type
->destructor
) 
 197         semantic_type_redeclaration (type
, "%destructor", 
 198                                      type
->destructor_location
, loc
); 
 199       type
->destructor 
= destructor
; 
 200       type
->destructor_location 
= loc
; 
 204 /*---------------------------------------. 
 205 | Get the computed %destructor for SYM.  | 
 206 `---------------------------------------*/ 
 209 symbol_destructor_get (symbol 
*sym
) 
 211   /* Per-symbol %destructor.  */ 
 212   if (sym
->destructor 
!= NULL
) 
 213     return sym
->destructor
; 
 215   /* Per-type %destructor.  */ 
 218       semantic_type 
*type 
= semantic_type_get (sym
->type_name
); 
 219       if (type
->destructor
) 
 220         return type
->destructor
; 
 223   /* Apply the default %destructor only to user-defined symbols.  */ 
 224   if (sym
->tag
[0] == '$' || sym 
== errtoken
) 
 226   return default_destructor
; 
 229 /*---------------------------------------------------------------. 
 230 | Get the grammar location of the %destructor computed for SYM.  | 
 231 `---------------------------------------------------------------*/ 
 234 symbol_destructor_location_get (symbol 
*sym
) 
 236   if (sym
->destructor 
!= NULL
) 
 237     return sym
->destructor_location
; 
 240       semantic_type 
*type 
= semantic_type_get (sym
->type_name
); 
 241       if (type
->destructor
) 
 242         return type
->destructor_location
; 
 244   return default_destructor_location
; 
 247 /*---------------------------------------------------------------. 
 248 | Set the PRINTER associated with SYM.  Do nothing if passed 0.  | 
 249 `---------------------------------------------------------------*/ 
 252 symbol_printer_set (symbol 
*sym
, const char *printer
, location loc
) 
 257         symbol_redeclaration (sym
, "%printer", sym
->printer_location
, loc
); 
 258       sym
->printer 
= printer
; 
 259       sym
->printer_location 
= loc
; 
 263 /*----------------------------------------------------------------. 
 264 | Set the PRINTER associated with TYPE.  Do nothing if passed 0.  | 
 265 `----------------------------------------------------------------*/ 
 268 semantic_type_printer_set (semantic_type 
*type
, const char *printer
, 
 274         semantic_type_redeclaration (type
, "%printer", type
->printer_location
, 
 276       type
->printer 
= printer
; 
 277       type
->printer_location 
= loc
; 
 281 /*------------------------------------. 
 282 | Get the computed %printer for SYM.  | 
 283 `------------------------------------*/ 
 286 symbol_printer_get (symbol 
*sym
) 
 288   /* Per-symbol %printer.  */ 
 289   if (sym
->printer 
!= NULL
) 
 292   /* Per-type %printer.  */ 
 295       semantic_type 
*type 
= semantic_type_get (sym
->type_name
); 
 297         return type
->printer
; 
 300   /* Apply the default %printer only to user-defined symbols.  */ 
 301   if (sym
->tag
[0] == '$' || sym 
== errtoken
) 
 303   return default_printer
; 
 306 /*------------------------------------------------------------. 
 307 | Get the grammar location of the %printer computed for SYM.  | 
 308 `------------------------------------------------------------*/ 
 311 symbol_printer_location_get (symbol 
*sym
) 
 313   if (sym
->printer 
!= NULL
) 
 314     return sym
->printer_location
; 
 317       semantic_type 
*type 
= semantic_type_get (sym
->type_name
); 
 319         return type
->printer_location
; 
 321   return default_printer_location
; 
 325 /*-----------------------------------------------------------------. 
 326 | Set the PRECEDENCE associated with SYM.  Does nothing if invoked | 
 327 | with UNDEF_ASSOC as ASSOC.                                       | 
 328 `-----------------------------------------------------------------*/ 
 331 symbol_precedence_set (symbol 
*sym
, int prec
, assoc a
, location loc
) 
 333   if (a 
!= undef_assoc
) 
 336         symbol_redeclaration (sym
, assoc_to_string (a
), sym
->prec_location
, 
 340       sym
->prec_location 
= loc
; 
 343   /* Only terminals have a precedence. */ 
 344   symbol_class_set (sym
, token_sym
, loc
, false); 
 348 /*------------------------------------. 
 349 | Set the CLASS associated with SYM.  | 
 350 `------------------------------------*/ 
 353 symbol_class_set (symbol 
*sym
, symbol_class 
class, location loc
, bool declaring
) 
 355   if (sym
->class != unknown_sym 
&& sym
->class != class) 
 357       complain_at (loc
, _("symbol %s redefined"), sym
->tag
); 
 358       sym
->declared 
= false; 
 361   if (class == nterm_sym 
&& sym
->class != nterm_sym
) 
 362     sym
->number 
= nvars
++; 
 363   else if (class == token_sym 
&& sym
->number 
== NUMBER_UNDEFINED
) 
 364     sym
->number 
= ntokens
++; 
 371         warn_at (loc
, _("symbol %s redeclared"), sym
->tag
); 
 372       sym
->declared 
= true; 
 377 /*------------------------------------------------. 
 378 | Set the USER_TOKEN_NUMBER associated with SYM.  | 
 379 `------------------------------------------------*/ 
 382 symbol_user_token_number_set (symbol 
*sym
, int user_token_number
, location loc
) 
 384   int *user_token_numberp
; 
 386   aver (sym
->class == token_sym
); 
 388   if (sym
->user_token_number 
!= USER_NUMBER_ALIAS
) 
 389     user_token_numberp 
= &sym
->user_token_number
; 
 391     user_token_numberp 
= &sym
->alias
->user_token_number
; 
 392   if (*user_token_numberp 
!= USER_NUMBER_UNDEFINED
 
 393       && *user_token_numberp 
!= user_token_number
) 
 394     complain_at (loc
, _("redefining user token number of %s"), sym
->tag
); 
 396   *user_token_numberp 
= user_token_number
; 
 397   /* User defined $end token? */ 
 398   if (user_token_number 
== 0) 
 401       endtoken
->number 
= 0; 
 402       /* It is always mapped to 0, so it was already counted in 
 409 /*----------------------------------------------------------. 
 410 | If SYM is not defined, report an error, and consider it a | 
 412 `----------------------------------------------------------*/ 
 415 symbol_check_defined (symbol 
*sym
) 
 417   if (sym
->class == unknown_sym
) 
 421          _("symbol %s is used, but is not defined as a token and has no rules"), 
 423       sym
->class = nterm_sym
; 
 424       sym
->number 
= nvars
++; 
 431 symbol_check_defined_processor (void *sym
, void *null ATTRIBUTE_UNUSED
) 
 433   return symbol_check_defined (sym
); 
 437 /*------------------------------------------------------------------. 
 438 | Declare the new symbol SYM.  Make it an alias of SYMVAL, and type | 
 439 | SYMVAL with SYM's type.                                           | 
 440 `------------------------------------------------------------------*/ 
 443 symbol_make_alias (symbol 
*sym
, symbol 
*symval
, location loc
) 
 446     warn_at (loc
, _("symbol `%s' used more than once as a literal string"), 
 449     warn_at (loc
, _("symbol `%s' given more than one literal string"), 
 453       symval
->class = token_sym
; 
 454       symval
->user_token_number 
= sym
->user_token_number
; 
 455       sym
->user_token_number 
= USER_NUMBER_ALIAS
; 
 458       symval
->number 
= sym
->number
; 
 459       symbol_type_set (symval
, sym
->type_name
, loc
); 
 464 /*---------------------------------------------------------. 
 465 | Check that THIS, and its alias, have same precedence and | 
 467 `---------------------------------------------------------*/ 
 470 symbol_check_alias_consistency (symbol 
*this) 
 472   symbol 
*alias 
= this; 
 473   symbol 
*orig  
= this->alias
; 
 475   /* Check only those that _are_ the aliases.  */ 
 476   if (!(this->alias 
&& this->user_token_number 
== USER_NUMBER_ALIAS
)) 
 479   if (orig
->type_name 
!= alias
->type_name
) 
 482         symbol_type_set (alias
, orig
->type_name
, orig
->type_location
); 
 484         symbol_type_set (orig
, alias
->type_name
, alias
->type_location
); 
 488   if (orig
->destructor 
|| alias
->destructor
) 
 490       if (orig
->destructor
) 
 491         symbol_destructor_set (alias
, orig
->destructor
, 
 492                                orig
->destructor_location
); 
 494         symbol_destructor_set (orig
, alias
->destructor
, 
 495                                alias
->destructor_location
); 
 498   if (orig
->printer 
|| alias
->printer
) 
 501         symbol_printer_set (alias
, orig
->printer
, orig
->printer_location
); 
 503         symbol_printer_set (orig
, alias
->printer
, alias
->printer_location
); 
 506   if (alias
->prec 
|| orig
->prec
) 
 509         symbol_precedence_set (alias
, orig
->prec
, orig
->assoc
, 
 510                                orig
->prec_location
); 
 512         symbol_precedence_set (orig
, alias
->prec
, alias
->assoc
, 
 513                                alias
->prec_location
); 
 518 symbol_check_alias_consistency_processor (void *this, 
 519                                           void *null ATTRIBUTE_UNUSED
) 
 521   symbol_check_alias_consistency (this); 
 526 /*-------------------------------------------------------------------. 
 527 | Assign a symbol number, and write the definition of the token name | 
 528 | into FDEFINES.  Put in SYMBOLS.                                    | 
 529 `-------------------------------------------------------------------*/ 
 532 symbol_pack (symbol 
*this) 
 534   if (this->class == nterm_sym
) 
 536       this->number 
+= ntokens
; 
 538   else if (this->alias
) 
 540       /* This symbol and its alias are a single token defn. 
 541          Allocate a tokno, and assign to both check agreement of 
 542          prec and assoc fields and make both the same */ 
 543       if (this->number 
== NUMBER_UNDEFINED
) 
 545           if (this == endtoken 
|| this->alias 
== endtoken
) 
 546             this->number 
= this->alias
->number 
= 0; 
 549               aver (this->alias
->number 
!= NUMBER_UNDEFINED
); 
 550               this->number 
= this->alias
->number
; 
 553       /* Do not do processing below for USER_NUMBER_ALIASes.  */ 
 554       if (this->user_token_number 
== USER_NUMBER_ALIAS
) 
 557   else /* this->class == token_sym */ 
 558     aver (this->number 
!= NUMBER_UNDEFINED
); 
 560   symbols
[this->number
] = this; 
 565 symbol_pack_processor (void *this, void *null ATTRIBUTE_UNUSED
) 
 567   return symbol_pack (this); 
 573 /*--------------------------------------------------. 
 574 | Put THIS in TOKEN_TRANSLATIONS if it is a token.  | 
 575 `--------------------------------------------------*/ 
 578 symbol_translation (symbol 
*this) 
 581   if (this->class == token_sym
 
 582       && this->user_token_number 
!= USER_NUMBER_ALIAS
) 
 584       /* A token which translation has already been set? */ 
 585       if (token_translations
[this->user_token_number
] != undeftoken
->number
) 
 586         complain_at (this->location
, 
 587                      _("tokens %s and %s both assigned number %d"), 
 588                      symbols
[token_translations
[this->user_token_number
]]->tag
, 
 589                      this->tag
, this->user_token_number
); 
 591       token_translations
[this->user_token_number
] = this->number
; 
 598 symbol_translation_processor (void *this, void *null ATTRIBUTE_UNUSED
) 
 600   return symbol_translation (this); 
 604 /*---------------------------------------. 
 605 | Symbol and semantic type hash tables.  | 
 606 `---------------------------------------*/ 
 608 /* Initial capacity of symbol and semantic type hash table.  */ 
 609 #define HT_INITIAL_CAPACITY 257 
 611 static struct hash_table 
*symbol_table 
= NULL
; 
 612 static struct hash_table 
*semantic_type_table 
= NULL
; 
 615 hash_compare_symbol (const symbol 
*m1
, const symbol 
*m2
) 
 617   /* Since tags are unique, we can compare the pointers themselves.  */ 
 618   return UNIQSTR_EQ (m1
->tag
, m2
->tag
); 
 622 hash_compare_semantic_type (const semantic_type 
*m1
, const semantic_type 
*m2
) 
 624   /* Since names are unique, we can compare the pointers themselves.  */ 
 625   return UNIQSTR_EQ (m1
->tag
, m2
->tag
); 
 629 hash_symbol_comparator (void const *m1
, void const *m2
) 
 631   return hash_compare_symbol (m1
, m2
); 
 635 hash_semantic_type_comparator (void const *m1
, void const *m2
) 
 637   return hash_compare_semantic_type (m1
, m2
); 
 641 hash_symbol (const symbol 
*m
, size_t tablesize
) 
 643   /* Since tags are unique, we can hash the pointer itself.  */ 
 644   return ((uintptr_t) m
->tag
) % tablesize
; 
 648 hash_semantic_type (const semantic_type 
*m
, size_t tablesize
) 
 650   /* Since names are unique, we can hash the pointer itself.  */ 
 651   return ((uintptr_t) m
->tag
) % tablesize
; 
 655 hash_symbol_hasher (void const *m
, size_t tablesize
) 
 657   return hash_symbol (m
, tablesize
); 
 661 hash_semantic_type_hasher (void const *m
, size_t tablesize
) 
 663   return hash_semantic_type (m
, tablesize
); 
 666 /*-------------------------------. 
 667 | Create the symbol hash table.  | 
 668 `-------------------------------*/ 
 673   symbol_table 
= hash_initialize (HT_INITIAL_CAPACITY
, 
 676                                   hash_symbol_comparator
, 
 678   semantic_type_table 
= hash_initialize (HT_INITIAL_CAPACITY
, 
 680                                          hash_semantic_type_hasher
, 
 681                                          hash_semantic_type_comparator
, 
 686 /*----------------------------------------------------------------. 
 687 | Find the symbol named KEY, and return it.  If it does not exist | 
 689 `----------------------------------------------------------------*/ 
 692 symbol_from_uniqstr (const uniqstr key
, location loc
) 
 698   entry 
= hash_lookup (symbol_table
, &probe
); 
 702       /* First insertion in the hash. */ 
 703       entry 
= symbol_new (key
, loc
); 
 704       hash_insert (symbol_table
, entry
); 
 710 /*-----------------------------------------------------------------------. 
 711 | Find the semantic type named KEY, and return it.  If it does not exist | 
 713 `-----------------------------------------------------------------------*/ 
 716 semantic_type_from_uniqstr (const uniqstr key
) 
 719   semantic_type 
*entry
; 
 722   entry 
= hash_lookup (semantic_type_table
, &probe
); 
 726       /* First insertion in the hash. */ 
 727       entry 
= semantic_type_new (key
); 
 728       hash_insert (semantic_type_table
, entry
); 
 734 /*----------------------------------------------------------------. 
 735 | Find the symbol named KEY, and return it.  If it does not exist | 
 737 `----------------------------------------------------------------*/ 
 740 symbol_get (const char *key
, location loc
) 
 742   return symbol_from_uniqstr (uniqstr_new (key
), loc
); 
 746 /*-----------------------------------------------------------------------. 
 747 | Find the semantic type named KEY, and return it.  If it does not exist | 
 749 `-----------------------------------------------------------------------*/ 
 752 semantic_type_get (const char *key
) 
 754   return semantic_type_from_uniqstr (uniqstr_new (key
)); 
 758 /*------------------------------------------------------------------. 
 759 | Generate a dummy nonterminal, whose name cannot conflict with the | 
 761 `------------------------------------------------------------------*/ 
 764 dummy_symbol_get (location loc
) 
 766   /* Incremented for each generated symbol.  */ 
 767   static int dummy_count 
= 0; 
 768   static char buf
[256]; 
 772   sprintf (buf
, "$@%d", ++dummy_count
); 
 773   sym 
= symbol_get (buf
, loc
); 
 774   sym
->class = nterm_sym
; 
 775   sym
->number 
= nvars
++; 
 780 symbol_is_dummy (const symbol 
*sym
) 
 782   return sym
->tag
[0] == '@' || (sym
->tag
[0] == '$' && sym
->tag
[1] == '@'); 
 785 /*-------------------. 
 786 | Free the symbols.  | 
 787 `-------------------*/ 
 792   hash_free (symbol_table
); 
 793   hash_free (semantic_type_table
); 
 798 /*---------------------------------------------------------------. 
 799 | Look for undefined symbols, report an error, and consider them | 
 801 `---------------------------------------------------------------*/ 
 804 symbols_do (Hash_processor processor
, void *processor_data
) 
 806   hash_do_for_each (symbol_table
, processor
, processor_data
); 
 810 /*--------------------------------------------------------------. 
 811 | Check that all the symbols are defined.  Report any undefined | 
 812 | symbols and consider them nonterminals.                       | 
 813 `--------------------------------------------------------------*/ 
 816 symbols_check_defined (void) 
 818   symbols_do (symbol_check_defined_processor
, NULL
); 
 821 /*------------------------------------------------------------------. 
 822 | Set TOKEN_TRANSLATIONS.  Check that no two symbols share the same | 
 824 `------------------------------------------------------------------*/ 
 827 symbols_token_translations_init (void) 
 829   bool num_256_available_p 
= true; 
 832   /* Find the highest user token number, and whether 256, the POSIX 
 833      preferred user token number for the error token, is used.  */ 
 834   max_user_token_number 
= 0; 
 835   for (i 
= 0; i 
< ntokens
; ++i
) 
 837       symbol 
*this = symbols
[i
]; 
 838       if (this->user_token_number 
!= USER_NUMBER_UNDEFINED
) 
 840           if (this->user_token_number 
> max_user_token_number
) 
 841             max_user_token_number 
= this->user_token_number
; 
 842           if (this->user_token_number 
== 256) 
 843             num_256_available_p 
= false; 
 847   /* If 256 is not used, assign it to error, to follow POSIX.  */ 
 848   if (num_256_available_p
 
 849       && errtoken
->user_token_number 
== USER_NUMBER_UNDEFINED
) 
 850     errtoken
->user_token_number 
= 256; 
 852   /* Set the missing user numbers. */ 
 853   if (max_user_token_number 
< 256) 
 854     max_user_token_number 
= 256; 
 856   for (i 
= 0; i 
< ntokens
; ++i
) 
 858       symbol 
*this = symbols
[i
]; 
 859       if (this->user_token_number 
== USER_NUMBER_UNDEFINED
) 
 860         this->user_token_number 
= ++max_user_token_number
; 
 861       if (this->user_token_number 
> max_user_token_number
) 
 862         max_user_token_number 
= this->user_token_number
; 
 865   token_translations 
= xnmalloc (max_user_token_number 
+ 1, 
 866                                  sizeof *token_translations
); 
 868   /* Initialize all entries for literal tokens to 2, the internal 
 869      token number for $undefined, which represents all invalid inputs. 
 871   for (i 
= 0; i 
< max_user_token_number 
+ 1; i
++) 
 872     token_translations
[i
] = undeftoken
->number
; 
 873   symbols_do (symbol_translation_processor
, NULL
); 
 877 /*----------------------------------------------------------------. 
 878 | Assign symbol numbers, and write definition of token names into | 
 879 | FDEFINES.  Set up vectors SYMBOL_TABLE, TAGS of symbols.        | 
 880 `----------------------------------------------------------------*/ 
 885   symbols_do (symbol_check_alias_consistency_processor
, NULL
); 
 887   symbols 
= xcalloc (nsyms
, sizeof *symbols
); 
 888   symbols_do (symbol_pack_processor
, NULL
); 
 890   /* Aliases leave empty slots in symbols, so remove them.  */ 
 894     int nsyms_old 
= nsyms
; 
 895     for (writei 
= 0, readi 
= 0; readi 
< nsyms_old
; readi 
+= 1) 
 897         if (symbols
[readi
] == NULL
) 
 904             symbols
[writei
] = symbols
[readi
]; 
 905             symbols
[writei
]->number 
= writei
; 
 906             if (symbols
[writei
]->alias
) 
 907               symbols
[writei
]->alias
->number 
= writei
; 
 912   symbols 
= xnrealloc (symbols
, nsyms
, sizeof *symbols
); 
 914   symbols_token_translations_init (); 
 916   if (startsymbol
->class == unknown_sym
) 
 917     fatal_at (startsymbol_location
, 
 918               _("the start symbol %s is undefined"), 
 920   else if (startsymbol
->class == token_sym
) 
 921     fatal_at (startsymbol_location
, 
 922               _("the start symbol %s is a token"), 
 927 /*-----------------------------------. 
 928 | Set default %destructor/%printer.  | 
 929 `-----------------------------------*/ 
 932 default_destructor_set (const char *destructor
, location loc
) 
 934   if (default_destructor 
!= NULL
) 
 936       complain_at (loc
, _("redeclaration for default %%destructor")); 
 937       complain_at (default_destructor_location
, _("previous declaration")); 
 939   default_destructor 
= destructor
; 
 940   default_destructor_location 
= loc
; 
 944 default_printer_set (const char *printer
, location loc
) 
 946   if (default_printer 
!= NULL
) 
 948       complain_at (loc
, _("redeclaration for default %%printer")); 
 949       complain_at (default_printer_location
, _("previous declaration")); 
 951   default_printer 
= printer
; 
 952   default_printer_location 
= loc
;