/* Lists of symbols for Bison Copyright (C) 2002, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc. This file is part of Bison, the GNU Compiler Compiler. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include "system.h" #include "complain.h" #include "symlist.h" /*--------------------------------------. | Create a list containing SYM at LOC. | `--------------------------------------*/ symbol_list * symbol_list_sym_new (symbol *sym, location loc) { symbol_list *res = xmalloc (sizeof *res); res->content_type = SYMLIST_SYMBOL; res->content.sym = sym; res->location = res->sym_loc = loc; res->midrule = NULL; res->midrule_parent_rule = NULL; res->midrule_parent_rhs_index = 0; code_props_none_init (&res->action_props); res->ruleprec = NULL; res->dprec = 0; res->merger = 0; res->named_ref = NULL; res->next = NULL; return res; } /*--------------------------------------------. | Create a list containing TYPE_NAME at LOC. | `--------------------------------------------*/ symbol_list * symbol_list_type_new (uniqstr type_name, location loc) { symbol_list *res = xmalloc (sizeof *res); res->content_type = SYMLIST_TYPE; res->content.type_name = type_name; res->location = res->sym_loc = loc; res->named_ref = NULL; res->next = NULL; return res; } /*----------------------------------------. | Create a list containing a <*> at LOC. | `----------------------------------------*/ symbol_list * symbol_list_default_tagged_new (location loc) { symbol_list *res = xmalloc (sizeof *res); res->content_type = SYMLIST_DEFAULT_TAGGED; res->location = res->sym_loc = loc; res->named_ref = NULL; res->next = NULL; return res; } /*---------------------------------------. | Create a list containing a <> at LOC. | `---------------------------------------*/ symbol_list * symbol_list_default_tagless_new (location loc) { symbol_list *res = xmalloc (sizeof *res); res->content_type = SYMLIST_DEFAULT_TAGLESS; res->location = res->sym_loc = loc; res->named_ref = NULL; res->next = NULL; return res; } /*-----------------------------------------------------------------------. | Print this list, for which every content_type must be SYMLIST_SYMBOL. | `-----------------------------------------------------------------------*/ void symbol_list_syms_print (const symbol_list *l, FILE *f) { for (/* Nothing. */; l && l->content.sym; l = l->next) { symbol_print (l->content.sym, f); fprintf (stderr, l->action_props.is_value_used ? " used" : " unused"); if (l && l->content.sym) fprintf (f, ", "); } } /*---------------------------. | Prepend NODE to the LIST. | `---------------------------*/ symbol_list * symbol_list_prepend (symbol_list *list, symbol_list *node) { node->next = list; return node; } /*-----------------------------------------------. | Free the LIST, but not the items it contains. | `-----------------------------------------------*/ void symbol_list_free (symbol_list *list) { symbol_list *node, *next; for (node = list; node; node = next) { next = node->next; if (node->named_ref) named_ref_free (node->named_ref); free (node); } } /*--------------------. | Return its length. | `--------------------*/ int symbol_list_length (symbol_list const *l) { int res = 0; for (/* Nothing. */; l && !(l->content_type == SYMLIST_SYMBOL && l->content.sym == NULL); l = l->next) ++res; return res; } /*------------------------------. | Get item N in symbol list L. | `------------------------------*/ symbol_list * symbol_list_n_get (symbol_list *l, int n) { int i; if (n < 0) return NULL; for (i = 0; i < n; ++i) { l = l->next; if (l == NULL || (l->content_type == SYMLIST_SYMBOL && l->content.sym == NULL)) return NULL; } return l; } /*--------------------------------------------------------------. | Get the data type (alternative in the union) of the value for | | symbol N in symbol list L. | `--------------------------------------------------------------*/ uniqstr symbol_list_n_type_name_get (symbol_list *l, location loc, int n) { l = symbol_list_n_get (l, n); if (!l) { complain_at (loc, _("invalid $ value: $%d"), n); return NULL; } aver (l->content_type == SYMLIST_SYMBOL); return l->content.sym->type_name; } bool symbol_list_null (symbol_list *node) { return !node || (node->content_type == SYMLIST_SYMBOL && !(node->content.sym)); } void symbol_list_destructor_set (symbol_list *node, char const *code, location loc) { code_props destructor; code_props_symbol_action_init (&destructor, code, loc); code_props_translate_code (&destructor); switch (node->content_type) { case SYMLIST_SYMBOL: symbol_destructor_set (node->content.sym, &destructor); break; case SYMLIST_TYPE: semantic_type_destructor_set ( semantic_type_get (node->content.type_name), &destructor); break; case SYMLIST_DEFAULT_TAGGED: default_tagged_destructor_set (&destructor); break; case SYMLIST_DEFAULT_TAGLESS: default_tagless_destructor_set (&destructor); break; } } void symbol_list_printer_set (symbol_list *node, char const *code, location loc) { code_props printer; code_props_symbol_action_init (&printer, code, loc); code_props_translate_code (&printer); switch (node->content_type) { case SYMLIST_SYMBOL: symbol_printer_set (node->content.sym, &printer); break; case SYMLIST_TYPE: semantic_type_printer_set ( semantic_type_get (node->content.type_name), &printer); break; case SYMLIST_DEFAULT_TAGGED: default_tagged_printer_set (&printer); break; case SYMLIST_DEFAULT_TAGLESS: default_tagless_printer_set (&printer); break; } }