(STRUNIQ_EQ, struniq_assert, struniq_assert_p): New.
Use struniq for symbols.
* src/symtab.h (symbol_t): The tag member is a struniq.
(symbol_type_set): Adjust.
* src/symtab.c (symbol_new): Takes a struniq.
(symbol_free): Don't free the tag member.
(hash_compare_symbol_t, hash_symbol_t): Rename as...
(hash_compare_symbol, hash_symbol): these.
Use the fact that tags as struniqs.
(symbol_get): Use struniq_new.
* src/symlist.h, src/symlist.c (symbol_list_n_type_name_get):
Returns a strniq.
* src/reader.h (merger_list, grammar_currentmerge_set): The name
and type members are struniqs.
* src/reader.c (get_merge_function)
(grammar_current_rule_merge_set): Adjust.
(TYPE, current_type): Are struniq.
Use struniq for file names.
* src/files.h, src/files.c (infile): Split into...
(grammar_file, current_file): these.
* src/scan-gram.c (YY_USER_INIT, handle_syncline): Adjust.
* src/reduce.c (reduce_print): Likewise.
* src/getargs.c (getargs): Likewise.
* src/complain.h, src/complain.c: Likewise.
* src/main.c (main): Call struniqs_new early enough to use it for
file names.
Don't free the input file name.
2002-11-12 Akim Demaille <akim@epita.fr>
+ * src/struniq.h, src/struniq.c (struniq_t): Is const.
+ (STRUNIQ_EQ, struniq_assert, struniq_assert_p): New.
+
+ Use struniq for symbols.
+
+ * src/symtab.h (symbol_t): The tag member is a struniq.
+ (symbol_type_set): Adjust.
+ * src/symtab.c (symbol_new): Takes a struniq.
+ (symbol_free): Don't free the tag member.
+ (hash_compare_symbol_t, hash_symbol_t): Rename as...
+ (hash_compare_symbol, hash_symbol): these.
+ Use the fact that tags as struniqs.
+ (symbol_get): Use struniq_new.
+ * src/symlist.h, src/symlist.c (symbol_list_n_type_name_get):
+ Returns a strniq.
+ * src/reader.h (merger_list, grammar_currentmerge_set): The name
+ and type members are struniqs.
+ * src/reader.c (get_merge_function)
+ (grammar_current_rule_merge_set): Adjust.
+ (TYPE, current_type): Are struniq.
+
+ Use struniq for file names.
+
+ * src/files.h, src/files.c (infile): Split into...
+ (grammar_file, current_file): these.
+ * src/scan-gram.c (YY_USER_INIT, handle_syncline): Adjust.
+ * src/reduce.c (reduce_print): Likewise.
+ * src/getargs.c (getargs): Likewise.
+ * src/complain.h, src/complain.c: Likewise.
+ * src/main.c (main): Call struniqs_new early enough to use it for
+ file names.
+ Don't free the input file name.
+
+2002-11-12 Akim Demaille <akim@epita.fr>
+
* src/symtab.c (symbol_free): Remove dead deactivated code:
type_name are properly removed.
Don't use XFREE to free items that cannot be NULL.
va_list args;
fflush (stdout);
- fprintf (stderr, "%s: %s", infile ? infile : program_name, _("warning: "));
+ fprintf (stderr, "%s: %s", current_file ? current_file : program_name, _("warning: "));
va_start (args, message);
vfprintf (stderr, message, args);
va_list args;
fflush (stdout);
- fprintf (stderr, "%s: ", infile ? infile : program_name);
+ fprintf (stderr, "%s: ", current_file ? current_file : program_name);
va_start (args, message);
vfprintf (stderr, message, args);
va_list args;
fflush (stdout);
- fprintf (stderr, "%s: ", infile ? infile : program_name);
+ fprintf (stderr, "%s: ", current_file ? current_file : program_name);
fputs (_("fatal error: "), stderr);
__attribute__ ((__noreturn__, __format__ (__printf__, 2, 3)));
/* Position in the current input file. */
-extern char *infile;
+extern const char *current_file;
/* This variable is set each time `warn' is called. */
extern bool warning_issued;
char *spec_defines_file = NULL; /* for --defines. */
char *parser_file_name = NULL;
-char *infile = NULL;
+struniq_t grammar_file = NULL;
+struniq_t current_file = NULL;
static char *full_base_name = NULL;
{
/* Otherwise, the short base name is computed from the input
grammar: `foo/bar.yy' => `bar'. */
- filename_split (infile, &base, &tab, &ext);
+ filename_split (grammar_file, &base, &tab, &ext);
short_base_name =
xstrndup (base,
(strlen (base) - (ext ? strlen (ext) : 0)));
stpcpy (stpcpy (full_base_name, short_base_name), EXT_TAB);
/* Computes the extensions from the grammar file name. */
- filename_split (infile, &base, &tab, &ext);
+ filename_split (grammar_file, &base, &tab, &ext);
if (ext && !yacc_flag)
compute_exts_from_gf (ext);
}
#ifndef FILES_H_
# define FILES_H_
+# include "struniq.h"
+
/* File name specified with -o for the output file, or 0 if no -o. */
extern char *spec_outfile;
extern struct obstack pre_prologue_obstack;
extern struct obstack post_prologue_obstack;
-extern char *infile;
+/* The file name as given on the command line.
+ Not named "input_file" because Flex uses this name for an argument,
+ and therefore GCC warns about a name clash. */
+extern struniq_t grammar_file;
+
+/* The current file name. Might change with %include, or with #line. */
+extern struniq_t current_file;
void compute_output_file_names (void);
#include "argmatch.h"
#include "error.h"
#include "complain.h"
+#include "struniq.h"
#include "getargs.h"
#include "files.h"
usage (EXIT_FAILURE);
}
- infile = xstrdup (argv[optind]);
+ current_file = grammar_file = struniq_new (argv[optind]);
}
(void) bindtextdomain (PACKAGE, LOCALEDIR);
(void) textdomain (PACKAGE);
+ struniqs_new ();
+
getargs (argc, argv);
time_report = trace_flag & trace_time;
if (trace_flag & trace_bitsets)
bitset_stats_enable ();
- struniqs_new ();
muscle_init ();
/* Read the input. Copy some parts of it to FGUARD, FACTION, FTABLE
reduce_free ();
conflicts_free ();
grammar_free ();
- /* FIXME: We are leaking all the other file names. */
- free (infile);
/* The scanner memory cannot be released right after parsing, as it
contains things such as user actions, prologue, epilogue etc. */
/* Version and input file. */
MUSCLE_INSERT_STRING ("version", VERSION);
- MUSCLE_INSERT_C_STRING ("filename", infile);
+ MUSCLE_INSERT_C_STRING ("filename", grammar_file);
}
/*-------------------------------------------------------------.
| Prepare the muscles related to the rules: rhs, prhs, r1, r2, |
-| rline, dprec, merger |
+| rline, dprec, merger. |
`-------------------------------------------------------------*/
static void
rhs[i++] = -1;
/* Line where rule was defined. */
rline[r] = rules[r].location.first_line;
- /* Dynamic precedence (GLR) */
+ /* Dynamic precedence (GLR). */
dprec[r] = rules[r].dprec;
- /* Merger-function index (GLR) */
+ /* Merger-function index (GLR). */
merger[r] = rules[r].merger;
}
assert (i == nritems);
static void yyprint (FILE *file, int type, const yystype *value);
symbol_class current_class = unknown_sym;
-char *current_type = 0;
+struniq_t current_type = 0;
symbol_t *current_lhs;
location_t current_lhs_location;
assoc_t current_assoc;
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const unsigned short yyrline[] =
{
- 0, 168, 168, 181, 183, 186, 188, 189, 190, 191,
- 192, 193, 194, 195, 196, 198, 199, 200, 201, 202,
- 204, 205, 206, 207, 208, 211, 213, 214, 218, 225,
- 224, 235, 234, 247, 246, 252, 252, 257, 266, 281,
- 283, 284, 287, 289, 294, 296, 300, 305, 310, 316,
- 322, 332, 335, 344, 346, 352, 354, 359, 366, 365,
- 370, 372, 375, 378, 380, 382, 384, 386, 390, 392,
- 395, 401, 410, 418, 423, 429, 431
+ 0, 169, 169, 182, 184, 187, 189, 190, 191, 192,
+ 193, 194, 195, 196, 197, 199, 200, 201, 202, 203,
+ 205, 206, 207, 208, 209, 212, 214, 215, 219, 226,
+ 225, 236, 235, 248, 247, 253, 253, 258, 267, 282,
+ 284, 285, 288, 290, 295, 297, 301, 306, 311, 317,
+ 323, 333, 336, 345, 347, 353, 355, 360, 367, 366,
+ 371, 373, 376, 379, 381, 383, 385, 387, 391, 393,
+ 396, 402, 411, 419, 424, 430, 432
};
#endif
switch (yyn)
{
case 2:
-#line 170 "parse-gram.y"
+#line 171 "parse-gram.y"
{
yycontrol->errcode = 0;
epilogue_set (yyvsp[0].string, yylsp[0]);
break;
case 6:
-#line 188 "parse-gram.y"
+#line 189 "parse-gram.y"
{ prologue_augment (yyvsp[0].string, yylsp[0]); }
break;
case 7:
-#line 189 "parse-gram.y"
+#line 190 "parse-gram.y"
{ debug_flag = 1; }
break;
case 8:
-#line 190 "parse-gram.y"
+#line 191 "parse-gram.y"
{ muscle_insert (yyvsp[-1].string, yyvsp[0].string); }
break;
case 9:
-#line 191 "parse-gram.y"
+#line 192 "parse-gram.y"
{ defines_flag = 1; }
break;
case 10:
-#line 192 "parse-gram.y"
+#line 193 "parse-gram.y"
{ error_verbose = 1; }
break;
case 11:
-#line 193 "parse-gram.y"
+#line 194 "parse-gram.y"
{ expected_conflicts = yyvsp[0].integer; }
break;
case 12:
-#line 194 "parse-gram.y"
+#line 195 "parse-gram.y"
{ spec_file_prefix = yyvsp[0].string; }
break;
case 13:
-#line 195 "parse-gram.y"
+#line 196 "parse-gram.y"
{ glr_parser = 1; }
break;
case 14:
-#line 197 "parse-gram.y"
+#line 198 "parse-gram.y"
{ muscle_pair_list_grow ("lex_param", yyvsp[-2].string, yyvsp[0].string); }
break;
case 15:
-#line 198 "parse-gram.y"
+#line 199 "parse-gram.y"
{ locations_flag = 1; }
break;
case 16:
-#line 199 "parse-gram.y"
+#line 200 "parse-gram.y"
{ spec_name_prefix = yyvsp[0].string; }
break;
case 17:
-#line 200 "parse-gram.y"
+#line 201 "parse-gram.y"
{ no_lines_flag = 1; }
break;
case 18:
-#line 201 "parse-gram.y"
+#line 202 "parse-gram.y"
{ spec_outfile = yyvsp[0].string; }
break;
case 19:
-#line 203 "parse-gram.y"
+#line 204 "parse-gram.y"
{ muscle_pair_list_grow ("parse_param", yyvsp[-2].string, yyvsp[0].string); }
break;
case 20:
-#line 204 "parse-gram.y"
+#line 205 "parse-gram.y"
{ pure_parser = 1; }
break;
case 21:
-#line 205 "parse-gram.y"
+#line 206 "parse-gram.y"
{ skeleton = yyvsp[0].string; }
break;
case 22:
-#line 206 "parse-gram.y"
+#line 207 "parse-gram.y"
{ token_table_flag = 1; }
break;
case 23:
-#line 207 "parse-gram.y"
+#line 208 "parse-gram.y"
{ report_flag = 1; }
break;
case 24:
-#line 208 "parse-gram.y"
+#line 209 "parse-gram.y"
{ yacc_flag = 1; }
break;
case 27:
-#line 215 "parse-gram.y"
+#line 216 "parse-gram.y"
{
grammar_start_symbol_set (yyvsp[0].symbol, yylsp[0]);
}
break;
case 28:
-#line 219 "parse-gram.y"
+#line 220 "parse-gram.y"
{
typed = 1;
MUSCLE_INSERT_INT ("stype_line", yylsp[0].first_line);
break;
case 29:
-#line 225 "parse-gram.y"
+#line 226 "parse-gram.y"
{ current_braced_code = destructor_braced_code; }
break;
case 30:
-#line 227 "parse-gram.y"
+#line 228 "parse-gram.y"
{
symbol_list_t *list;
for (list = yyvsp[0].list; list; list = list->next)
break;
case 31:
-#line 235 "parse-gram.y"
+#line 236 "parse-gram.y"
{ current_braced_code = printer_braced_code; }
break;
case 32:
-#line 237 "parse-gram.y"
+#line 238 "parse-gram.y"
{
symbol_list_t *list;
for (list = yyvsp[0].list; list; list = list->next)
break;
case 33:
-#line 247 "parse-gram.y"
+#line 248 "parse-gram.y"
{ current_class = nterm_sym; }
break;
case 34:
-#line 248 "parse-gram.y"
+#line 249 "parse-gram.y"
{
current_class = unknown_sym;
current_type = NULL;
break;
case 35:
-#line 252 "parse-gram.y"
+#line 253 "parse-gram.y"
{ current_class = token_sym; }
break;
case 36:
-#line 253 "parse-gram.y"
+#line 254 "parse-gram.y"
{
current_class = unknown_sym;
current_type = NULL;
break;
case 37:
-#line 258 "parse-gram.y"
+#line 259 "parse-gram.y"
{
symbol_list_t *list;
for (list = yyvsp[0].list; list; list = list->next)
- symbol_type_set (list->sym, yyvsp[-1].string, yylsp[-1]);
+ symbol_type_set (list->sym, yyvsp[-1].struniq, yylsp[-1]);
symbol_list_free (yyvsp[0].list);
}
break;
case 38:
-#line 268 "parse-gram.y"
+#line 269 "parse-gram.y"
{
symbol_list_t *list;
++current_prec;
break;
case 39:
-#line 282 "parse-gram.y"
+#line 283 "parse-gram.y"
{ yyval.assoc = left_assoc; }
break;
case 40:
-#line 283 "parse-gram.y"
+#line 284 "parse-gram.y"
{ yyval.assoc = right_assoc; }
break;
case 41:
-#line 284 "parse-gram.y"
+#line 285 "parse-gram.y"
{ yyval.assoc = non_assoc; }
break;
case 42:
-#line 288 "parse-gram.y"
+#line 289 "parse-gram.y"
{ current_type = NULL; }
break;
case 43:
-#line 289 "parse-gram.y"
- { current_type = yyvsp[0].string; }
+#line 290 "parse-gram.y"
+ { current_type = yyvsp[0].struniq; }
break;
case 44:
-#line 295 "parse-gram.y"
+#line 296 "parse-gram.y"
{ yyval.list = symbol_list_new (yyvsp[0].symbol, yylsp[0]); }
break;
case 45:
-#line 296 "parse-gram.y"
+#line 297 "parse-gram.y"
{ yyval.list = symbol_list_prepend (yyvsp[-1].list, yyvsp[0].symbol, yylsp[0]); }
break;
case 46:
-#line 302 "parse-gram.y"
+#line 303 "parse-gram.y"
{
- current_type = yyvsp[0].string;
+ current_type = yyvsp[0].struniq;
}
break;
case 47:
-#line 306 "parse-gram.y"
+#line 307 "parse-gram.y"
{
symbol_class_set (yyvsp[0].symbol, current_class, yylsp[0]);
symbol_type_set (yyvsp[0].symbol, current_type, yylsp[0]);
break;
case 48:
-#line 311 "parse-gram.y"
+#line 312 "parse-gram.y"
{
symbol_class_set (yyvsp[-1].symbol, current_class, yylsp[-1]);
symbol_type_set (yyvsp[-1].symbol, current_type, yylsp[-1]);
break;
case 49:
-#line 317 "parse-gram.y"
+#line 318 "parse-gram.y"
{
symbol_class_set (yyvsp[-1].symbol, current_class, yylsp[-1]);
symbol_type_set (yyvsp[-1].symbol, current_type, yylsp[-1]);
break;
case 50:
-#line 323 "parse-gram.y"
+#line 324 "parse-gram.y"
{
symbol_class_set (yyvsp[-2].symbol, current_class, yylsp[-2]);
symbol_type_set (yyvsp[-2].symbol, current_type, yylsp[-2]);
break;
case 51:
-#line 334 "parse-gram.y"
+#line 335 "parse-gram.y"
{;}
break;
case 52:
-#line 336 "parse-gram.y"
+#line 337 "parse-gram.y"
{;}
break;
case 56:
-#line 355 "parse-gram.y"
+#line 356 "parse-gram.y"
{
if (yacc_flag)
complain_at (yyloc, _("POSIX forbids declarations in the grammar"));
break;
case 57:
-#line 360 "parse-gram.y"
+#line 361 "parse-gram.y"
{
yyerrok;
}
break;
case 58:
-#line 366 "parse-gram.y"
+#line 367 "parse-gram.y"
{ current_lhs = yyvsp[-1].symbol; current_lhs_location = yylsp[-1]; }
break;
case 59:
-#line 367 "parse-gram.y"
+#line 368 "parse-gram.y"
{;}
break;
case 60:
-#line 371 "parse-gram.y"
+#line 372 "parse-gram.y"
{ grammar_rule_end (yylsp[0]); }
break;
case 61:
-#line 372 "parse-gram.y"
+#line 373 "parse-gram.y"
{ grammar_rule_end (yylsp[0]); }
break;
case 62:
-#line 377 "parse-gram.y"
+#line 378 "parse-gram.y"
{ grammar_rule_begin (current_lhs, current_lhs_location); }
break;
case 63:
-#line 379 "parse-gram.y"
+#line 380 "parse-gram.y"
{ grammar_current_rule_symbol_append (yyvsp[0].symbol, yylsp[0]); }
break;
case 64:
-#line 381 "parse-gram.y"
+#line 382 "parse-gram.y"
{ grammar_current_rule_action_append (yyvsp[0].string, yylsp[0]); }
break;
case 65:
-#line 383 "parse-gram.y"
+#line 384 "parse-gram.y"
{ grammar_current_rule_prec_set (yyvsp[0].symbol, yylsp[0]); }
break;
case 66:
-#line 385 "parse-gram.y"
+#line 386 "parse-gram.y"
{ grammar_current_rule_dprec_set (yyvsp[0].integer, yylsp[0]); }
break;
case 67:
-#line 387 "parse-gram.y"
- { grammar_current_rule_merge_set (yyvsp[0].string, yylsp[0]); }
+#line 388 "parse-gram.y"
+ { grammar_current_rule_merge_set (yyvsp[0].struniq, yylsp[0]); }
break;
case 68:
-#line 391 "parse-gram.y"
+#line 392 "parse-gram.y"
{ yyval.symbol = yyvsp[0].symbol; }
break;
case 69:
-#line 392 "parse-gram.y"
+#line 393 "parse-gram.y"
{ yyval.symbol = yyvsp[0].symbol; }
break;
case 70:
-#line 397 "parse-gram.y"
+#line 398 "parse-gram.y"
{ yyval.string = yyvsp[0].string; }
break;
case 71:
-#line 403 "parse-gram.y"
+#line 404 "parse-gram.y"
{
yyval.symbol = symbol_get (yyvsp[0].string, yylsp[0]);
symbol_class_set (yyval.symbol, token_sym, yylsp[0]);
break;
case 72:
-#line 412 "parse-gram.y"
+#line 413 "parse-gram.y"
{
yyval.string = yyvsp[0].string + 1;
yyval.string[strlen (yyval.string) - 1] = '\0';
break;
case 73:
-#line 420 "parse-gram.y"
+#line 421 "parse-gram.y"
{
yyval.string = xstrdup ("");
}
break;
case 74:
-#line 424 "parse-gram.y"
+#line 425 "parse-gram.y"
{
yyval.string = yyvsp[0].string;
}
}
-#line 433 "parse-gram.y"
+#line 434 "parse-gram.y"
/*------------------------------------------------------------------.
| When debugging the parser, display tokens' locations and values. |
static void yyprint (FILE *file, int type, const yystype *value);
symbol_class current_class = unknown_sym;
-char *current_type = 0;
+struniq_t current_type = 0;
symbol_t *current_lhs;
location_t current_lhs_location;
assoc_t current_assoc;
%token BRACED_CODE "{...}"
-%type <string> TYPE STRING string_content
+%type <string> STRING string_content
BRACED_CODE PROLOGUE EPILOGUE epilogue.opt action
+%type <struniq> TYPE
%type <integer> INT
%type <symbol> ID symbol string_as_id
%type <assoc> precedence_declarator
/*-------------------------------------------------------------------.
| Return the merger index for a merging function named NAME, whose |
| arguments have type TYPE. Records the function, if new, in |
-| merger_list. |
+| MERGER_LIST. |
`-------------------------------------------------------------------*/
static int
-get_merge_function (const char* name, const char* type,
- location_t loc)
+get_merge_function (struniq_t name, struniq_t type, location_t loc)
{
merger_list *syms;
merger_list head;
return 0;
if (type == NULL)
- type = "";
+ type = struniq_new ("");
head.next = merge_functions;
for (syms = &head, n = 1; syms->next != NULL; syms = syms->next, n += 1)
- if (strcmp (name, syms->next->name) == 0)
+ if (STRUNIQ_EQ (name, syms->next->name))
break;
if (syms->next == NULL)
{
syms->next = XMALLOC (merger_list, 1);
- syms->next->name = xstrdup (name);
- syms->next->type = xstrdup (type);
+ syms->next->name = struniq_new (name);
+ syms->next->type = struniq_new (type);
syms->next->next = NULL;
merge_functions = head.next;
}
- else if (strcmp (type, syms->next->type) != 0)
+ else if (!STRUNIQ_EQ (type, syms->next->type))
warn_at (loc, _("result type clash on merge function %s: <%s> != <%s>"),
name, type, syms->next->type);
return n;
if (first_rhs)
{
const char *rhs_type = first_rhs->type_name ? first_rhs->type_name : "";
- if (strcmp (lhs_type, rhs_type))
+ if (!STRUNIQ_EQ (lhs_type, rhs_type))
complain_at (current_rule->location,
_("type clash on default action: <%s> != <%s>"),
lhs_type, rhs_type);
rule. */
void
-grammar_current_rule_merge_set (const char* name, location_t location)
+grammar_current_rule_merge_set (struniq_t name, location_t location)
{
if (! glr_parser)
warn_at (location, _("%s affects only GLR parsers"), "%merge");
obstack_init (&pre_prologue_obstack);
obstack_init (&post_prologue_obstack);
- finput = xfopen (infile, "r");
+ finput = xfopen (grammar_file, "r");
gram_in = finput;
gram__flex_debug = trace_flag & trace_scan;
typedef struct merger_list
{
struct merger_list* next;
- const char* name;
- const char* type;
+ struniq_t name;
+ struniq_t type;
}
merger_list;
void grammar_midrule_action (void);
void grammar_current_rule_prec_set (symbol_t *precsym, location_t l);
void grammar_current_rule_dprec_set (int dprec, location_t l);
-void grammar_current_rule_merge_set (const char* name, location_t l);
+void grammar_current_rule_merge_set (struniq_t name, location_t l);
void grammar_current_rule_symbol_append (symbol_t *symbol, location_t l);
void grammar_current_rule_action_append (const char *action, location_t l);
nuseless_productions),
nuseless_productions);
- fprintf (stderr, "%s: %s: ", infile, _("warning"));
+ fprintf (stderr, "%s: %s: ", grammar_file, _("warning"));
if (nuseless_nonterminals > 0)
fprintf (stderr, ngettext ("%d useless nonterminal",
fprintf (stderr, "reduced %s defines %d terminals, %d nonterminals\
, and %d productions.\n",
- infile, ntokens, nvars, nrules);
+ grammar_file, ntokens, nvars, nrules);
}
}
#define YY_USER_INIT \
do { \
LOCATION_RESET (*yylloc); \
- yylloc->file = infile; \
+ yylloc->file = current_file; \
/* This is only to avoid GCC warnings. */ \
if (yycontrol) {;}; \
} while (0)
const char *file = NULL;
file = strchr (args, '"') + 1;
*strchr (file, '"') = 0;
- /* FIXME: Leaking... Can't free, as some locations are still
- pointing to the old file name. */
- infile = xstrdup (file);
- location->file = infile;
+ current_file = xstrdup (file);
+ location->file = current_file;
location->last_line = lineno;
}
#include "system.h"
#include "quotearg.h"
+#include "error.h"
#include "hash.h"
#include "struniq.h"
const struniq_t
struniq_new (const char *s)
{
- /* Keep the struniqs in a printable form. */
- struniq_t res = hash_lookup (struniqs_table,
- quotearg_style (escape_quoting_style, s));
-
+ struniq_t res = hash_lookup (struniqs_table, s);
if (!res)
{
/* First insertion in the hash. */
- res = xstrdup (quotearg_style (escape_quoting_style, s));
+ res = xstrdup (s);
hash_insert (struniqs_table, res);
}
return res;
}
+/*---------------------------------.
+| Return TRUE iff S is a struniq. |
+`---------------------------------*/
+
+bool
+struniq_assert_p (const char *s)
+{
+ if (!hash_lookup (struniqs_table, s))
+ {
+ error (0, 0, "not a struniq: %s", quotearg (s));
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+
/*--------------------.
| Print the struniq. |
`--------------------*/
| struniq_t -- pointers to unique copies of C strings. |
`------------------------------------------------------*/
-typedef char *struniq_t;
+typedef const char *struniq_t;
/* Return the struniq for S. */
const struniq_t struniq_new (const char *s);
+/* Two struniq have the same value iff they are the same. */
+#define STRUNIQ_EQ(S1, S2) ((S1) == (S2))
+
/*--------------------------------------.
| Initializing, destroying, debugging. |
`--------------------------------------*/
/* Create the string table. */
void struniqs_new (void);
+/* Die if S is not a struniq. */
+#define struniq_assert(S) assert (struniq_assert_p (S));
+bool struniq_assert_p (const char *s);
+
/* Free all the memory allocated for symbols. */
void struniqs_free (void);
| symbol N in rule RULE. |
`--------------------------------------------------------------*/
-char *
+struniq_t
symbol_list_n_type_name_get (symbol_list_t *rule, location_t location, int n)
{
int i;
/* Get the data type (alternative in the union) of the value for
symbol N in rule RULE. */
-char *symbol_list_n_type_name_get (symbol_list_t *rule,
+struniq_t symbol_list_n_type_name_get (symbol_list_t *rule,
location_t location, int n);
#endif /* !SYMLIST_H_ */
`---------------------------------*/
static symbol_t *
-symbol_new (const char *tag, location_t location)
+symbol_new (struniq_t tag, location_t location)
{
symbol_t *res = XMALLOC (symbol_t, 1);
- res->tag = xstrdup (tag);
+ struniq_assert (tag);
+ res->tag = tag;
res->location = location;
res->type_name = NULL;
`------------------------------------------------------------------*/
void
-symbol_type_set (symbol_t *symbol, char *type_name, location_t location)
+symbol_type_set (symbol_t *symbol, struniq_t type_name, location_t location)
{
if (type_name)
{
if (symbol->type_name)
complain_at (location,
_("type redeclaration for %s"), symbol->tag);
+ struniq_assert (type_name);
symbol->type_name = type_name;
}
}
static void
symbol_free (symbol_t *this)
{
- free (this->tag);
free (this);
}
static struct hash_table *symbol_table = NULL;
static bool
-hash_compare_symbol_t (const symbol_t *m1, const symbol_t *m2)
+hash_compare_symbol (const symbol_t *m1, const symbol_t *m2)
{
- return strcmp (m1->tag, m2->tag) == 0;
+ /* Since tags are unique, we can compare the pointers themselves. */
+ return STRUNIQ_EQ (m1->tag, m2->tag);
}
static unsigned int
-hash_symbol_t (const symbol_t *m, unsigned int tablesize)
+hash_symbol (const symbol_t *m, unsigned int tablesize)
{
- return hash_string (m->tag, tablesize);
+ /* Since tags are unique, we can hash the pointer itself. */
+ return ((size_t) m->tag) % tablesize;
}
{
symbol_table = hash_initialize (HT_INITIAL_CAPACITY,
NULL,
- (Hash_hasher) hash_symbol_t,
- (Hash_comparator) hash_compare_symbol_t,
+ (Hash_hasher) hash_symbol,
+ (Hash_comparator) hash_compare_symbol,
(Hash_data_freer) symbol_free);
}
symbol_t *entry;
/* Keep the symbol in a printable form. */
- key = quotearg_style (escape_quoting_style, key);
+ key = struniq_new (quotearg_style (escape_quoting_style, key));
*(char const **) &probe.tag = key;
entry = hash_lookup (symbol_table, &probe);
struct symbol_s
{
/* The key, name of the symbol. */
- char *tag;
+ struniq_t tag;
/* The location of its first occurence. */
location_t location;
/* Set the TYPE_NAME associated to SYMBOL. Does nothing if passed 0 as
TYPE_NAME. */
void symbol_type_set (symbol_t *symbol,
- char *type_name, location_t location);
+ struniq_t type_name, location_t location);
/* Set the DESTRUCTOR associated to SYMBOL. */
void symbol_destructor_set (symbol_t *symbol,