File indexing completed on 2025-01-26 04:44:00
0001 /* ------------------------------------------------------------------------ 0002 @NAME : macros.c 0003 @DESCRIPTION: Front-end to the standard PCCTS symbol table code (sym.c) 0004 to abstract my "macro table". 0005 @GLOBALS : 0006 @CALLS : 0007 @CREATED : 1997/01/12, Greg Ward 0008 @MODIFIED : 0009 @VERSION : $Id: macros.c,v 1.19 1999/11/29 01:13:10 greg Rel $ 0010 @COPYRIGHT : Copyright (c) 1996-99 by Gregory P. Ward. All rights reserved. 0011 0012 This file is part of the btparse library. This library is 0013 free software; you can redistribute it and/or modify it under 0014 the terms of the GNU General Public License as 0015 published by the Free Software Foundation; either version 2 0016 of the License, or (at your option) any later version. 0017 -------------------------------------------------------------------------- */ 0018 /*#include "bt_config.h"*/ 0019 #include <stdlib.h> 0020 #include <string.h> 0021 #include "sym.h" 0022 #include "prototypes.h" 0023 #include "error.h" 0024 /*#include "my_dmalloc.h"*/ 0025 #include "bt_debug.h" 0026 0027 0028 /* 0029 * NUM_MACROS and STRING_SIZE define the size of the static data 0030 * structure that holds the macro table. The defaults are to allocate 0031 * 4096 bytes of string space that will be divided up amongst 547 0032 * macros. This should be fine for most applications, but if you have a 0033 * big macro table you might need to change these and recompile (don't 0034 * forget to rebuild and reinstall Text::BibTeX if you're using it!). 0035 * You can set these as high as you like; just remember that a block of 0036 * STRING_SIZE bytes will be allocated and not freed as long as you're 0037 * using btparse. Also, NUM_MACROS defines the size of a hashtable, so 0038 * it should probably be a prime a bit greater than a power of 2 -- or 0039 * something like that. I'm not sure of the exact Knuthian 0040 * specification. 0041 */ 0042 #define NUM_MACROS 547 0043 #define STRING_SIZE 4096 0044 0045 Sym *AllMacros = NULL; /* `scope' so we can get back list */ 0046 /* of all macros when done */ 0047 0048 0049 GEN_PRIVATE_ERRFUNC (macro_warning, 0050 (const char * filename, int line, const char * fmt, ...), 0051 BTERR_CONTENT, filename, line, NULL, -1, fmt) 0052 0053 0054 /* ------------------------------------------------------------------------ 0055 @NAME : init_macros() 0056 @INPUT : 0057 @OUTPUT : 0058 @RETURNS : 0059 @DESCRIPTION: Initializes the symbol table used to store macro values. 0060 @GLOBALS : AllMacros 0061 @CALLS : zzs_init(), zzs_scope() (sym.c) 0062 @CALLERS : bt_initialize() (init.c) 0063 @CREATED : Jan 1997, GPW 0064 -------------------------------------------------------------------------- */ 0065 void 0066 init_macros (void) 0067 { 0068 zzs_init (NUM_MACROS, STRING_SIZE); 0069 zzs_scope (&AllMacros); 0070 } 0071 0072 0073 /* ------------------------------------------------------------------------ 0074 @NAME : done_macros() 0075 @INPUT : 0076 @OUTPUT : 0077 @RETURNS : 0078 @DESCRIPTION: Frees up all the macro values in the symbol table, and 0079 then frees up the symbol table itself. 0080 @GLOBALS : AllMacros 0081 @CALLS : zzs_rmscope(), zzs_done() 0082 @CALLERS : bt_cleanup() (init.c) 0083 @CREATED : Jan 1997, GPW 0084 -------------------------------------------------------------------------- */ 0085 void 0086 done_macros (void) 0087 { 0088 bt_delete_all_macros (); 0089 zzs_done (); 0090 } 0091 0092 0093 static void 0094 delete_macro_entry (Sym * sym) 0095 { 0096 Sym * cur; 0097 Sym * prev; 0098 0099 /* 0100 * Yechh! All this mucking about with the scope list really 0101 * ought to be handled by the symbol table code. Must write 0102 * my own someday. 0103 */ 0104 0105 /* Find this entry in the list of all macro table entries */ 0106 cur = AllMacros; 0107 prev = NULL; 0108 while (cur != NULL && cur != sym) 0109 { 0110 prev = cur; 0111 cur = cur->scope; 0112 } 0113 0114 if (cur == NULL) /* uh-oh -- wasn't found! */ 0115 { 0116 internal_error ("macro table entry for \"%s\" not found in scope list", 0117 sym->symbol); 0118 } 0119 0120 /* Now unlink from the "scope" list */ 0121 if (prev == NULL) /* it's the head of the list */ 0122 AllMacros = cur->scope; 0123 else 0124 prev->scope = cur->scope; 0125 0126 /* Remove it from the macro hash table */ 0127 zzs_del (sym); 0128 0129 /* And finally, free up the entry's text and the entry itself */ 0130 if (sym->text) free (sym->text); 0131 free (sym); 0132 } /* delete_macro_entry() */ 0133 0134 0135 /* ------------------------------------------------------------------------ 0136 @NAME : bt_add_macro_value() 0137 @INPUT : assignment - AST node representing "macro = value" 0138 options - string-processing options that were used to 0139 process this string after parsing 0140 @OUTPUT : 0141 @RETURNS : 0142 @DESCRIPTION: Adds a value to the symbol table used for macros. 0143 0144 If the value was not already post-processed as a macro value 0145 (expand macros, paste substrings, but don't collapse 0146 whitespace), then this post-processing is done before adding 0147 the macro text to the table. 0148 0149 If the macro is already defined, a warning is printed and 0150 the old text is overridden. 0151 @GLOBALS : 0152 @CALLS : bt_add_macro_text() 0153 bt_postprocess_field() 0154 @CALLERS : bt_postprocess_entry() (post_parse.c) 0155 @CREATED : Jan 1997, GPW 0156 -------------------------------------------------------------------------- */ 0157 void 0158 bt_add_macro_value (AST *assignment, ushort options) 0159 { 0160 AST * value; 0161 char * macro; 0162 char * text; 0163 boolean free_text; 0164 0165 if (assignment == NULL || assignment->down == NULL) return; 0166 value = assignment->down; 0167 0168 /* 0169 * If the options that were used to process the macro's expansion text 0170 * are anything other than BTO_MACRO, then we'll have to do it ourselves. 0171 */ 0172 0173 if ((options & BTO_STRINGMASK) != BTO_MACRO) 0174 { 0175 text = bt_postprocess_field (assignment, BTO_MACRO, FALSE); 0176 free_text = TRUE; /* because it's alloc'd by */ 0177 /* bt_postprocess_field() */ 0178 } 0179 else 0180 { 0181 /* 0182 * First a sanity check to make sure that the presumed post-processing 0183 * had the desired effect. 0184 */ 0185 0186 if (value->nodetype != BTAST_STRING || value->right != NULL) 0187 { 0188 internal_error ("add_macro: macro value was not " 0189 "correctly preprocessed"); 0190 } 0191 0192 text = assignment->down->text; 0193 free_text = FALSE; 0194 } 0195 0196 macro = assignment->text; 0197 bt_add_macro_text (macro, text, assignment->filename, assignment->line); 0198 if (free_text && text != NULL) 0199 free (text); 0200 0201 } /* bt_add_macro_value() */ 0202 0203 0204 /* ------------------------------------------------------------------------ 0205 @NAME : bt_add_macro_text() 0206 @INPUT : macro - the name of the macro to define 0207 text - the macro text 0208 filename, line - where the macro is defined; pass NULL 0209 for filename if no file, 0 for line if no line number 0210 (just used to generate warning message) 0211 @OUTPUT : 0212 @RETURNS : 0213 @DESCRIPTION: Sets the text value for a macro. If the macro is already 0214 defined, a warning is printed and the old value is overridden. 0215 @GLOBALS : 0216 @CALLS : zzs_get(), zzs_newadd() 0217 @CALLERS : bt_add_macro_value() 0218 (exported from library) 0219 @CREATED : 1997/11/13, GPW (from code in bt_add_macro_value()) 0220 @MODIFIED : 0221 -------------------------------------------------------------------------- */ 0222 void 0223 bt_add_macro_text (const char * macro, const char * text, const char * filename, int line) 0224 { 0225 Sym * sym; 0226 Sym * new_rec; 0227 0228 #if DEBUG == 1 0229 printf ("adding macro \"%s\" = \"%s\"\n", macro, text); 0230 #elif DEBUG >= 2 0231 printf ("add_macro: macro = %p (%s)\n" 0232 " text = %p (%s)\n", 0233 macro, macro, text, text); 0234 #endif 0235 0236 if ((sym = zzs_get (macro))) 0237 { 0238 macro_warning (filename, line, 0239 "overriding existing definition of macro \"%s\"", 0240 macro); 0241 delete_macro_entry (sym); 0242 } 0243 0244 new_rec = zzs_newadd (macro); 0245 new_rec->text = (text != NULL) ? strdup (text) : NULL; 0246 DBG_ACTION 0247 (2, printf (" saved = %p (%s)\n", 0248 new_rec->text, new_rec->text);) 0249 0250 } /* bt_add_macro_text() */ 0251 0252 0253 /* ------------------------------------------------------------------------ 0254 @NAME : bt_delete_macro() 0255 @INPUT : macro - name of macro to delete 0256 @DESCRIPTION: Deletes a macro from the macro table. 0257 @CALLS : zzs_get() 0258 @CALLERS : 0259 @CREATED : 1998/03/01, GPW 0260 @MODIFIED : 0261 -------------------------------------------------------------------------- */ 0262 void 0263 bt_delete_macro (const char * macro) 0264 { 0265 Sym * sym; 0266 0267 sym = zzs_get (macro); 0268 if (! sym) return; 0269 delete_macro_entry (sym); 0270 } 0271 0272 0273 /* ------------------------------------------------------------------------ 0274 @NAME : bt_delete_all_macros() 0275 @DESCRIPTION: Deletes all macros from the macro table. 0276 @CALLS : zzs_rmscore() 0277 @CALLERS : 0278 @CREATED : 1998/03/01, GPW 0279 @MODIFIED : 0280 -------------------------------------------------------------------------- */ 0281 void 0282 bt_delete_all_macros (void) 0283 { 0284 Sym *cur, *next; 0285 0286 DBG_ACTION (2, printf ("bt_delete_all_macros():\n");) 0287 0288 /* 0289 * Use the current `scope' (same one for all macros) to get access to 0290 * a linked list of all macros. Then traverse the list, free()'ing 0291 * both the text (which was strdup()'d in add_macro(), below) and 0292 * the records themselves (which are calloc()'d by zzs_new()). 0293 */ 0294 0295 cur = zzs_rmscope (&AllMacros); 0296 while (cur != NULL) 0297 { 0298 DBG_ACTION 0299 (2, printf (" freeing macro \"%s\" (%p=\"%s\") at %p\n", 0300 cur->symbol, cur->text, cur->text, cur);) 0301 0302 next = cur->scope; 0303 if (cur->text != NULL) free (cur->text); 0304 free (cur); 0305 cur = next; 0306 } 0307 } 0308 0309 0310 /* ------------------------------------------------------------------------ 0311 @NAME : bt_macro_length() 0312 @INPUT : macro - the macro name 0313 @OUTPUT : 0314 @RETURNS : length of the macro's text, or zero if the macro is undefined 0315 @DESCRIPTION: Returns length of a macro's text. 0316 @GLOBALS : 0317 @CALLS : zzs_get() 0318 @CALLERS : bt_postprocess_value() 0319 (exported from library) 0320 @CREATED : Jan 1997, GPW 0321 -------------------------------------------------------------------------- */ 0322 int 0323 bt_macro_length (const char *macro) 0324 { 0325 Sym *sym; 0326 0327 DBG_ACTION 0328 (2, printf ("bt_macro_length: looking up \"%s\"\n", macro);) 0329 0330 sym = zzs_get (macro); 0331 if (sym) 0332 return strlen (sym->text); 0333 else 0334 return 0; 0335 } 0336 0337 0338 /* ------------------------------------------------------------------------ 0339 @NAME : bt_macro_text() 0340 @INPUT : macro - the macro name 0341 filename, line - where the macro was invoked; NULL for 0342 `filename' and zero for `line' if not applicable 0343 @OUTPUT : 0344 @RETURNS : The text of the macro, or NULL if it's undefined. 0345 @DESCRIPTION: Fetches a macros text; prints warning and returns NULL if 0346 macro is undefined. 0347 @CALLS : zzs_get() 0348 @CALLERS : bt_postprocess_value() 0349 @CREATED : Jan 1997, GPW 0350 -------------------------------------------------------------------------- */ 0351 char * 0352 bt_macro_text (const char * macro, const char * filename, int line) 0353 { 0354 Sym * sym; 0355 0356 DBG_ACTION 0357 (2, printf ("bt_macro_text: looking up \"%s\"\n", macro);) 0358 0359 sym = zzs_get (macro); 0360 if (!sym) 0361 { 0362 macro_warning (filename, line, "undefined macro \"%s\"", macro); 0363 return NULL; 0364 } 0365 0366 return sym->text; 0367 }