]> git.saurik.com Git - bison.git/blame - src/muscle-tab.c
YYFAIL: warn about uses and remove from lalr1.java.
[bison.git] / src / muscle-tab.c
CommitLineData
e00b6826
PE
1/* Muscle table manager for Bison.
2
75c21b61
AD
3 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free
4 Software Foundation, Inc.
f753cd62
MA
5
6 This file is part of Bison, the GNU Compiler Compiler.
7
f16b0819 8 This program is free software: you can redistribute it and/or modify
f753cd62 9 it under the terms of the GNU General Public License as published by
f16b0819
PE
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
f753cd62 12
f16b0819 13 This program is distributed in the hope that it will be useful,
f753cd62
MA
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.
17
18 You should have received a copy of the GNU General Public License
f16b0819 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
f753cd62 20
2cec9080 21#include <config.h>
f753cd62 22#include "system.h"
8322e8f5
PE
23
24#include <hash.h>
25#include <quotearg.h>
26
9611cfa2 27#include "complain.h"
f753cd62 28#include "files.h"
23ec25b7 29#include "muscle-tab.h"
f508cb0a 30#include "getargs.h"
f753cd62 31
eb095650
PE
32/* A key-value pair, along with storage that can be reclaimed when
33 this pair is no longer needed. */
8322e8f5
PE
34typedef struct
35{
eb095650
PE
36 char const *key;
37 char const *value;
38 char *storage;
8322e8f5 39} muscle_entry;
592e8d4d
AD
40
41/* An obstack used to create some entries. */
42struct obstack muscle_obstack;
43
beda758b
AD
44/* Initial capacity of muscles hash table. */
45#define HT_INITIAL_CAPACITY 257
f753cd62 46
04098407 47static struct hash_table *muscle_table = NULL;
f753cd62 48
beda758b
AD
49static bool
50hash_compare_muscles (void const *x, void const *y)
f753cd62 51{
8322e8f5
PE
52 muscle_entry const *m1 = x;
53 muscle_entry const *m2 = y;
5dd5fd4a 54 return strcmp (m1->key, m2->key) == 0;
f753cd62
MA
55}
56
233a88ad
PE
57static size_t
58hash_muscle (const void *x, size_t tablesize)
f753cd62 59{
8322e8f5 60 muscle_entry const *m = x;
beda758b 61 return hash_string (m->key, tablesize);
f753cd62
MA
62}
63
592e8d4d
AD
64/*-----------------------------------------------------------------.
65| Create the MUSCLE_TABLE, and initialize it with default values. |
66| Also set up the MUSCLE_OBSTACK. |
67`-----------------------------------------------------------------*/
68
eb095650
PE
69static void
70muscle_entry_free (void *entry)
71{
72 muscle_entry *mentry = entry;
73 free (mentry->storage);
74 free (mentry);
75}
76
f753cd62
MA
77void
78muscle_init (void)
79{
ae7453f2
AD
80 /* Initialize the muscle obstack. */
81 obstack_init (&muscle_obstack);
82
beda758b 83 muscle_table = hash_initialize (HT_INITIAL_CAPACITY, NULL, hash_muscle,
eb095650 84 hash_compare_muscles, muscle_entry_free);
f753cd62
MA
85
86 /* Version and input file. */
ae7453f2 87 MUSCLE_INSERT_STRING ("version", VERSION);
f753cd62
MA
88}
89
592e8d4d
AD
90
91/*------------------------------------------------------------.
92| Free all the memory consumed by the muscle machinery only. |
93`------------------------------------------------------------*/
94
95void
96muscle_free (void)
97{
98 hash_free (muscle_table);
99 obstack_free (&muscle_obstack, NULL);
100}
101
102
103
ae7453f2
AD
104/*------------------------------------------------------------.
105| Insert (KEY, VALUE). If KEY already existed, overwrite the |
106| previous value. |
107`------------------------------------------------------------*/
108
a870c567 109void
eb095650 110muscle_insert (char const *key, char const *value)
f753cd62 111{
8322e8f5 112 muscle_entry probe;
da2a7671 113 muscle_entry *entry;
e9bca3ad 114
ae7453f2
AD
115 probe.key = key;
116 entry = hash_lookup (muscle_table, &probe);
beda758b
AD
117
118 if (!entry)
119 {
120 /* First insertion in the hash. */
da2a7671 121 entry = xmalloc (sizeof *entry);
beda758b 122 entry->key = key;
75c7a52a
AD
123 if (!hash_insert (muscle_table, entry))
124 xalloc_die ();
beda758b 125 }
4502eadc
JD
126 else
127 free (entry->storage);
beda758b 128 entry->value = value;
4502eadc 129 entry->storage = NULL;
f753cd62
MA
130}
131
ae7453f2
AD
132
133/*-------------------------------------------------------------------.
ff5150d9
PE
134| Append VALUE to the current value of KEY. If KEY did not already |
135| exist, create it. Use MUSCLE_OBSTACK. De-allocate the previously |
136| associated value. Copy VALUE and SEPARATOR. |
ae7453f2
AD
137`-------------------------------------------------------------------*/
138
139void
140muscle_grow (const char *key, const char *val, const char *separator)
141{
8322e8f5
PE
142 muscle_entry probe;
143 muscle_entry *entry = NULL;
ae7453f2
AD
144
145 probe.key = key;
146 entry = hash_lookup (muscle_table, &probe);
147
148 if (!entry)
149 {
150 /* First insertion in the hash. */
da2a7671 151 entry = xmalloc (sizeof *entry);
ae7453f2 152 entry->key = key;
75c7a52a
AD
153 if (!hash_insert (muscle_table, entry))
154 xalloc_die ();
eb095650 155 entry->value = entry->storage = xstrdup (val);
ae7453f2
AD
156 }
157 else
158 {
159 /* Grow the current value. */
160 char *new_val;
ae7453f2 161 obstack_sgrow (&muscle_obstack, entry->value);
eb095650 162 free (entry->storage);
ae7453f2
AD
163 obstack_sgrow (&muscle_obstack, separator);
164 obstack_sgrow (&muscle_obstack, val);
165 obstack_1grow (&muscle_obstack, 0);
166 new_val = obstack_finish (&muscle_obstack);
eb095650 167 entry->value = entry->storage = xstrdup (new_val);
ae7453f2
AD
168 obstack_free (&muscle_obstack, new_val);
169 }
170}
171
cd3684cf 172/*------------------------------------------------------------------.
35b8730d
JD
173| Using muscle_grow, append a synchronization line for the location |
174| LOC to the current value of KEY. |
cd3684cf
AD
175`------------------------------------------------------------------*/
176
35b8730d
JD
177static void
178muscle_syncline_grow (char const *key, location loc)
cd3684cf
AD
179{
180 char *extension = NULL;
05ac60f3 181 obstack_fgrow1 (&muscle_obstack, "]b4_syncline(%d, [[", loc.start.line);
cd3684cf
AD
182 MUSCLE_OBSTACK_SGROW (&muscle_obstack,
183 quotearg_style (c_quoting_style, loc.start.file));
35b8730d 184 obstack_sgrow (&muscle_obstack, "]])[");
cd3684cf
AD
185 obstack_1grow (&muscle_obstack, 0);
186 extension = obstack_finish (&muscle_obstack);
187 muscle_grow (key, extension, "");
eb095650 188 obstack_free (&muscle_obstack, extension);
cd3684cf
AD
189}
190
35b8730d
JD
191/*------------------------------------------------------------------.
192| Append VALUE to the current value of KEY, using muscle_grow. But |
193| in addition, issue a synchronization line for the location LOC |
194| using muscle_syncline_grow. |
195`------------------------------------------------------------------*/
196
197void
198muscle_code_grow (const char *key, const char *val, location loc)
199{
200 muscle_syncline_grow (key, loc);
201 muscle_grow (key, val, "\n");
202}
203
cd3684cf 204
ae7453f2
AD
205void muscle_pair_list_grow (const char *muscle,
206 const char *a1, const char *a2)
207{
66d30cd4 208 char *pair;
7ecec4dd
JD
209 obstack_sgrow (&muscle_obstack, "[[[");
210 MUSCLE_OBSTACK_SGROW (&muscle_obstack, a1);
211 obstack_sgrow (&muscle_obstack, "]], [[");
212 MUSCLE_OBSTACK_SGROW (&muscle_obstack, a2);
213 obstack_sgrow (&muscle_obstack, "]]]");
ae7453f2 214 obstack_1grow (&muscle_obstack, 0);
66d30cd4
AD
215 pair = obstack_finish (&muscle_obstack);
216 muscle_grow (muscle, pair, ",\n");
217 obstack_free (&muscle_obstack, pair);
ae7453f2
AD
218}
219
7eb8a0bc
JD
220
221/*----------------------------------------------------------------------------.
222| Find the value of muscle KEY. Unlike MUSCLE_FIND, this is always reliable |
223| to determine whether KEY has a value. |
224`----------------------------------------------------------------------------*/
225
226char const *
227muscle_find_const (char const *key)
228{
229 muscle_entry probe;
230 muscle_entry *result = NULL;
231
232 probe.key = key;
233 result = hash_lookup (muscle_table, &probe);
234 if (result)
235 return result->value;
236 return NULL;
237}
238
239
4502eadc
JD
240/*----------------------------------------------------------------------------.
241| Find the value of muscle KEY. Abort if muscle_insert was invoked more |
242| recently than muscle_grow for KEY since muscle_find can't return a |
243| char const *. |
244`----------------------------------------------------------------------------*/
ae7453f2 245
ff5150d9 246char *
7eb8a0bc 247muscle_find (char const *key)
f753cd62 248{
8322e8f5
PE
249 muscle_entry probe;
250 muscle_entry *result = NULL;
e9bca3ad 251
ae7453f2
AD
252 probe.key = key;
253 result = hash_lookup (muscle_table, &probe);
4502eadc
JD
254 if (result)
255 {
256 aver (result->value == result->storage);
257 return result->storage;
258 }
259 return NULL;
f753cd62 260}
be2a1a68
AD
261
262
9611cfa2
JD
263void
264muscle_boundary_grow (char const *key, boundary bound)
265{
266 char *extension;
267 MUSCLE_OBSTACK_SGROW (&muscle_obstack, bound.file);
268 obstack_1grow (&muscle_obstack, ':');
269 obstack_fgrow1 (&muscle_obstack, "%d", bound.line);
270 obstack_1grow (&muscle_obstack, '.');
271 obstack_fgrow1 (&muscle_obstack, "%d", bound.column);
272 obstack_1grow (&muscle_obstack, '\0');
273 extension = obstack_finish (&muscle_obstack);
274 muscle_grow (key, extension, "");
275 obstack_free (&muscle_obstack, extension);
276}
277
278void
279muscle_location_grow (char const *key, location loc)
280{
281 muscle_grow (key, "[[", "");
282 muscle_boundary_grow (key, loc.start);
283 muscle_grow (key, "]], [[", "");
284 muscle_boundary_grow (key, loc.end);
285 muscle_grow (key, "]]", "");
286}
287
f124d423
JD
288#define MUSCLE_COMMON_DECODE(Value) \
289 case '$': \
290 aver (*++(Value) == ']'); \
291 aver (*++(Value) == '['); \
292 obstack_sgrow (&muscle_obstack, "$"); \
293 break; \
294 case '@': \
295 switch (*++(Value)) \
296 { \
297 case '@': obstack_sgrow (&muscle_obstack, "@" ); break; \
298 case '{': obstack_sgrow (&muscle_obstack, "[" ); break; \
299 case '}': obstack_sgrow (&muscle_obstack, "]" ); break; \
300 default: aver (false); break; \
301 } \
302 break; \
303 default: \
304 obstack_1grow (&muscle_obstack, *(Value)); \
305 break;
306
307/* Reverse of MUSCLE_OBSTACK_SGROW. */
308static char *
309muscle_string_decode (char const *key)
310{
311 char const *value;
312 char *value_decoded;
313 char *result;
314
315 value = muscle_find_const (key);
316 if (!value)
317 return NULL;
318 do {
319 switch (*value)
320 {
321 MUSCLE_COMMON_DECODE (value)
322 case '[':
323 case ']':
324 aver (false);
325 break;
326 }
327 } while (*value++);
328 value_decoded = obstack_finish (&muscle_obstack);
329 result = xstrdup (value_decoded);
330 obstack_free (&muscle_obstack, value_decoded);
331 return result;
332}
333
9611cfa2
JD
334/* Reverse of muscle_location_grow. */
335static location
336muscle_location_decode (char const *key)
337{
338 location loc;
339 char const *value = muscle_find_const (key);
340 aver (value);
341 aver (*value == '[');
342 aver (*++value == '[');
343 while (*++value)
344 switch (*value)
345 {
f124d423 346 MUSCLE_COMMON_DECODE (value)
9611cfa2
JD
347 case '[':
348 aver (false);
349 break;
350 case ']':
351 {
352 char *boundary_str;
353 aver (*++value == ']');
354 obstack_1grow (&muscle_obstack, '\0');
355 boundary_str = obstack_finish (&muscle_obstack);
356 switch (*++value)
357 {
358 case ',':
359 boundary_set_from_string (&loc.start, boundary_str);
360 obstack_free (&muscle_obstack, boundary_str);
361 aver (*++value == ' ');
362 aver (*++value == '[');
363 aver (*++value == '[');
364 break;
365 case '\0':
366 boundary_set_from_string (&loc.end, boundary_str);
367 obstack_free (&muscle_obstack, boundary_str);
368 return loc;
369 break;
370 default:
371 aver (false);
372 break;
373 }
374 }
375 break;
9611cfa2
JD
376 }
377 aver (false);
378 return loc;
379}
380
381void
382muscle_user_name_list_grow (char const *key, char const *user_name,
383 location loc)
384{
385 muscle_grow (key, "[[[[", ",");
386 muscle_grow (key, user_name, "");
387 muscle_grow (key, "]], ", "");
388 muscle_location_grow (key, loc);
389 muscle_grow (key, "]]", "");
390}
391
9611cfa2
JD
392void
393muscle_percent_define_insert (char const *variable, location variable_loc,
34d41938
JD
394 char const *value,
395 muscle_percent_define_how how)
9611cfa2 396{
812775a0 397 char *variable_tr = NULL;
9611cfa2
JD
398 char const *name;
399 char const *loc_name;
35b8730d 400 char const *syncline_name;
34d41938 401 char const *how_name;
9611cfa2 402
812775a0
JD
403 /* Permit certain names with underscores for backward compatibility. */
404 if (0 == strcmp (variable, "api.push_pull")
405 || 0 == strcmp (variable, "lr.keep_unreachable_states"))
406 {
407 variable_tr = strdup (variable);
408 tr (variable_tr, '_', '-');
409 variable = variable_tr;
410 }
411
0ab402b4
JD
412 name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
413 loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
414 syncline_name =
415 UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
416 how_name = UNIQSTR_CONCAT ("percent_define_how(", variable, ")");
9611cfa2 417
34d41938
JD
418 /* Command-line options are processed before the grammar file. */
419 if (how == MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE
420 && muscle_find_const (name))
9611cfa2 421 {
34d41938
JD
422 muscle_percent_define_how how_old =
423 atoi (muscle_find_const (how_name));
424 if (how_old == MUSCLE_PERCENT_DEFINE_F)
425 {
426 free (variable_tr);
427 return;
428 }
e3a33f7c
JD
429 complain_at (variable_loc, _("%s `%s' redefined"),
430 "%define variable", variable);
431 complain_at (muscle_percent_define_get_loc (variable),
34d41938 432 _("previous definition"));
9611cfa2 433 }
9611cfa2 434
34d41938 435 MUSCLE_INSERT_STRING (name, value);
9611cfa2
JD
436 muscle_insert (loc_name, "");
437 muscle_location_grow (loc_name, variable_loc);
35b8730d
JD
438 muscle_insert (syncline_name, "");
439 muscle_syncline_grow (syncline_name, variable_loc);
9611cfa2
JD
440 muscle_user_name_list_grow ("percent_define_user_variables", variable,
441 variable_loc);
34d41938 442 MUSCLE_INSERT_INT (how_name, how);
812775a0
JD
443
444 free (variable_tr);
9611cfa2
JD
445}
446
f124d423
JD
447char *
448muscle_percent_define_get (char const *variable)
449{
450 char const *name;
451 char const *usage_name;
452 char *value;
453
0ab402b4
JD
454 name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
455 usage_name = UNIQSTR_CONCAT ("percent_define_bison_variables(",
456 variable, ")");
f124d423
JD
457
458 muscle_insert (usage_name, "");
459 value = muscle_string_decode (name);
460 if (!value)
461 value = xstrdup ("");
462 return value;
463}
464
35b8730d
JD
465location
466muscle_percent_define_get_loc (char const *variable)
467{
468 char const *loc_name;
0ab402b4 469 loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
35b8730d 470 if (!muscle_find_const (loc_name))
0ab402b4
JD
471 fatal(_("undefined %%define variable `%s' passed to"
472 " muscle_percent_define_get_loc"), variable);
35b8730d
JD
473 return muscle_location_decode (loc_name);
474}
475
476char const *
477muscle_percent_define_get_syncline (char const *variable)
478{
479 char const *syncline_name;
480 char const *syncline;
0ab402b4
JD
481 syncline_name =
482 UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
35b8730d
JD
483 syncline = muscle_find_const (syncline_name);
484 if (!syncline)
0ab402b4
JD
485 fatal(_("undefined %%define variable `%s' passed to"
486 " muscle_percent_define_get_syncline"), variable);
35b8730d
JD
487 return syncline;
488}
489
f124d423
JD
490bool
491muscle_percent_define_ifdef (char const *variable)
492{
493 char const *name;
494 char const *usage_name;
495 char const *value;
496
0ab402b4
JD
497 name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
498 usage_name =
499 UNIQSTR_CONCAT ("percent_define_bison_variables(", variable, ")");
f124d423
JD
500
501 value = muscle_find_const (name);
502 if (value)
503 {
504 muscle_insert (usage_name, "");
505 return true;
506 }
507
508 return false;
509}
510
9611cfa2
JD
511bool
512muscle_percent_define_flag_if (char const *variable)
513{
cbd50549 514 char const *invalid_boolean_name;
9611cfa2
JD
515 bool result = false;
516
0ab402b4
JD
517 invalid_boolean_name =
518 UNIQSTR_CONCAT ("percent_define_invalid_boolean(", variable, ")");
9611cfa2 519
f124d423 520 if (muscle_percent_define_ifdef (variable))
9611cfa2 521 {
f124d423 522 char *value = muscle_percent_define_get (variable);
9611cfa2
JD
523 if (value[0] == '\0' || 0 == strcmp (value, "true"))
524 result = true;
525 else if (0 == strcmp (value, "false"))
526 result = false;
cbd50549
JD
527 else if (!muscle_find_const (invalid_boolean_name))
528 {
529 muscle_insert (invalid_boolean_name, "");
35b8730d 530 complain_at(muscle_percent_define_get_loc (variable),
922bdd7f 531 _("invalid value for %%define Boolean variable `%s'"),
cbd50549
JD
532 variable);
533 }
f124d423 534 free (value);
9611cfa2
JD
535 }
536 else
537 fatal(_("undefined %%define variable `%s' passed to muscle_percent_define_flag_if"),
538 variable);
539
9611cfa2
JD
540 return result;
541}
542
543void
544muscle_percent_define_default (char const *variable, char const *value)
545{
546 char const *name;
547 char const *loc_name;
35b8730d 548 char const *syncline_name;
0ab402b4
JD
549 name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
550 loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
551 syncline_name =
552 UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
9611cfa2
JD
553 if (!muscle_find_const (name))
554 {
555 location loc;
556 MUSCLE_INSERT_STRING (name, value);
580c075d
JD
557 loc.start.file = loc.end.file = "<default value>";
558 loc.start.line = loc.end.line = -1;
559 loc.start.column = loc.end.column = -1;
9611cfa2
JD
560 muscle_insert (loc_name, "");
561 muscle_location_grow (loc_name, loc);
35b8730d 562 muscle_insert (syncline_name, "");
9611cfa2
JD
563 }
564}
565
f124d423 566void
b1a81613 567muscle_percent_define_check_values (char const * const *values)
f124d423 568{
b1a81613
JD
569 for (; *values; ++values)
570 {
25029e16 571 char const * const *variablep = values;
b1a81613 572 char const *name;
b1a81613
JD
573 char *value;
574
0ab402b4 575 name = UNIQSTR_CONCAT ("percent_define(", *variablep, ")");
b1a81613
JD
576
577 value = muscle_string_decode (name);
578 if (value)
579 {
b1a81613
JD
580 for (++values; *values; ++values)
581 {
582 if (0 == strcmp (value, *values))
25029e16
JD
583 break;
584 }
585 if (!*values)
586 {
587 location loc = muscle_percent_define_get_loc (*variablep);
588 complain_at(loc,
589 _("invalid value for %%define variable `%s': `%s'"),
590 *variablep, value);
591 for (values = variablep + 1; *values; ++values)
592 complain_at (loc, _("accepted value: `%s'"), *values);
593 }
594 else
595 {
596 while (*values)
597 ++values;
b1a81613 598 }
b1a81613
JD
599 free (value);
600 }
601 else
25029e16
JD
602 fatal(_("undefined %%define variable `%s' passed to"
603 " muscle_percent_define_check_values"),
604 *variablep);
b1a81613 605 }
f124d423
JD
606}
607
9611cfa2
JD
608void
609muscle_percent_code_grow (char const *qualifier, location qualifier_loc,
610 char const *code, location code_loc)
611{
612 char const *name;
0ab402b4 613 name = UNIQSTR_CONCAT ("percent_code(", qualifier, ")");
9611cfa2
JD
614 muscle_code_grow (name, code, code_loc);
615 muscle_user_name_list_grow ("percent_code_user_qualifiers", qualifier,
616 qualifier_loc);
617}
618
619
ae7453f2
AD
620/*------------------------------------------------.
621| Output the definition of ENTRY as a m4_define. |
622`------------------------------------------------*/
be2a1a68 623
e00b6826 624static inline bool
8322e8f5 625muscle_m4_output (muscle_entry *entry, FILE *out)
be2a1a68
AD
626{
627 fprintf (out, "m4_define([b4_%s],\n", entry->key);
ae7453f2 628 fprintf (out, "[[%s]])\n\n\n", entry->value);
e00b6826
PE
629 return true;
630}
631
632static bool
633muscle_m4_output_processor (void *entry, void *out)
634{
635 return muscle_m4_output (entry, out);
be2a1a68
AD
636}
637
638
ae7453f2
AD
639/*----------------------------------------------------------------.
640| Output the definition of all the current muscles into a list of |
641| m4_defines. |
642`----------------------------------------------------------------*/
be2a1a68
AD
643
644void
645muscles_m4_output (FILE *out)
646{
e00b6826 647 hash_do_for_each (muscle_table, muscle_m4_output_processor, out);
be2a1a68 648}