Home | History | Annotate | Download | only in src
      1 /* Muscle table manager for Bison.
      2 
      3    Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software
      4    Foundation, Inc.
      5 
      6    This file is part of Bison, the GNU Compiler Compiler.
      7 
      8    Bison is free software; you can redistribute it and/or modify
      9    it under the terms of the GNU General Public License as published by
     10    the Free Software Foundation; either version 2, or (at your option)
     11    any later version.
     12 
     13    Bison is distributed in the hope that it will be useful,
     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
     19    along with Bison; see the file COPYING.  If not, write to
     20    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     21    Boston, MA 02110-1301, USA.  */
     22 
     23 #include <config.h>
     24 #include "system.h"
     25 
     26 #include <hash.h>
     27 #include <quotearg.h>
     28 
     29 #include "files.h"
     30 #include "muscle_tab.h"
     31 #include "getargs.h"
     32 
     33 typedef struct
     34 {
     35   const char *key;
     36   char *value;
     37 } muscle_entry;
     38 
     39 /* An obstack used to create some entries.  */
     40 struct obstack muscle_obstack;
     41 
     42 /* Initial capacity of muscles hash table.  */
     43 #define HT_INITIAL_CAPACITY 257
     44 
     45 static struct hash_table *muscle_table = NULL;
     46 
     47 static bool
     48 hash_compare_muscles (void const *x, void const *y)
     49 {
     50   muscle_entry const *m1 = x;
     51   muscle_entry const *m2 = y;
     52   return strcmp (m1->key, m2->key) == 0;
     53 }
     54 
     55 static size_t
     56 hash_muscle (const void *x, size_t tablesize)
     57 {
     58   muscle_entry const *m = x;
     59   return hash_string (m->key, tablesize);
     60 }
     61 
     62 /*-----------------------------------------------------------------.
     63 | Create the MUSCLE_TABLE, and initialize it with default values.  |
     64 | Also set up the MUSCLE_OBSTACK.                                  |
     65 `-----------------------------------------------------------------*/
     66 
     67 void
     68 muscle_init (void)
     69 {
     70   /* Initialize the muscle obstack.  */
     71   obstack_init (&muscle_obstack);
     72 
     73   muscle_table = hash_initialize (HT_INITIAL_CAPACITY, NULL, hash_muscle,
     74 				  hash_compare_muscles, free);
     75 
     76   /* Version and input file.  */
     77   MUSCLE_INSERT_STRING ("version", VERSION);
     78   MUSCLE_INSERT_C_STRING ("file_name", grammar_file);
     79 }
     80 
     81 
     82 /*------------------------------------------------------------.
     83 | Free all the memory consumed by the muscle machinery only.  |
     84 `------------------------------------------------------------*/
     85 
     86 void
     87 muscle_free (void)
     88 {
     89   hash_free (muscle_table);
     90   obstack_free (&muscle_obstack, NULL);
     91 }
     92 
     93 
     94 
     95 /*------------------------------------------------------------.
     96 | Insert (KEY, VALUE).  If KEY already existed, overwrite the |
     97 | previous value.                                             |
     98 `------------------------------------------------------------*/
     99 
    100 void
    101 muscle_insert (const char *key, char *value)
    102 {
    103   muscle_entry probe;
    104   muscle_entry *entry;
    105 
    106   probe.key = key;
    107   entry = hash_lookup (muscle_table, &probe);
    108 
    109   if (!entry)
    110     {
    111       /* First insertion in the hash. */
    112       entry = xmalloc (sizeof *entry);
    113       entry->key = key;
    114       hash_insert (muscle_table, entry);
    115     }
    116   entry->value = value;
    117 }
    118 
    119 
    120 /*-------------------------------------------------------------------.
    121 | Append VALUE to the current value of KEY.  If KEY did not already  |
    122 | exist, create it.  Use MUSCLE_OBSTACK.  De-allocate the previously |
    123 | associated value.  Copy VALUE and SEPARATOR.                       |
    124 `-------------------------------------------------------------------*/
    125 
    126 void
    127 muscle_grow (const char *key, const char *val, const char *separator)
    128 {
    129   muscle_entry probe;
    130   muscle_entry *entry = NULL;
    131 
    132   probe.key = key;
    133   entry = hash_lookup (muscle_table, &probe);
    134 
    135   if (!entry)
    136     {
    137       /* First insertion in the hash. */
    138       entry = xmalloc (sizeof *entry);
    139       entry->key = key;
    140       hash_insert (muscle_table, entry);
    141       entry->value = xstrdup (val);
    142     }
    143   else
    144     {
    145       /* Grow the current value. */
    146       char *new_val;
    147       obstack_sgrow (&muscle_obstack, entry->value);
    148       free (entry->value);
    149       obstack_sgrow (&muscle_obstack, separator);
    150       obstack_sgrow (&muscle_obstack, val);
    151       obstack_1grow (&muscle_obstack, 0);
    152       new_val = obstack_finish (&muscle_obstack);
    153       entry->value = xstrdup (new_val);
    154       obstack_free (&muscle_obstack, new_val);
    155     }
    156 }
    157 
    158 
    159 /*------------------------------------------------------------------.
    160 | Append VALUE to the current value of KEY, using muscle_grow.  But |
    161 | in addition, issue a synchronization line for the location LOC.   |
    162 `------------------------------------------------------------------*/
    163 
    164 void
    165 muscle_code_grow (const char *key, const char *val, location loc)
    166 {
    167   char *extension = NULL;
    168   obstack_fgrow1 (&muscle_obstack, "]b4_syncline(%d, [[", loc.start.line);
    169   MUSCLE_OBSTACK_SGROW (&muscle_obstack,
    170 			quotearg_style (c_quoting_style, loc.start.file));
    171   obstack_sgrow (&muscle_obstack, "]])[\n");
    172   obstack_sgrow (&muscle_obstack, val);
    173   obstack_1grow (&muscle_obstack, 0);
    174   extension = obstack_finish (&muscle_obstack);
    175   muscle_grow (key, extension, "");
    176 }
    177 
    178 
    179 /*-------------------------------------------------------------------.
    180 | MUSCLE is an M4 list of pairs.  Create or extend it with the pair  |
    181 | (A1, A2).  Note that because the muscle values are output *double* |
    182 | quoted, one needs to strip the first level of quotes to reach the  |
    183 | list itself.                                                       |
    184 `-------------------------------------------------------------------*/
    185 
    186 void muscle_pair_list_grow (const char *muscle,
    187 			    const char *a1, const char *a2)
    188 {
    189   char *pair;
    190   obstack_fgrow2 (&muscle_obstack, "[[[%s]], [[%s]]]", a1, a2);
    191   obstack_1grow (&muscle_obstack, 0);
    192   pair = obstack_finish (&muscle_obstack);
    193   muscle_grow (muscle, pair, ",\n");
    194   obstack_free (&muscle_obstack, pair);
    195 }
    196 
    197 /*-------------------------------.
    198 | Find the value of muscle KEY.  |
    199 `-------------------------------*/
    200 
    201 char *
    202 muscle_find (const char *key)
    203 {
    204   muscle_entry probe;
    205   muscle_entry *result = NULL;
    206 
    207   probe.key = key;
    208   result = hash_lookup (muscle_table, &probe);
    209   return result ? result->value : NULL;
    210 }
    211 
    212 
    213 /*------------------------------------------------.
    214 | Output the definition of ENTRY as a m4_define.  |
    215 `------------------------------------------------*/
    216 
    217 static inline bool
    218 muscle_m4_output (muscle_entry *entry, FILE *out)
    219 {
    220   fprintf (out, "m4_define([b4_%s],\n", entry->key);
    221   fprintf (out, "[[%s]])\n\n\n", entry->value);
    222   return true;
    223 }
    224 
    225 static bool
    226 muscle_m4_output_processor (void *entry, void *out)
    227 {
    228   return muscle_m4_output (entry, out);
    229 }
    230 
    231 
    232 /*----------------------------------------------------------------.
    233 | Output the definition of all the current muscles into a list of |
    234 | m4_defines.                                                     |
    235 `----------------------------------------------------------------*/
    236 
    237 void
    238 muscles_m4_output (FILE *out)
    239 {
    240   hash_do_for_each (muscle_table, muscle_m4_output_processor, out);
    241 }
    242