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 33typedef struct 34{ 35 const char *key; 36 char *value; 37} muscle_entry; 38 39/* An obstack used to create some entries. */ 40struct obstack muscle_obstack; 41 42/* Initial capacity of muscles hash table. */ 43#define HT_INITIAL_CAPACITY 257 44 45static struct hash_table *muscle_table = NULL; 46 47static bool 48hash_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 55static size_t 56hash_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 67void 68muscle_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 86void 87muscle_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 100void 101muscle_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 126void 127muscle_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 164void 165muscle_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 186void 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 201char * 202muscle_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 217static inline bool 218muscle_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 225static bool 226muscle_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 237void 238muscles_m4_output (FILE *out) 239{ 240 hash_do_for_each (muscle_table, muscle_m4_output_processor, out); 241} 242