summaryrefslogtreecommitdiffstats
path: root/src/translators/btparse/macros.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/translators/btparse/macros.c')
-rw-r--r--src/translators/btparse/macros.c367
1 files changed, 367 insertions, 0 deletions
diff --git a/src/translators/btparse/macros.c b/src/translators/btparse/macros.c
new file mode 100644
index 0000000..06db983
--- /dev/null
+++ b/src/translators/btparse/macros.c
@@ -0,0 +1,367 @@
+/* ------------------------------------------------------------------------
+@NAME : macros.c
+@DESCRIPTION: Front-end to the standard PCCTS symbol table code (sym.c)
+ to abstract my "macro table".
+@GLOBALS :
+@CALLS :
+@CREATED : 1997/01/12, Greg Ward
+@MODIFIED :
+@VERSION : $Id: macros.c,v 1.19 1999/11/29 01:13:10 greg Rel $
+@COPYRIGHT : Copyright (c) 1996-99 by Gregory P. Ward. All rights reserved.
+
+ This file is part of the btparse library. This library is
+ free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+-------------------------------------------------------------------------- */
+/*#include "bt_config.h"*/
+#include <stdlib.h>
+#include <string.h>
+#include "sym.h"
+#include "prototypes.h"
+#include "error.h"
+/*#include "my_dmalloc.h"*/
+#include "bt_debug.h"
+
+
+/*
+ * NUM_MACROS and STRING_SIZE define the size of the static data
+ * structure that holds the macro table. The defaults are to allocate
+ * 4096 bytes of string space that will be divided up amongst 547
+ * macros. This should be fine for most applications, but if you have a
+ * big macro table you might need to change these and recompile (don't
+ * forget to rebuild and reinstall Text::BibTeX if you're using it!).
+ * You can set these as high as you like; just remember that a block of
+ * STRING_SIZE bytes will be allocated and not freed as long as you're
+ * using btparse. Also, NUM_MACROS defines the size of a hashtable, so
+ * it should probably be a prime a bit greater than a power of 2 -- or
+ * something like that. I'm not sure of the exact Knuthian
+ * specification.
+ */
+#define NUM_MACROS 547
+#define STRING_SIZE 4096
+
+Sym *AllMacros = NULL; /* `scope' so we can get back list */
+ /* of all macros when done */
+
+
+GEN_PRIVATE_ERRFUNC (macro_warning,
+ (char * filename, int line, const char * fmt, ...),
+ BTERR_CONTENT, filename, line, NULL, -1, fmt)
+
+
+/* ------------------------------------------------------------------------
+@NAME : init_macros()
+@INPUT :
+@OUTPUT :
+@RETURNS :
+@DESCRIPTION: Initializes the symbol table used to store macro values.
+@GLOBALS : AllMacros
+@CALLS : zzs_init(), zzs_scope() (sym.c)
+@CALLERS : bt_initialize() (init.c)
+@CREATED : Jan 1997, GPW
+-------------------------------------------------------------------------- */
+void
+init_macros (void)
+{
+ zzs_init (NUM_MACROS, STRING_SIZE);
+ zzs_scope (&AllMacros);
+}
+
+
+/* ------------------------------------------------------------------------
+@NAME : done_macros()
+@INPUT :
+@OUTPUT :
+@RETURNS :
+@DESCRIPTION: Frees up all the macro values in the symbol table, and
+ then frees up the symbol table itself.
+@GLOBALS : AllMacros
+@CALLS : zzs_rmscope(), zzs_done()
+@CALLERS : bt_cleanup() (init.c)
+@CREATED : Jan 1997, GPW
+-------------------------------------------------------------------------- */
+void
+done_macros (void)
+{
+ bt_delete_all_macros ();
+ zzs_done ();
+}
+
+
+static void
+delete_macro_entry (Sym * sym)
+{
+ Sym * cur;
+ Sym * prev;
+
+ /*
+ * Yechh! All this mucking about with the scope list really
+ * ought to be handled by the symbol table code. Must write
+ * my own someday.
+ */
+
+ /* Find this entry in the list of all macro table entries */
+ cur = AllMacros;
+ prev = NULL;
+ while (cur != NULL && cur != sym)
+ {
+ prev = cur;
+ cur = cur->scope;
+ }
+
+ if (cur == NULL) /* uh-oh -- wasn't found! */
+ {
+ internal_error ("macro table entry for \"%s\" not found in scope list",
+ sym->symbol);
+ }
+
+ /* Now unlink from the "scope" list */
+ if (prev == NULL) /* it's the head of the list */
+ AllMacros = cur->scope;
+ else
+ prev->scope = cur->scope;
+
+ /* Remove it from the macro hash table */
+ zzs_del (sym);
+
+ /* And finally, free up the entry's text and the entry itself */
+ if (sym->text) free (sym->text);
+ free (sym);
+} /* delete_macro_entry() */
+
+
+/* ------------------------------------------------------------------------
+@NAME : bt_add_macro_value()
+@INPUT : assignment - AST node representing "macro = value"
+ options - string-processing options that were used to
+ process this string after parsing
+@OUTPUT :
+@RETURNS :
+@DESCRIPTION: Adds a value to the symbol table used for macros.
+
+ If the value was not already post-processed as a macro value
+ (expand macros, paste substrings, but don't collapse
+ whitespace), then this post-processing is done before adding
+ the macro text to the table.
+
+ If the macro is already defined, a warning is printed and
+ the old text is overridden.
+@GLOBALS :
+@CALLS : bt_add_macro_text()
+ bt_postprocess_field()
+@CALLERS : bt_postprocess_entry() (post_parse.c)
+@CREATED : Jan 1997, GPW
+-------------------------------------------------------------------------- */
+void
+bt_add_macro_value (AST *assignment, ushort options)
+{
+ AST * value;
+ char * macro;
+ char * text;
+ boolean free_text;
+
+ if (assignment == NULL || assignment->down == NULL) return;
+ value = assignment->down;
+
+ /*
+ * If the options that were used to process the macro's expansion text
+ * are anything other than BTO_MACRO, then we'll have to do it ourselves.
+ */
+
+ if ((options & BTO_STRINGMASK) != BTO_MACRO)
+ {
+ text = bt_postprocess_field (assignment, BTO_MACRO, FALSE);
+ free_text = TRUE; /* because it's alloc'd by */
+ /* bt_postprocess_field() */
+ }
+ else
+ {
+ /*
+ * First a sanity check to make sure that the presumed post-processing
+ * had the desired effect.
+ */
+
+ if (value->nodetype != BTAST_STRING || value->right != NULL)
+ {
+ internal_error ("add_macro: macro value was not "
+ "correctly preprocessed");
+ }
+
+ text = assignment->down->text;
+ free_text = FALSE;
+ }
+
+ macro = assignment->text;
+ bt_add_macro_text (macro, text, assignment->filename, assignment->line);
+ if (free_text && text != NULL)
+ free (text);
+
+} /* bt_add_macro_value() */
+
+
+/* ------------------------------------------------------------------------
+@NAME : bt_add_macro_text()
+@INPUT : macro - the name of the macro to define
+ text - the macro text
+ filename, line - where the macro is defined; pass NULL
+ for filename if no file, 0 for line if no line number
+ (just used to generate warning message)
+@OUTPUT :
+@RETURNS :
+@DESCRIPTION: Sets the text value for a macro. If the macro is already
+ defined, a warning is printed and the old value is overridden.
+@GLOBALS :
+@CALLS : zzs_get(), zzs_newadd()
+@CALLERS : bt_add_macro_value()
+ (exported from library)
+@CREATED : 1997/11/13, GPW (from code in bt_add_macro_value())
+@MODIFIED :
+-------------------------------------------------------------------------- */
+void
+bt_add_macro_text (char * macro, char * text, char * filename, int line)
+{
+ Sym * sym;
+ Sym * new_rec;
+
+#if DEBUG == 1
+ printf ("adding macro \"%s\" = \"%s\"\n", macro, text);
+#elif DEBUG >= 2
+ printf ("add_macro: macro = %p (%s)\n"
+ " text = %p (%s)\n",
+ macro, macro, text, text);
+#endif
+
+ if ((sym = zzs_get (macro)))
+ {
+ macro_warning (filename, line,
+ "overriding existing definition of macro \"%s\"",
+ macro);
+ delete_macro_entry (sym);
+ }
+
+ new_rec = zzs_newadd (macro);
+ new_rec->text = (text != NULL) ? strdup (text) : NULL;
+ DBG_ACTION
+ (2, printf (" saved = %p (%s)\n",
+ new_rec->text, new_rec->text);)
+
+} /* bt_add_macro_text() */
+
+
+/* ------------------------------------------------------------------------
+@NAME : bt_delete_macro()
+@INPUT : macro - name of macro to delete
+@DESCRIPTION: Deletes a macro from the macro table.
+@CALLS : zzs_get()
+@CALLERS :
+@CREATED : 1998/03/01, GPW
+@MODIFIED :
+-------------------------------------------------------------------------- */
+void
+bt_delete_macro (char * macro)
+{
+ Sym * sym;
+
+ sym = zzs_get (macro);
+ if (! sym) return;
+ delete_macro_entry (sym);
+}
+
+
+/* ------------------------------------------------------------------------
+@NAME : bt_delete_all_macros()
+@DESCRIPTION: Deletes all macros from the macro table.
+@CALLS : zzs_rmscore()
+@CALLERS :
+@CREATED : 1998/03/01, GPW
+@MODIFIED :
+-------------------------------------------------------------------------- */
+void
+bt_delete_all_macros (void)
+{
+ Sym *cur, *next;
+
+ DBG_ACTION (2, printf ("bt_delete_all_macros():\n");)
+
+ /*
+ * Use the current `scope' (same one for all macros) to get access to
+ * a linked list of all macros. Then traverse the list, free()'ing
+ * both the text (which was strdup()'d in add_macro(), below) and
+ * the records themselves (which are calloc()'d by zzs_new()).
+ */
+
+ cur = zzs_rmscope (&AllMacros);
+ while (cur != NULL)
+ {
+ DBG_ACTION
+ (2, printf (" freeing macro \"%s\" (%p=\"%s\") at %p\n",
+ cur->symbol, cur->text, cur->text, cur);)
+
+ next = cur->scope;
+ if (cur->text != NULL) free (cur->text);
+ free (cur);
+ cur = next;
+ }
+}
+
+
+/* ------------------------------------------------------------------------
+@NAME : bt_macro_length()
+@INPUT : macro - the macro name
+@OUTPUT :
+@RETURNS : length of the macro's text, or zero if the macro is undefined
+@DESCRIPTION: Returns length of a macro's text.
+@GLOBALS :
+@CALLS : zzs_get()
+@CALLERS : bt_postprocess_value()
+ (exported from library)
+@CREATED : Jan 1997, GPW
+-------------------------------------------------------------------------- */
+int
+bt_macro_length (char *macro)
+{
+ Sym *sym;
+
+ DBG_ACTION
+ (2, printf ("bt_macro_length: looking up \"%s\"\n", macro);)
+
+ sym = zzs_get (macro);
+ if (sym)
+ return strlen (sym->text);
+ else
+ return 0;
+}
+
+
+/* ------------------------------------------------------------------------
+@NAME : bt_macro_text()
+@INPUT : macro - the macro name
+ filename, line - where the macro was invoked; NULL for
+ `filename' and zero for `line' if not applicable
+@OUTPUT :
+@RETURNS : The text of the macro, or NULL if it's undefined.
+@DESCRIPTION: Fetches a macros text; prints warning and returns NULL if
+ macro is undefined.
+@CALLS : zzs_get()
+@CALLERS : bt_postprocess_value()
+@CREATED : Jan 1997, GPW
+-------------------------------------------------------------------------- */
+char *
+bt_macro_text (char * macro, char * filename, int line)
+{
+ Sym * sym;
+
+ DBG_ACTION
+ (2, printf ("bt_macro_text: looking up \"%s\"\n", macro);)
+
+ sym = zzs_get (macro);
+ if (!sym)
+ {
+ macro_warning (filename, line, "undefined macro \"%s\"", macro);
+ return NULL;
+ }
+
+ return sym->text;
+}