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