]> git.saurik.com Git - bison.git/blame - src/muscle-tab.c
Convert multiple variable definition warnings to complaints.
[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,
de5ab940
JD
404 char const *value,
405 muscle_percent_define_how how)
9611cfa2 406{
67212941 407 char *variable_tr = NULL;
9611cfa2
JD
408 char const *name;
409 char const *loc_name;
35b8730d 410 char const *syncline_name;
de5ab940 411 char const *how_name;
9611cfa2 412
67212941
JD
413 /* Permit certain names with underscores for backward compatibility. */
414 if (0 == strcmp (variable, "api.push_pull")
415 || 0 == strcmp (variable, "lr.keep_unreachable_states"))
416 {
417 variable_tr = strdup (variable);
418 tr (variable_tr, '_', '-');
419 variable = variable_tr;
420 }
421
9611cfa2
JD
422 MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")");
423 MUSCLE_USER_NAME_CONVERT (loc_name, "percent_define_loc(", variable, ")");
35b8730d
JD
424 MUSCLE_USER_NAME_CONVERT (syncline_name,
425 "percent_define_syncline(", variable, ")");
de5ab940 426 MUSCLE_USER_NAME_CONVERT (how_name, "percent_define_how(", variable, ")");
9611cfa2 427
de5ab940
JD
428 /* Command-line options are processed before the grammar file. */
429 if (how == MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE
430 && muscle_find_const (name))
9611cfa2 431 {
de5ab940
JD
432 muscle_percent_define_how how_old =
433 atoi (muscle_find_const (how_name));
434 if (how_old == MUSCLE_PERCENT_DEFINE_F)
435 {
436 free (variable_tr);
437 return;
438 }
0b6d43c5
JD
439 complain_at (variable_loc, _("%s `%s' redefined"),
440 "%define variable", variable);
441 complain_at (muscle_percent_define_get_loc (variable),
de5ab940 442 _("previous definition"));
9611cfa2 443 }
9611cfa2 444
de5ab940 445 MUSCLE_INSERT_STRING (name, value);
9611cfa2
JD
446 muscle_insert (loc_name, "");
447 muscle_location_grow (loc_name, variable_loc);
35b8730d
JD
448 muscle_insert (syncline_name, "");
449 muscle_syncline_grow (syncline_name, variable_loc);
9611cfa2
JD
450 muscle_user_name_list_grow ("percent_define_user_variables", variable,
451 variable_loc);
de5ab940 452 MUSCLE_INSERT_INT (how_name, how);
67212941
JD
453
454 free (variable_tr);
9611cfa2
JD
455}
456
4920ae8b
AD
457/* This is used for backward compatibility, e.g., "%define api.pure"
458 supersedes "%pure-parser". */
459void
460muscle_percent_define_ensure (char const *variable, location loc,
461 bool value)
462{
463 char const *val = value ? "" : "false";
464 char const *name;
465 MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")");
466
467 /* %pure-parser is deprecated in favor of `%define api.pure', so use
468 `%define api.pure' in a backward-compatible manner here. First,
469 don't complain if %pure-parser is specified multiple times. */
470 if (!muscle_find_const (name))
de5ab940
JD
471 muscle_percent_define_insert (variable, loc, val,
472 MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
4920ae8b
AD
473 /* In all cases, use api.pure now so that the backend doesn't complain if
474 the skeleton ignores api.pure, but do warn now if there's a previous
475 conflicting definition from an actual %define. */
476 if (muscle_percent_define_flag_if (variable) != value)
de5ab940
JD
477 muscle_percent_define_insert (variable, loc, val,
478 MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE);
4920ae8b
AD
479}
480
f124d423
JD
481char *
482muscle_percent_define_get (char const *variable)
483{
484 char const *name;
485 char const *usage_name;
486 char *value;
487
488 MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")");
489 MUSCLE_USER_NAME_CONVERT (usage_name, "percent_define_bison_variables(",
490 variable, ")");
491
492 muscle_insert (usage_name, "");
493 value = muscle_string_decode (name);
494 if (!value)
495 value = xstrdup ("");
496 return value;
497}
498
35b8730d
JD
499location
500muscle_percent_define_get_loc (char const *variable)
501{
502 char const *loc_name;
503 MUSCLE_USER_NAME_CONVERT (loc_name, "percent_define_loc(", variable, ")");
504 if (!muscle_find_const (loc_name))
505 fatal(_("undefined %%define variable `%s' passed to muscle_percent_define_get_loc"),
506 variable);
507 return muscle_location_decode (loc_name);
508}
509
510char const *
511muscle_percent_define_get_syncline (char const *variable)
512{
513 char const *syncline_name;
514 char const *syncline;
515 MUSCLE_USER_NAME_CONVERT (syncline_name,
516 "percent_define_syncline(", variable, ")");
517 syncline = muscle_find_const (syncline_name);
518 if (!syncline)
519 fatal(_("undefined %%define variable `%s' passed to muscle_percent_define_get_syncline"),
520 variable);
521 return syncline;
522}
523
f124d423
JD
524bool
525muscle_percent_define_ifdef (char const *variable)
526{
527 char const *name;
528 char const *usage_name;
529 char const *value;
530
531 MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")");
532 MUSCLE_USER_NAME_CONVERT (usage_name, "percent_define_bison_variables(",
533 variable, ")");
534
535 value = muscle_find_const (name);
536 if (value)
537 {
538 muscle_insert (usage_name, "");
539 return true;
540 }
541
542 return false;
543}
544
9611cfa2
JD
545bool
546muscle_percent_define_flag_if (char const *variable)
547{
cbd50549 548 char const *invalid_boolean_name;
9611cfa2
JD
549 bool result = false;
550
cbd50549
JD
551 MUSCLE_USER_NAME_CONVERT (invalid_boolean_name,
552 "percent_define_invalid_boolean(", variable, ")");
9611cfa2 553
f124d423 554 if (muscle_percent_define_ifdef (variable))
9611cfa2 555 {
f124d423 556 char *value = muscle_percent_define_get (variable);
9611cfa2
JD
557 if (value[0] == '\0' || 0 == strcmp (value, "true"))
558 result = true;
559 else if (0 == strcmp (value, "false"))
560 result = false;
cbd50549
JD
561 else if (!muscle_find_const (invalid_boolean_name))
562 {
563 muscle_insert (invalid_boolean_name, "");
35b8730d 564 complain_at(muscle_percent_define_get_loc (variable),
922bdd7f 565 _("invalid value for %%define Boolean variable `%s'"),
cbd50549
JD
566 variable);
567 }
f124d423 568 free (value);
9611cfa2
JD
569 }
570 else
571 fatal(_("undefined %%define variable `%s' passed to muscle_percent_define_flag_if"),
572 variable);
573
9611cfa2
JD
574 return result;
575}
576
577void
578muscle_percent_define_default (char const *variable, char const *value)
579{
580 char const *name;
581 char const *loc_name;
35b8730d 582 char const *syncline_name;
9611cfa2
JD
583 MUSCLE_USER_NAME_CONVERT (name, "percent_define(", variable, ")");
584 MUSCLE_USER_NAME_CONVERT (loc_name, "percent_define_loc(", variable, ")");
35b8730d
JD
585 MUSCLE_USER_NAME_CONVERT (syncline_name,
586 "percent_define_syncline(", variable, ")");
9611cfa2
JD
587 if (!muscle_find_const (name))
588 {
589 location loc;
590 MUSCLE_INSERT_STRING (name, value);
92822aff
JD
591 loc.start.file = loc.end.file = "<default value>";
592 loc.start.line = loc.end.line = -1;
593 loc.start.column = loc.end.column = -1;
9611cfa2
JD
594 muscle_insert (loc_name, "");
595 muscle_location_grow (loc_name, loc);
35b8730d 596 muscle_insert (syncline_name, "");
9611cfa2
JD
597 }
598}
599
f124d423 600void
b1a81613 601muscle_percent_define_check_values (char const * const *values)
f124d423 602{
b1a81613
JD
603 for (; *values; ++values)
604 {
f4909773 605 char const * const *variablep = values;
b1a81613 606 char const *name;
b1a81613
JD
607 char *value;
608
f4909773 609 MUSCLE_USER_NAME_CONVERT (name, "percent_define(", *variablep, ")");
b1a81613
JD
610
611 value = muscle_string_decode (name);
612 if (value)
613 {
b1a81613
JD
614 for (++values; *values; ++values)
615 {
616 if (0 == strcmp (value, *values))
f4909773
JD
617 break;
618 }
619 if (!*values)
620 {
621 location loc = muscle_percent_define_get_loc (*variablep);
622 complain_at(loc,
623 _("invalid value for %%define variable `%s': `%s'"),
624 *variablep, value);
625 for (values = variablep + 1; *values; ++values)
626 complain_at (loc, _("accepted value: `%s'"), *values);
627 }
628 else
629 {
630 while (*values)
631 ++values;
b1a81613 632 }
b1a81613
JD
633 free (value);
634 }
635 else
f4909773
JD
636 fatal(_("undefined %%define variable `%s' passed to"
637 " muscle_percent_define_check_values"),
638 *variablep);
b1a81613 639 }
f124d423
JD
640}
641
9611cfa2
JD
642void
643muscle_percent_code_grow (char const *qualifier, location qualifier_loc,
644 char const *code, location code_loc)
645{
646 char const *name;
647 MUSCLE_USER_NAME_CONVERT (name, "percent_code(", qualifier, ")");
648 muscle_code_grow (name, code, code_loc);
649 muscle_user_name_list_grow ("percent_code_user_qualifiers", qualifier,
650 qualifier_loc);
651}
652
653
ae7453f2
AD
654/*------------------------------------------------.
655| Output the definition of ENTRY as a m4_define. |
656`------------------------------------------------*/
be2a1a68 657
e00b6826 658static inline bool
8322e8f5 659muscle_m4_output (muscle_entry *entry, FILE *out)
be2a1a68
AD
660{
661 fprintf (out, "m4_define([b4_%s],\n", entry->key);
ae7453f2 662 fprintf (out, "[[%s]])\n\n\n", entry->value);
e00b6826
PE
663 return true;
664}
665
666static bool
667muscle_m4_output_processor (void *entry, void *out)
668{
669 return muscle_m4_output (entry, out);
be2a1a68
AD
670}
671
672
ae7453f2
AD
673/*----------------------------------------------------------------.
674| Output the definition of all the current muscles into a list of |
675| m4_defines. |
676`----------------------------------------------------------------*/
be2a1a68
AD
677
678void
679muscles_m4_output (FILE *out)
680{
e00b6826 681 hash_do_for_each (muscle_table, muscle_m4_output_processor, out);
be2a1a68 682}