]> git.saurik.com Git - bison.git/blame - src/muscle-tab.c
Update some comments to make sense for -D.
[bison.git] / src / muscle-tab.c
CommitLineData
e00b6826
PE
1/* Muscle table manager for Bison.
2
4920ae8b
AD
3 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
4 Free 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"
00f5d575 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
AD
122 entry->key = key;
123 hash_insert (muscle_table, entry);
124 }
4502eadc
JD
125 else
126 free (entry->storage);
beda758b 127 entry->value = value;
4502eadc 128 entry->storage = NULL;
f753cd62
MA
129}
130
ae7453f2
AD
131
132/*-------------------------------------------------------------------.
ff5150d9
PE
133| Append VALUE to the current value of KEY. If KEY did not already |
134| exist, create it. Use MUSCLE_OBSTACK. De-allocate the previously |
135| associated value. Copy VALUE and SEPARATOR. |
ae7453f2
AD
136`-------------------------------------------------------------------*/
137
138void
139muscle_grow (const char *key, const char *val, const char *separator)
140{
8322e8f5
PE
141 muscle_entry probe;
142 muscle_entry *entry = NULL;
ae7453f2
AD
143
144 probe.key = key;
145 entry = hash_lookup (muscle_table, &probe);
146
147 if (!entry)
148 {
149 /* First insertion in the hash. */
da2a7671 150 entry = xmalloc (sizeof *entry);
ae7453f2
AD
151 entry->key = key;
152 hash_insert (muscle_table, entry);
eb095650 153 entry->value = entry->storage = xstrdup (val);
ae7453f2
AD
154 }
155 else
156 {
157 /* Grow the current value. */
158 char *new_val;
ae7453f2 159 obstack_sgrow (&muscle_obstack, entry->value);
eb095650 160 free (entry->storage);
ae7453f2
AD
161 obstack_sgrow (&muscle_obstack, separator);
162 obstack_sgrow (&muscle_obstack, val);
163 obstack_1grow (&muscle_obstack, 0);
164 new_val = obstack_finish (&muscle_obstack);
eb095650 165 entry->value = entry->storage = xstrdup (new_val);
ae7453f2
AD
166 obstack_free (&muscle_obstack, new_val);
167 }
168}
169
cd3684cf 170/*------------------------------------------------------------------.
35b8730d
JD
171| Using muscle_grow, append a synchronization line for the location |
172| LOC to the current value of KEY. |
cd3684cf
AD
173`------------------------------------------------------------------*/
174
35b8730d
JD
175static void
176muscle_syncline_grow (char const *key, location loc)
cd3684cf
AD
177{
178 char *extension = NULL;
05ac60f3 179 obstack_fgrow1 (&muscle_obstack, "]b4_syncline(%d, [[", loc.start.line);
cd3684cf
AD
180 MUSCLE_OBSTACK_SGROW (&muscle_obstack,
181 quotearg_style (c_quoting_style, loc.start.file));
35b8730d 182 obstack_sgrow (&muscle_obstack, "]])[");
cd3684cf
AD
183 obstack_1grow (&muscle_obstack, 0);
184 extension = obstack_finish (&muscle_obstack);
185 muscle_grow (key, extension, "");
eb095650 186 obstack_free (&muscle_obstack, extension);
cd3684cf
AD
187}
188
35b8730d
JD
189/*------------------------------------------------------------------.
190| Append VALUE to the current value of KEY, using muscle_grow. But |
191| in addition, issue a synchronization line for the location LOC |
192| using muscle_syncline_grow. |
193`------------------------------------------------------------------*/
194
195void
196muscle_code_grow (const char *key, const char *val, location loc)
197{
198 muscle_syncline_grow (key, loc);
199 muscle_grow (key, val, "\n");
200}
201
cd3684cf 202
ae7453f2
AD
203void muscle_pair_list_grow (const char *muscle,
204 const char *a1, const char *a2)
205{
66d30cd4 206 char *pair;
7ecec4dd
JD
207 obstack_sgrow (&muscle_obstack, "[[[");
208 MUSCLE_OBSTACK_SGROW (&muscle_obstack, a1);
209 obstack_sgrow (&muscle_obstack, "]], [[");
210 MUSCLE_OBSTACK_SGROW (&muscle_obstack, a2);
211 obstack_sgrow (&muscle_obstack, "]]]");
ae7453f2 212 obstack_1grow (&muscle_obstack, 0);
66d30cd4
AD
213 pair = obstack_finish (&muscle_obstack);
214 muscle_grow (muscle, pair, ",\n");
215 obstack_free (&muscle_obstack, pair);
ae7453f2
AD
216}
217
7eb8a0bc
JD
218
219/*----------------------------------------------------------------------------.
220| Find the value of muscle KEY. Unlike MUSCLE_FIND, this is always reliable |
221| to determine whether KEY has a value. |
222`----------------------------------------------------------------------------*/
223
224char const *
225muscle_find_const (char const *key)
226{
227 muscle_entry probe;
228 muscle_entry *result = NULL;
229
230 probe.key = key;
231 result = hash_lookup (muscle_table, &probe);
232 if (result)
233 return result->value;
234 return NULL;
235}
236
237
4502eadc
JD
238/*----------------------------------------------------------------------------.
239| Find the value of muscle KEY. Abort if muscle_insert was invoked more |
240| recently than muscle_grow for KEY since muscle_find can't return a |
241| char const *. |
242`----------------------------------------------------------------------------*/
ae7453f2 243
ff5150d9 244char *
7eb8a0bc 245muscle_find (char const *key)
f753cd62 246{
8322e8f5
PE
247 muscle_entry probe;
248 muscle_entry *result = NULL;
e9bca3ad 249
ae7453f2
AD
250 probe.key = key;
251 result = hash_lookup (muscle_table, &probe);
4502eadc
JD
252 if (result)
253 {
254 aver (result->value == result->storage);
255 return result->storage;
256 }
257 return NULL;
f753cd62 258}
be2a1a68
AD
259
260
9611cfa2
JD
261void
262muscle_boundary_grow (char const *key, boundary bound)
263{
264 char *extension;
265 MUSCLE_OBSTACK_SGROW (&muscle_obstack, bound.file);
266 obstack_1grow (&muscle_obstack, ':');
267 obstack_fgrow1 (&muscle_obstack, "%d", bound.line);
268 obstack_1grow (&muscle_obstack, '.');
269 obstack_fgrow1 (&muscle_obstack, "%d", bound.column);
270 obstack_1grow (&muscle_obstack, '\0');
271 extension = obstack_finish (&muscle_obstack);
272 muscle_grow (key, extension, "");
273 obstack_free (&muscle_obstack, extension);
274}
275
276void
277muscle_location_grow (char const *key, location loc)
278{
279 muscle_grow (key, "[[", "");
280 muscle_boundary_grow (key, loc.start);
281 muscle_grow (key, "]], [[", "");
282 muscle_boundary_grow (key, loc.end);
283 muscle_grow (key, "]]", "");
284}
285
f124d423
JD
286#define MUSCLE_COMMON_DECODE(Value) \
287 case '$': \
288 aver (*++(Value) == ']'); \
289 aver (*++(Value) == '['); \
290 obstack_sgrow (&muscle_obstack, "$"); \
291 break; \
292 case '@': \
293 switch (*++(Value)) \
294 { \
295 case '@': obstack_sgrow (&muscle_obstack, "@" ); break; \
296 case '{': obstack_sgrow (&muscle_obstack, "[" ); break; \
297 case '}': obstack_sgrow (&muscle_obstack, "]" ); break; \
298 default: aver (false); break; \
299 } \
300 break; \
301 default: \
302 obstack_1grow (&muscle_obstack, *(Value)); \
303 break;
304
305/* Reverse of MUSCLE_OBSTACK_SGROW. */
306static char *
307muscle_string_decode (char const *key)
308{
309 char const *value;
310 char *value_decoded;
311 char *result;
312
313 value = muscle_find_const (key);
314 if (!value)
315 return NULL;
316 do {
317 switch (*value)
318 {
319 MUSCLE_COMMON_DECODE (value)
320 case '[':
321 case ']':
322 aver (false);
323 break;
324 }
325 } while (*value++);
326 value_decoded = obstack_finish (&muscle_obstack);
327 result = xstrdup (value_decoded);
328 obstack_free (&muscle_obstack, value_decoded);
329 return result;
330}
331
9611cfa2
JD
332/* Reverse of muscle_location_grow. */
333static location
334muscle_location_decode (char const *key)
335{
336 location loc;
337 char const *value = muscle_find_const (key);
338 aver (value);
339 aver (*value == '[');
340 aver (*++value == '[');
341 while (*++value)
342 switch (*value)
343 {
f124d423 344 MUSCLE_COMMON_DECODE (value)
9611cfa2
JD
345 case '[':
346 aver (false);
347 break;
348 case ']':
349 {
350 char *boundary_str;
351 aver (*++value == ']');
352 obstack_1grow (&muscle_obstack, '\0');
353 boundary_str = obstack_finish (&muscle_obstack);
354 switch (*++value)
355 {
356 case ',':
357 boundary_set_from_string (&loc.start, boundary_str);
358 obstack_free (&muscle_obstack, boundary_str);
359 aver (*++value == ' ');
360 aver (*++value == '[');
361 aver (*++value == '[');
362 break;
363 case '\0':
364 boundary_set_from_string (&loc.end, boundary_str);
365 obstack_free (&muscle_obstack, boundary_str);
366 return loc;
367 break;
368 default:
369 aver (false);
370 break;
371 }
372 }
373 break;
9611cfa2
JD
374 }
375 aver (false);
376 return loc;
377}
378
379void
380muscle_user_name_list_grow (char const *key, char const *user_name,
381 location loc)
382{
383 muscle_grow (key, "[[[[", ",");
384 muscle_grow (key, user_name, "");
385 muscle_grow (key, "]], ", "");
386 muscle_location_grow (key, loc);
387 muscle_grow (key, "]]", "");
388}
389
390#define MUSCLE_USER_NAME_CONVERT(NAME, PREFIX, USER_NAME, SUFFIX) \
391do { \
392 char *tmp; \
393 size_t length = strlen ((USER_NAME)); \
394 tmp = xmalloc (sizeof (PREFIX) - 1 + length + sizeof (SUFFIX)); \
395 strcpy (tmp, (PREFIX)); \
396 strcpy (tmp + sizeof (PREFIX) - 1, (USER_NAME)); \
397 strcpy (tmp + sizeof (PREFIX) - 1 + length, (SUFFIX)); \
398 (NAME) = uniqstr_new (tmp); \
399 free (tmp); \
400} while (0)
401
402void
403muscle_percent_define_insert (char const *variable, location variable_loc,
404 char const *value)
405{
67212941 406 char *variable_tr = NULL;
9611cfa2
JD
407 char const *name;
408 char const *loc_name;
35b8730d 409 char const *syncline_name;
9611cfa2 410
67212941
JD
411 /* Permit certain names with underscores for backward compatibility. */
412 if (0 == strcmp (variable, "api.push_pull")
413 || 0 == strcmp (variable, "lr.keep_unreachable_states"))
414 {
415 variable_tr = strdup (variable);
416 tr (variable_tr, '_', '-');
417 variable = variable_tr;
418 }
419
9611cfa2
JD
420 MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")");
421 MUSCLE_USER_NAME_CONVERT (loc_name, "percent_define_loc(", variable, ")");
35b8730d
JD
422 MUSCLE_USER_NAME_CONVERT (syncline_name,
423 "percent_define_syncline(", variable, ")");
9611cfa2
JD
424
425 if (muscle_find_const (name))
426 {
427 warn_at (variable_loc, _("%s `%s' redefined"),
428 "%define variable", variable);
35b8730d
JD
429 warn_at (muscle_percent_define_get_loc (variable),
430 _("previous definition"));
9611cfa2
JD
431 }
432 MUSCLE_INSERT_STRING (name, value);
433
434 muscle_insert (loc_name, "");
435 muscle_location_grow (loc_name, variable_loc);
35b8730d
JD
436 muscle_insert (syncline_name, "");
437 muscle_syncline_grow (syncline_name, variable_loc);
9611cfa2
JD
438 muscle_user_name_list_grow ("percent_define_user_variables", variable,
439 variable_loc);
67212941
JD
440
441 free (variable_tr);
9611cfa2
JD
442}
443
4920ae8b
AD
444/* This is used for backward compatibility, e.g., "%define api.pure"
445 supersedes "%pure-parser". */
446void
447muscle_percent_define_ensure (char const *variable, location loc,
448 bool value)
449{
450 char const *val = value ? "" : "false";
451 char const *name;
452 MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")");
453
454 /* %pure-parser is deprecated in favor of `%define api.pure', so use
455 `%define api.pure' in a backward-compatible manner here. First,
456 don't complain if %pure-parser is specified multiple times. */
457 if (!muscle_find_const (name))
458 muscle_percent_define_insert (variable, loc, val);
459 /* In all cases, use api.pure now so that the backend doesn't complain if
460 the skeleton ignores api.pure, but do warn now if there's a previous
461 conflicting definition from an actual %define. */
462 if (muscle_percent_define_flag_if (variable) != value)
463 muscle_percent_define_insert (variable, loc, val);
464}
465
f124d423
JD
466char *
467muscle_percent_define_get (char const *variable)
468{
469 char const *name;
470 char const *usage_name;
471 char *value;
472
473 MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")");
474 MUSCLE_USER_NAME_CONVERT (usage_name, "percent_define_bison_variables(",
475 variable, ")");
476
477 muscle_insert (usage_name, "");
478 value = muscle_string_decode (name);
479 if (!value)
480 value = xstrdup ("");
481 return value;
482}
483
35b8730d
JD
484location
485muscle_percent_define_get_loc (char const *variable)
486{
487 char const *loc_name;
488 MUSCLE_USER_NAME_CONVERT (loc_name, "percent_define_loc(", variable, ")");
489 if (!muscle_find_const (loc_name))
490 fatal(_("undefined %%define variable `%s' passed to muscle_percent_define_get_loc"),
491 variable);
492 return muscle_location_decode (loc_name);
493}
494
495char const *
496muscle_percent_define_get_syncline (char const *variable)
497{
498 char const *syncline_name;
499 char const *syncline;
500 MUSCLE_USER_NAME_CONVERT (syncline_name,
501 "percent_define_syncline(", variable, ")");
502 syncline = muscle_find_const (syncline_name);
503 if (!syncline)
504 fatal(_("undefined %%define variable `%s' passed to muscle_percent_define_get_syncline"),
505 variable);
506 return syncline;
507}
508
f124d423
JD
509bool
510muscle_percent_define_ifdef (char const *variable)
511{
512 char const *name;
513 char const *usage_name;
514 char const *value;
515
516 MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")");
517 MUSCLE_USER_NAME_CONVERT (usage_name, "percent_define_bison_variables(",
518 variable, ")");
519
520 value = muscle_find_const (name);
521 if (value)
522 {
523 muscle_insert (usage_name, "");
524 return true;
525 }
526
527 return false;
528}
529
9611cfa2
JD
530bool
531muscle_percent_define_flag_if (char const *variable)
532{
cbd50549 533 char const *invalid_boolean_name;
9611cfa2
JD
534 bool result = false;
535
cbd50549
JD
536 MUSCLE_USER_NAME_CONVERT (invalid_boolean_name,
537 "percent_define_invalid_boolean(", variable, ")");
9611cfa2 538
f124d423 539 if (muscle_percent_define_ifdef (variable))
9611cfa2 540 {
f124d423 541 char *value = muscle_percent_define_get (variable);
9611cfa2
JD
542 if (value[0] == '\0' || 0 == strcmp (value, "true"))
543 result = true;
544 else if (0 == strcmp (value, "false"))
545 result = false;
cbd50549
JD
546 else if (!muscle_find_const (invalid_boolean_name))
547 {
548 muscle_insert (invalid_boolean_name, "");
35b8730d 549 complain_at(muscle_percent_define_get_loc (variable),
922bdd7f 550 _("invalid value for %%define Boolean variable `%s'"),
cbd50549
JD
551 variable);
552 }
f124d423 553 free (value);
9611cfa2
JD
554 }
555 else
556 fatal(_("undefined %%define variable `%s' passed to muscle_percent_define_flag_if"),
557 variable);
558
9611cfa2
JD
559 return result;
560}
561
562void
563muscle_percent_define_default (char const *variable, char const *value)
564{
565 char const *name;
566 char const *loc_name;
35b8730d 567 char const *syncline_name;
9611cfa2
JD
568 MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")");
569 MUSCLE_USER_NAME_CONVERT (loc_name, "percent_define_loc(", variable, ")");
35b8730d
JD
570 MUSCLE_USER_NAME_CONVERT (syncline_name,
571 "percent_define_syncline(", variable, ")");
9611cfa2
JD
572 if (!muscle_find_const (name))
573 {
574 location loc;
575 MUSCLE_INSERT_STRING (name, value);
92822aff
JD
576 loc.start.file = loc.end.file = "<default value>";
577 loc.start.line = loc.end.line = -1;
578 loc.start.column = loc.end.column = -1;
9611cfa2
JD
579 muscle_insert (loc_name, "");
580 muscle_location_grow (loc_name, loc);
35b8730d 581 muscle_insert (syncline_name, "");
9611cfa2
JD
582 }
583}
584
f124d423 585void
b1a81613 586muscle_percent_define_check_values (char const * const *values)
f124d423 587{
b1a81613
JD
588 for (; *values; ++values)
589 {
f4909773 590 char const * const *variablep = values;
b1a81613 591 char const *name;
b1a81613
JD
592 char *value;
593
f4909773 594 MUSCLE_USER_NAME_CONVERT (name, "percent_define(", *variablep, ")");
b1a81613
JD
595
596 value = muscle_string_decode (name);
597 if (value)
598 {
b1a81613
JD
599 for (++values; *values; ++values)
600 {
601 if (0 == strcmp (value, *values))
f4909773
JD
602 break;
603 }
604 if (!*values)
605 {
606 location loc = muscle_percent_define_get_loc (*variablep);
607 complain_at(loc,
608 _("invalid value for %%define variable `%s': `%s'"),
609 *variablep, value);
610 for (values = variablep + 1; *values; ++values)
611 complain_at (loc, _("accepted value: `%s'"), *values);
612 }
613 else
614 {
615 while (*values)
616 ++values;
b1a81613 617 }
b1a81613
JD
618 free (value);
619 }
620 else
f4909773
JD
621 fatal(_("undefined %%define variable `%s' passed to"
622 " muscle_percent_define_check_values"),
623 *variablep);
b1a81613 624 }
f124d423
JD
625}
626
9611cfa2
JD
627void
628muscle_percent_code_grow (char const *qualifier, location qualifier_loc,
629 char const *code, location code_loc)
630{
631 char const *name;
632 MUSCLE_USER_NAME_CONVERT (name, "percent_code(", qualifier, ")");
633 muscle_code_grow (name, code, code_loc);
634 muscle_user_name_list_grow ("percent_code_user_qualifiers", qualifier,
635 qualifier_loc);
636}
637
638
ae7453f2
AD
639/*------------------------------------------------.
640| Output the definition of ENTRY as a m4_define. |
641`------------------------------------------------*/
be2a1a68 642
e00b6826 643static inline bool
8322e8f5 644muscle_m4_output (muscle_entry *entry, FILE *out)
be2a1a68
AD
645{
646 fprintf (out, "m4_define([b4_%s],\n", entry->key);
ae7453f2 647 fprintf (out, "[[%s]])\n\n\n", entry->value);
e00b6826
PE
648 return true;
649}
650
651static bool
652muscle_m4_output_processor (void *entry, void *out)
653{
654 return muscle_m4_output (entry, out);
be2a1a68
AD
655}
656
657
ae7453f2
AD
658/*----------------------------------------------------------------.
659| Output the definition of all the current muscles into a list of |
660| m4_defines. |
661`----------------------------------------------------------------*/
be2a1a68
AD
662
663void
664muscles_m4_output (FILE *out)
665{
e00b6826 666 hash_do_for_each (muscle_table, muscle_m4_output_processor, out);
be2a1a68 667}