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 }