105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Muscle table manager for Bison.
205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Copyright (C) 2001-2012 Free Software Foundation, Inc.
405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This file is part of Bison, the GNU Compiler Compiler.
605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This program is free software: you can redistribute it and/or modify
805436638acc7c010349a69c3395f1a57c642dc62Ying Wang   it under the terms of the GNU General Public License as published by
905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   the Free Software Foundation, either version 3 of the License, or
1005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   (at your option) any later version.
1105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This program is distributed in the hope that it will be useful,
1305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   but WITHOUT ANY WARRANTY; without even the implied warranty of
1405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   GNU General Public License for more details.
1605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   You should have received a copy of the GNU General Public License
1805436638acc7c010349a69c3395f1a57c642dc62Ying Wang   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
1905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <config.h>
2105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "system.h"
2205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <hash.h>
2405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "complain.h"
2605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "files.h"
2705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "getargs.h"
2805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "muscle-tab.h"
2905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "quote.h"
3005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
3105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* A key-value pair, along with storage that can be reclaimed when
3205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   this pair is no longer needed.  */
3305436638acc7c010349a69c3395f1a57c642dc62Ying Wangtypedef struct
3405436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
3505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *key;
3605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *value;
3705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char *storage;
3805436638acc7c010349a69c3395f1a57c642dc62Ying Wang} muscle_entry;
3905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
4005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* An obstack used to create some entries.  */
4105436638acc7c010349a69c3395f1a57c642dc62Ying Wangstruct obstack muscle_obstack;
4205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
4305436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Initial capacity of muscles hash table.  */
4405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define HT_INITIAL_CAPACITY 257
4505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
4605436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic struct hash_table *muscle_table = NULL;
4705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
4805436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic bool
4905436638acc7c010349a69c3395f1a57c642dc62Ying Wanghash_compare_muscles (void const *x, void const *y)
5005436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
5105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_entry const *m1 = x;
5205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_entry const *m2 = y;
5305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return strcmp (m1->key, m2->key) == 0;
5405436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
5505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
5605436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic size_t
5705436638acc7c010349a69c3395f1a57c642dc62Ying Wanghash_muscle (const void *x, size_t tablesize)
5805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
5905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_entry const *m = x;
6005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return hash_string (m->key, tablesize);
6105436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
6205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
6305436638acc7c010349a69c3395f1a57c642dc62Ying Wang/*-----------------------------------------------------------------.
6405436638acc7c010349a69c3395f1a57c642dc62Ying Wang| Create the MUSCLE_TABLE, and initialize it with default values.  |
6505436638acc7c010349a69c3395f1a57c642dc62Ying Wang| Also set up the MUSCLE_OBSTACK.                                  |
6605436638acc7c010349a69c3395f1a57c642dc62Ying Wang`-----------------------------------------------------------------*/
6705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
6805436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic void
6905436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_entry_free (void *entry)
7005436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
7105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_entry *mentry = entry;
7205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  free (mentry->storage);
7305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  free (mentry);
7405436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
7505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
7605436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid
7705436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_init (void)
7805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
7905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Initialize the muscle obstack.  */
8005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_init (&muscle_obstack);
8105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
8205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_table = hash_initialize (HT_INITIAL_CAPACITY, NULL, hash_muscle,
8305436638acc7c010349a69c3395f1a57c642dc62Ying Wang				  hash_compare_muscles, muscle_entry_free);
8405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
8505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Version and input file.  */
8605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  MUSCLE_INSERT_STRING ("version", VERSION);
8705436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
8805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
8905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
9005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/*------------------------------------------------------------.
9105436638acc7c010349a69c3395f1a57c642dc62Ying Wang| Free all the memory consumed by the muscle machinery only.  |
9205436638acc7c010349a69c3395f1a57c642dc62Ying Wang`------------------------------------------------------------*/
9305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
9405436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid
9505436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_free (void)
9605436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
9705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  hash_free (muscle_table);
9805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_free (&muscle_obstack, NULL);
9905436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
10005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
10105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
10205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
10305436638acc7c010349a69c3395f1a57c642dc62Ying Wang/*------------------------------------------------------------.
10405436638acc7c010349a69c3395f1a57c642dc62Ying Wang| Insert (KEY, VALUE).  If KEY already existed, overwrite the |
10505436638acc7c010349a69c3395f1a57c642dc62Ying Wang| previous value.                                             |
10605436638acc7c010349a69c3395f1a57c642dc62Ying Wang`------------------------------------------------------------*/
10705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
10805436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid
10905436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_insert (char const *key, char const *value)
11005436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
11105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_entry probe;
11205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_entry *entry;
11305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
11405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  probe.key = key;
11505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  entry = hash_lookup (muscle_table, &probe);
11605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
11705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (!entry)
11805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
11905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* First insertion in the hash. */
12005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      entry = xmalloc (sizeof *entry);
12105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      entry->key = key;
12205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (!hash_insert (muscle_table, entry))
12305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        xalloc_die ();
12405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
12505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else
12605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    free (entry->storage);
12705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  entry->value = value;
12805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  entry->storage = NULL;
12905436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
13005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
13105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
13205436638acc7c010349a69c3395f1a57c642dc62Ying Wang/*-------------------------------------------------------------------.
13305436638acc7c010349a69c3395f1a57c642dc62Ying Wang| Append VALUE to the current value of KEY.  If KEY did not already  |
13405436638acc7c010349a69c3395f1a57c642dc62Ying Wang| exist, create it.  Use MUSCLE_OBSTACK.  De-allocate the previously |
13505436638acc7c010349a69c3395f1a57c642dc62Ying Wang| associated value.  Copy VALUE and SEPARATOR.                       |
13605436638acc7c010349a69c3395f1a57c642dc62Ying Wang`-------------------------------------------------------------------*/
13705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
13805436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid
13905436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_grow (const char *key, const char *val, const char *separator)
14005436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
14105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_entry probe;
14205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_entry *entry = NULL;
14305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
14405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  probe.key = key;
14505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  entry = hash_lookup (muscle_table, &probe);
14605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
14705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (!entry)
14805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
14905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* First insertion in the hash. */
15005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      entry = xmalloc (sizeof *entry);
15105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      entry->key = key;
15205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (!hash_insert (muscle_table, entry))
15305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        xalloc_die ();
15405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      entry->value = entry->storage = xstrdup (val);
15505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
15605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else
15705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
15805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* Grow the current value. */
15905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      char *new_val;
16005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      obstack_sgrow (&muscle_obstack, entry->value);
16105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      free (entry->storage);
16205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      obstack_sgrow (&muscle_obstack, separator);
16305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      obstack_sgrow (&muscle_obstack, val);
16405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      obstack_1grow (&muscle_obstack, 0);
16505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      new_val = obstack_finish (&muscle_obstack);
16605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      entry->value = entry->storage = xstrdup (new_val);
16705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      obstack_free (&muscle_obstack, new_val);
16805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
16905436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
17005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
17105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/*------------------------------------------------------------------.
17205436638acc7c010349a69c3395f1a57c642dc62Ying Wang| Using muscle_grow, append a synchronization line for the location |
17305436638acc7c010349a69c3395f1a57c642dc62Ying Wang| LOC to the current value of KEY.                                  |
17405436638acc7c010349a69c3395f1a57c642dc62Ying Wang`------------------------------------------------------------------*/
17505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
17605436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic void
17705436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_syncline_grow (char const *key, location loc)
17805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
17905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char *extension = NULL;
18005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_printf (&muscle_obstack, "]b4_syncline(%d, ", loc.start.line);
18105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_quote (&muscle_obstack,
18205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                 quotearg_style (c_quoting_style, loc.start.file));
18305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_sgrow (&muscle_obstack, ")[");
18405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_1grow (&muscle_obstack, 0);
18505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  extension = obstack_finish (&muscle_obstack);
18605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_grow (key, extension, "");
18705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_free (&muscle_obstack, extension);
18805436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
18905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
19005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/*------------------------------------------------------------------.
19105436638acc7c010349a69c3395f1a57c642dc62Ying Wang| Append VALUE to the current value of KEY, using muscle_grow.  But |
19205436638acc7c010349a69c3395f1a57c642dc62Ying Wang| in addition, issue a synchronization line for the location LOC    |
19305436638acc7c010349a69c3395f1a57c642dc62Ying Wang| using muscle_syncline_grow.                                       |
19405436638acc7c010349a69c3395f1a57c642dc62Ying Wang`------------------------------------------------------------------*/
19505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
19605436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid
19705436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_code_grow (const char *key, const char *val, location loc)
19805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
19905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_syncline_grow (key, loc);
20005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_grow (key, val, "\n");
20105436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
20205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
20305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
20405436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid muscle_pair_list_grow (const char *muscle,
20505436638acc7c010349a69c3395f1a57c642dc62Ying Wang			    const char *a1, const char *a2)
20605436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
20705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char *pair;
20805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_sgrow (&muscle_obstack, "[");
20905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_quote (&muscle_obstack, a1);
21005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_sgrow (&muscle_obstack, ", ");
21105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_quote (&muscle_obstack, a2);
21205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_sgrow (&muscle_obstack, "]");
21305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_1grow (&muscle_obstack, 0);
21405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  pair = obstack_finish (&muscle_obstack);
21505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_grow (muscle, pair, ",\n");
21605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_free (&muscle_obstack, pair);
21705436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
21805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
21905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
22005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/*----------------------------------------------------------------------------.
22105436638acc7c010349a69c3395f1a57c642dc62Ying Wang| Find the value of muscle KEY.  Unlike MUSCLE_FIND, this is always reliable  |
22205436638acc7c010349a69c3395f1a57c642dc62Ying Wang| to determine whether KEY has a value.                                       |
22305436638acc7c010349a69c3395f1a57c642dc62Ying Wang`----------------------------------------------------------------------------*/
22405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
22505436638acc7c010349a69c3395f1a57c642dc62Ying Wangchar const *
22605436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_find_const (char const *key)
22705436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
22805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_entry probe;
22905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_entry *result = NULL;
23005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
23105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  probe.key = key;
23205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  result = hash_lookup (muscle_table, &probe);
23305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (result)
23405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return result->value;
23505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return NULL;
23605436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
23705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
23805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
23905436638acc7c010349a69c3395f1a57c642dc62Ying Wang/*----------------------------------------------------------------------------.
24005436638acc7c010349a69c3395f1a57c642dc62Ying Wang| Find the value of muscle KEY.  Abort if muscle_insert was invoked more      |
24105436638acc7c010349a69c3395f1a57c642dc62Ying Wang| recently than muscle_grow for KEY since muscle_find can't return a          |
24205436638acc7c010349a69c3395f1a57c642dc62Ying Wang| char const *.                                                               |
24305436638acc7c010349a69c3395f1a57c642dc62Ying Wang`----------------------------------------------------------------------------*/
24405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
24505436638acc7c010349a69c3395f1a57c642dc62Ying Wangchar *
24605436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_find (char const *key)
24705436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
24805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_entry probe;
24905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_entry *result = NULL;
25005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
25105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  probe.key = key;
25205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  result = hash_lookup (muscle_table, &probe);
25305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (result)
25405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
25505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      aver (result->value == result->storage);
25605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      return result->storage;
25705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
25805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return NULL;
25905436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
26005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
26105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
26205436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* In the format `file_name:line.column', append BOUND to MUSCLE.  Use
26305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   digraphs for special characters in the file name.  */
26405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
26505436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic void
26605436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_boundary_grow (char const *key, boundary bound)
26705436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
26805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char *extension;
26905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_sgrow  (&muscle_obstack, "[[");
27005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_escape (&muscle_obstack, bound.file);
27105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_1grow  (&muscle_obstack, ':');
27205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_printf (&muscle_obstack, "%d", bound.line);
27305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_1grow  (&muscle_obstack, '.');
27405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_printf (&muscle_obstack, "%d", bound.column);
27505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_sgrow  (&muscle_obstack, "]]");
27605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_1grow  (&muscle_obstack, '\0');
27705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  extension = obstack_finish (&muscle_obstack);
27805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_grow (key, extension, "");
27905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_free (&muscle_obstack, extension);
28005436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
28105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
28205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
28305436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* In the format `[[file_name:line.column]], [[file_name:line.column]]',
28405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   append LOC to MUSCLE.  Use digraphs for special characters in each
28505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   file name.  */
28605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
28705436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic void
28805436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_location_grow (char const *key, location loc)
28905436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
29005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_boundary_grow (key, loc.start);
29105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_grow (key, "", ", ");
29205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_boundary_grow (key, loc.end);
29305436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
29405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
29505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define COMMON_DECODE(Value)                                    \
29605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  case '$':                                                     \
29705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    aver (*++(Value) == ']');                                   \
29805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    aver (*++(Value) == '[');                                   \
29905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    obstack_sgrow (&muscle_obstack, "$");                       \
30005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    break;                                                      \
30105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  case '@':                                                     \
30205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    switch (*++(Value))                                         \
30305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      {                                                         \
30405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        case '@': obstack_sgrow (&muscle_obstack, "@" ); break; \
30505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        case '{': obstack_sgrow (&muscle_obstack, "[" ); break; \
30605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        case '}': obstack_sgrow (&muscle_obstack, "]" ); break; \
30705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        default: aver (false); break;                           \
30805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      }                                                         \
30905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    break;                                                      \
31005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  default:                                                      \
31105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    obstack_1grow (&muscle_obstack, *(Value));                  \
31205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    break;
31305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
31405436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Reverse of obstack_escape.  */
31505436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic char *
31605436638acc7c010349a69c3395f1a57c642dc62Ying Wangstring_decode (char const *key)
31705436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
31805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *value;
31905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char *value_decoded;
32005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char *result;
32105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
32205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  value = muscle_find_const (key);
32305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (!value)
32405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    return NULL;
32505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  do {
32605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    switch (*value)
32705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      {
32805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        COMMON_DECODE (value)
32905436638acc7c010349a69c3395f1a57c642dc62Ying Wang        case '[':
33005436638acc7c010349a69c3395f1a57c642dc62Ying Wang        case ']':
33105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          aver (false);
33205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          break;
33305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      }
33405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  } while (*value++);
33505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  value_decoded = obstack_finish (&muscle_obstack);
33605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  result = xstrdup (value_decoded);
33705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  obstack_free (&muscle_obstack, value_decoded);
33805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return result;
33905436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
34005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
34105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Reverse of muscle_location_grow.  */
34205436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic location
34305436638acc7c010349a69c3395f1a57c642dc62Ying Wanglocation_decode (char const *key)
34405436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
34505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  location loc;
34605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *value = muscle_find_const (key);
34705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  aver (value);
34805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  aver (*value == '[');
34905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  aver (*++value == '[');
35005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  while (*++value)
35105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    switch (*value)
35205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      {
35305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        COMMON_DECODE (value)
35405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        case '[':
35505436638acc7c010349a69c3395f1a57c642dc62Ying Wang          aver (false);
35605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          break;
35705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        case ']':
35805436638acc7c010349a69c3395f1a57c642dc62Ying Wang          {
35905436638acc7c010349a69c3395f1a57c642dc62Ying Wang            char *boundary_str;
36005436638acc7c010349a69c3395f1a57c642dc62Ying Wang            aver (*++value == ']');
36105436638acc7c010349a69c3395f1a57c642dc62Ying Wang            obstack_1grow (&muscle_obstack, '\0');
36205436638acc7c010349a69c3395f1a57c642dc62Ying Wang            boundary_str = obstack_finish (&muscle_obstack);
36305436638acc7c010349a69c3395f1a57c642dc62Ying Wang            switch (*++value)
36405436638acc7c010349a69c3395f1a57c642dc62Ying Wang              {
36505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                case ',':
36605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  boundary_set_from_string (&loc.start, boundary_str);
36705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  obstack_free (&muscle_obstack, boundary_str);
36805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  aver (*++value == ' ');
36905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  aver (*++value == '[');
37005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  aver (*++value == '[');
37105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  break;
37205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                case '\0':
37305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  boundary_set_from_string (&loc.end, boundary_str);
37405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  obstack_free (&muscle_obstack, boundary_str);
37505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  return loc;
37605436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  break;
37705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                default:
37805436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  aver (false);
37905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                  break;
38005436638acc7c010349a69c3395f1a57c642dc62Ying Wang              }
38105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          }
38205436638acc7c010349a69c3395f1a57c642dc62Ying Wang          break;
38305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      }
38405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  aver (false);
38505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return loc;
38605436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
38705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
38805436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid
38905436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_user_name_list_grow (char const *key, char const *user_name,
39005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                            location loc)
39105436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
39205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_grow (key, "[[[[", ",");
39305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_grow (key, user_name, "");
39405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_grow (key, "]], ", "");
39505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_location_grow (key, loc);
39605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_grow (key, "]]", "");
39705436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
39805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
39905436638acc7c010349a69c3395f1a57c642dc62Ying Wang/** If the \a variable name is obsolete, return the name to use,
40005436638acc7c010349a69c3395f1a57c642dc62Ying Wang * otherwise \a variable. */
40105436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic
40205436638acc7c010349a69c3395f1a57c642dc62Ying Wangchar const *
40305436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_percent_variable_update (char const *variable)
40405436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
40505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  typedef struct
40605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  {
40705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    const char *obsolete;
40805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    const char *updated;
40905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  } conversion_type;
41005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  const conversion_type conversion[] =
41105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
41205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      { "api.push_pull", "api.push-pull", },
41305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      { "location_type", "api.location.type", },
41405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      { "lr.keep_unreachable_states", "lr.keep-unreachable-states", },
41505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    };
41605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *res = variable;
41705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  int i;
41805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  for (i = 0; i < ARRAY_CARDINALITY (conversion); ++i)
41905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    if (STREQ (conversion[i].obsolete, variable))
42005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      {
42105436638acc7c010349a69c3395f1a57c642dc62Ying Wang        res = conversion[i].updated;
42205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        break;
42305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      }
42405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return res;
42505436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
42605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
42705436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid
42805436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_percent_define_insert (char const *var, location variable_loc,
42905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              char const *value,
43005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              muscle_percent_define_how how)
43105436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
43205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Backward compatibility.  */
43305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *variable = muscle_percent_variable_update (var);
43405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
43505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
43605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *syncline_name =
43705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
43805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *how_name = UNIQSTR_CONCAT ("percent_define_how(", variable, ")");
43905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
44005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* Command-line options are processed before the grammar file.  */
44105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (how == MUSCLE_PERCENT_DEFINE_GRAMMAR_FILE
44205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      && muscle_find_const (name))
44305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
44405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      unsigned i = 0;
44505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      muscle_percent_define_how how_old =
44605436638acc7c010349a69c3395f1a57c642dc62Ying Wang        atoi (muscle_find_const (how_name));
44705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (how_old == MUSCLE_PERCENT_DEFINE_F)
44805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        return;
44905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      complain_at_indent (variable_loc, &i,
45005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          _("%%define variable %s redefined"), quote (variable));
45105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      i += SUB_INDENT;
45205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      complain_at_indent (muscle_percent_define_get_loc (variable), &i,
45305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          _("previous definition"));
45405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
45505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
45605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  MUSCLE_INSERT_STRING (name, value);
45705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_insert (loc_name, "");
45805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_location_grow (loc_name, variable_loc);
45905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_insert (syncline_name, "");
46005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_syncline_grow (syncline_name, variable_loc);
46105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_user_name_list_grow ("percent_define_user_variables", variable,
46205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                              variable_loc);
46305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  MUSCLE_INSERT_INT (how_name, how);
46405436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
46505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
46605436638acc7c010349a69c3395f1a57c642dc62Ying Wangchar *
46705436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_percent_define_get (char const *variable)
46805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
46905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *name;
47005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *usage_name;
47105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char *value;
47205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
47305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
47405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  usage_name = UNIQSTR_CONCAT ("percent_define_bison_variables(",
47505436638acc7c010349a69c3395f1a57c642dc62Ying Wang                               variable, ")");
47605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
47705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_insert (usage_name, "");
47805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  value = string_decode (name);
47905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (!value)
48005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    value = xstrdup ("");
48105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return value;
48205436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
48305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
48405436638acc7c010349a69c3395f1a57c642dc62Ying Wanglocation
48505436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_percent_define_get_loc (char const *variable)
48605436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
48705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *loc_name;
48805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
48905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (!muscle_find_const (loc_name))
49005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    fatal(_("%s: undefined %%define variable %s"),
49105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          "muscle_percent_define_get_loc", quote (variable));
49205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return location_decode (loc_name);
49305436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
49405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
49505436638acc7c010349a69c3395f1a57c642dc62Ying Wangchar const *
49605436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_percent_define_get_syncline (char const *variable)
49705436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
49805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *syncline_name;
49905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *syncline;
50005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  syncline_name =
50105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
50205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  syncline = muscle_find_const (syncline_name);
50305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (!syncline)
50405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    fatal(_("%s: undefined %%define variable %s"),
50505436638acc7c010349a69c3395f1a57c642dc62Ying Wang          "muscle_percent_define_get_syncline", quote (variable));
50605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return syncline;
50705436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
50805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
50905436638acc7c010349a69c3395f1a57c642dc62Ying Wangbool
51005436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_percent_define_ifdef (char const *variable)
51105436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
51205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *name;
51305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *usage_name;
51405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *value;
51505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
51605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
51705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  usage_name =
51805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    UNIQSTR_CONCAT ("percent_define_bison_variables(", variable, ")");
51905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
52005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  value = muscle_find_const (name);
52105436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (value)
52205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
52305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      muscle_insert (usage_name, "");
52405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      return true;
52505436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
52605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
52705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return false;
52805436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
52905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
53005436638acc7c010349a69c3395f1a57c642dc62Ying Wangbool
53105436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_percent_define_flag_if (char const *variable)
53205436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
53305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *invalid_boolean_name;
53405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  bool result = false;
53505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
53605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  invalid_boolean_name =
53705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    UNIQSTR_CONCAT ("percent_define_invalid_boolean(", variable, ")");
53805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
53905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (muscle_percent_define_ifdef (variable))
54005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
54105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      char *value = muscle_percent_define_get (variable);
54205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (value[0] == '\0' || 0 == strcmp (value, "true"))
54305436638acc7c010349a69c3395f1a57c642dc62Ying Wang        result = true;
54405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else if (0 == strcmp (value, "false"))
54505436638acc7c010349a69c3395f1a57c642dc62Ying Wang        result = false;
54605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else if (!muscle_find_const (invalid_boolean_name))
54705436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
54805436638acc7c010349a69c3395f1a57c642dc62Ying Wang          muscle_insert (invalid_boolean_name, "");
54905436638acc7c010349a69c3395f1a57c642dc62Ying Wang          complain_at(muscle_percent_define_get_loc (variable),
55005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      _("invalid value for %%define Boolean variable %s"),
55105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                      quote (variable));
55205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
55305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      free (value);
55405436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
55505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  else
55605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    fatal(_("%s: undefined %%define variable %s"),
55705436638acc7c010349a69c3395f1a57c642dc62Ying Wang          "muscle_percent_define_flag", quote (variable));
55805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
55905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return result;
56005436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
56105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
56205436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid
56305436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_percent_define_default (char const *variable, char const *value)
56405436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
56505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *name;
56605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *loc_name;
56705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *syncline_name;
56805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  name = UNIQSTR_CONCAT ("percent_define(", variable, ")");
56905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
57005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  syncline_name =
57105436638acc7c010349a69c3395f1a57c642dc62Ying Wang    UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
57205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (!muscle_find_const (name))
57305436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
57405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      location loc;
57505436638acc7c010349a69c3395f1a57c642dc62Ying Wang      MUSCLE_INSERT_STRING (name, value);
57605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      loc.start.file = loc.end.file = "<default value>";
57705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      loc.start.line = loc.end.line = -1;
57805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      loc.start.column = loc.end.column = -1;
57905436638acc7c010349a69c3395f1a57c642dc62Ying Wang      muscle_insert (loc_name, "");
58005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      muscle_location_grow (loc_name, loc);
58105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      muscle_insert (syncline_name, "");
58205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
58305436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
58405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
58505436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid
58605436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_percent_define_check_values (char const * const *values)
58705436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
58805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  for (; *values; ++values)
58905436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
59005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      char const * const *variablep = values;
59105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      char const *name;
59205436638acc7c010349a69c3395f1a57c642dc62Ying Wang      char *value;
59305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
59405436638acc7c010349a69c3395f1a57c642dc62Ying Wang      name = UNIQSTR_CONCAT ("percent_define(", *variablep, ")");
59505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
59605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      value = string_decode (name);
59705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      if (value)
59805436638acc7c010349a69c3395f1a57c642dc62Ying Wang        {
59905436638acc7c010349a69c3395f1a57c642dc62Ying Wang          for (++values; *values; ++values)
60005436638acc7c010349a69c3395f1a57c642dc62Ying Wang            {
60105436638acc7c010349a69c3395f1a57c642dc62Ying Wang              if (0 == strcmp (value, *values))
60205436638acc7c010349a69c3395f1a57c642dc62Ying Wang                break;
60305436638acc7c010349a69c3395f1a57c642dc62Ying Wang            }
60405436638acc7c010349a69c3395f1a57c642dc62Ying Wang          if (!*values)
60505436638acc7c010349a69c3395f1a57c642dc62Ying Wang            {
60605436638acc7c010349a69c3395f1a57c642dc62Ying Wang              unsigned i = 0;
60705436638acc7c010349a69c3395f1a57c642dc62Ying Wang              location loc = muscle_percent_define_get_loc (*variablep);
60805436638acc7c010349a69c3395f1a57c642dc62Ying Wang              complain_at_indent (loc, &i,
60905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                _("invalid value for %%define variable %s: %s"),
61005436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                  quote (*variablep), quote_n (1, value));
61105436638acc7c010349a69c3395f1a57c642dc62Ying Wang              i += SUB_INDENT;
61205436638acc7c010349a69c3395f1a57c642dc62Ying Wang              for (values = variablep + 1; *values; ++values)
61305436638acc7c010349a69c3395f1a57c642dc62Ying Wang                complain_at_indent (loc, &i, _("accepted value: %s"),
61405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                                    quote (*values));
61505436638acc7c010349a69c3395f1a57c642dc62Ying Wang            }
61605436638acc7c010349a69c3395f1a57c642dc62Ying Wang          else
61705436638acc7c010349a69c3395f1a57c642dc62Ying Wang            {
61805436638acc7c010349a69c3395f1a57c642dc62Ying Wang              while (*values)
61905436638acc7c010349a69c3395f1a57c642dc62Ying Wang                ++values;
62005436638acc7c010349a69c3395f1a57c642dc62Ying Wang            }
62105436638acc7c010349a69c3395f1a57c642dc62Ying Wang          free (value);
62205436638acc7c010349a69c3395f1a57c642dc62Ying Wang        }
62305436638acc7c010349a69c3395f1a57c642dc62Ying Wang      else
62405436638acc7c010349a69c3395f1a57c642dc62Ying Wang        fatal (_("%s: undefined %%define variable %s"),
62505436638acc7c010349a69c3395f1a57c642dc62Ying Wang               "muscle_percent_define_check_values", quote (*variablep));
62605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
62705436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
62805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
62905436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid
63005436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_percent_code_grow (char const *qualifier, location qualifier_loc,
63105436638acc7c010349a69c3395f1a57c642dc62Ying Wang                          char const *code, location code_loc)
63205436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
63305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  char const *name;
63405436638acc7c010349a69c3395f1a57c642dc62Ying Wang  name = UNIQSTR_CONCAT ("percent_code(", qualifier, ")");
63505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_code_grow (name, code, code_loc);
63605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  muscle_user_name_list_grow ("percent_code_user_qualifiers", qualifier,
63705436638acc7c010349a69c3395f1a57c642dc62Ying Wang                               qualifier_loc);
63805436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
63905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
64005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
64105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/*------------------------------------------------.
64205436638acc7c010349a69c3395f1a57c642dc62Ying Wang| Output the definition of ENTRY as a m4_define.  |
64305436638acc7c010349a69c3395f1a57c642dc62Ying Wang`------------------------------------------------*/
64405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
64505436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic inline bool
64605436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_m4_output (muscle_entry *entry, FILE *out)
64705436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
64805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  fprintf (out, "m4_define([b4_%s],\n", entry->key);
64905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  fprintf (out, "[[%s]])\n\n\n", entry->value);
65005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return true;
65105436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
65205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
65305436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic bool
65405436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscle_m4_output_processor (void *entry, void *out)
65505436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
65605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return muscle_m4_output (entry, out);
65705436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
65805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
65905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
66005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/*----------------------------------------------------------------.
66105436638acc7c010349a69c3395f1a57c642dc62Ying Wang| Output the definition of all the current muscles into a list of |
66205436638acc7c010349a69c3395f1a57c642dc62Ying Wang| m4_defines.                                                     |
66305436638acc7c010349a69c3395f1a57c642dc62Ying Wang`----------------------------------------------------------------*/
66405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
66505436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid
66605436638acc7c010349a69c3395f1a57c642dc62Ying Wangmuscles_m4_output (FILE *out)
66705436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
66805436638acc7c010349a69c3395f1a57c642dc62Ying Wang  hash_do_for_each (muscle_table, muscle_m4_output_processor, out);
66905436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
670