/****************************************************************************** * This file is Copyright 1992 by Philip G. Richards. All Rights Reserved. * See the file README that came with this distribution for permissions on * code usage, copying, and distribution. It comes with absolutely no warranty. ******************************************************************************/ #include "client.h" #include "main.h" #include "macro.h" #include typedef struct MACRO { char *name; int length; char **text; char *help; } MACRO; static int maxmacro = 0, nummacro = 0; static MACRO *macrotable = (MACRO*)0; static int *macrostack = (int*)0; static int stacktop = 0; static int stacklimit = 0; static int *cntstack = (int*)0; static void clean_macro(MACRO *macro) { if (macro == (MACRO*)0) return; macro->name = (char*)0; macro->length = 0; macro->text = (char**)0; macro->help = (char*)0; } static void destroy_macro(MACRO *macro) { int i; if (macro == (MACRO*)0) return; for (i = 0; i < macro->length; i++) (void)free((char*)(macro->text[i])); (void)free((char*)(macro->name)); (void)free((char*)(macro->help)); nummacro--; clean_macro(macro); } static MACRO * lookup_macro(char *name) { int i; if (macrotable == (MACRO*)0) return (MACRO*)0; for (i = 0; i < nummacro; i++) if (macrotable[i].name && strcmp(macrotable[i].name, name) == 0) break; return (i < nummacro)? (¯otable[i]): (MACRO*)0; } int remove_macro(char *name) { MACRO *macro; macro = lookup_macro(name); if (macro) destroy_macro(macro); else ffprintf(STDERR, "?no macro `%s'\n", name); return (macro == 0); } int list_macro(char *name) { MACRO *macro; macro = lookup_macro(name); if (macro) { int i; ffprintf(STDOUT, "--- Macro `%s': %d lines\n", macro->name, macro->length); if (macro->help) ffprintf(STDOUT, " Help text: `%s'\n", macro->help); else ffprintf(STDOUT, " No help text defined\n"); for (i = 0; i < macro->length; i++) if (macro->text[i]) ffprintf(STDOUT, "\t%s\n", macro->text[i]); else ffprintf(STDOUT, "\n"); ffprintf(STDERR, ".\n"); } else ffprintf(STDERR, "?no macro `%s'\n", name); return (macro == 0); } /*************************************************************************** * it is assumed that name will be free'd by the caller (if necessary) * but that macrotext is being handed over fully to this function; * i.e., do what you like with name back in the calling environment, * but under no circumstances free macrotext! ***************************************************************************/ int install_macro(char *name, int macrolen, char **macrotext, char *macrohelp) { MACRO *oldmacro; MACRO *newmacro = (MACRO*)0; if (name == (char*)0 || *name == '\0') { ffprintf(STDERR, "?attempt to install null named macro failed\n"); return 1; } oldmacro = lookup_macro(name); if (oldmacro != (MACRO*)0) { /* free the old macro; the new macro can take its place */ ffprintf(STDINFO, "?overwriting old macro definition for `%s'\n", name); destroy_macro(oldmacro); newmacro = oldmacro; } else if (nummacro < maxmacro) { /* there is a free space in the table */ int i; for (i = 0; i < maxmacro; i++) if (!macrotable[i].name) break; /* if this fails then we have *big* problems, oh well, check anyway */ if (i < maxmacro) newmacro = ¯otable[i]; else { ffprintf(STDERR,"??internal error: nummacro(%d) < maxmacro(%d) and no gap found\n", nummacro, maxmacro); return 1; } } else { /* no free space in table; extend by a bit */ maxmacro += 4; if (macrotable) macrotable = (MACRO*)realloc((char*)macrotable, sizeof(MACRO) * maxmacro); else macrotable = (MACRO*)malloc(sizeof(MACRO) * maxmacro); if (macrotable == (MACRO*)0) { ffprintf(STDERR, "??run out of memory in install_macro()\n"); abort(); } else { int i; for (i = nummacro + 1; i < maxmacro; i++) clean_macro(¯otable[i]); } newmacro = ¯otable[nummacro]; } nummacro++; newmacro->name = strdup(name); newmacro->length = macrolen; newmacro->text = macrotext; newmacro->help = macrohelp? strdup(macrohelp): 0; return 0; } int deinstall_macro(char *name) { MACRO *macro; macro = lookup_macro(name); if (macro == (MACRO*)0) { ffprintf(STDERR, "?can not delete macro `%s': doesn't exist\n", name); return 1; } destroy_macro(macro); return 0; } int initialise_macro(int argc, char **argv) { MACRO *macro; int i; macro = lookup_macro(argv[0]); if (macro == (MACRO*)0) return 1; if (dbug_flag > 0) { int i; ffprintf(STDDBG, "\nmacro initialise called with valid macro name:\n"); for (i = 0; i <= argc; i++) ffprintf(STDDBG, " $%-2d = \"%s\"\n", i, argv[i]); ffprintf(STDDBG, "\ndefinition:\n"); for (i = 0; i < macro->length; i++) ffprintf(STDDBG, "%02d: %s\n", i, macro->text[i]); ffprintf(STDDBG, "\n"); } /* we don't allow recursion (yet) so check this isn't trying to */ for (i = 0; i < stacktop; i++) if (macro == ¯otable[macrostack[i]]) { ffprintf(STDERR, "?attempted recursion in macro `%s' -- ignoring call to `%s'\n", macrotable[macrostack[stacktop-1]].name, macro->name); (void)fflush(STDERR); return 0; } /* push this macro onto the macro execution stack */ if (stacktop >= stacklimit) { stacklimit += 8; if (macrostack) macrostack = (int*)realloc((char*)macrostack, stacklimit * sizeof(int)); else macrostack = (int*)malloc(stacklimit * sizeof(int)); if (cntstack) cntstack = (int*)realloc((char*)cntstack, stacklimit * sizeof(int)); else cntstack = (int*)malloc(stacklimit * sizeof(int)); } macrostack[stacktop] = (int)(macro - macrotable); cntstack[stacktop++] = 0; return 0; } char * get_macroline(void) { if (stacktop > 0) { int st = stacktop - 1; if (cntstack[st] < macrotable[macrostack[st]].length) return (macrotable[macrostack[st]].text[cntstack[st]++]); else stacktop--; } return (char*)0; } #define NCO 6 void fsp_macro_long_help_all(void) { int i; int notext = 0; if (macrotable == (MACRO*)0 || nummacro == 0) { ffprintf(STDOUT,"No macros defined\n"); return; } ffprintf(STDOUT,"Macros are:\n"); for (i = 0; i < maxmacro; i++) if (macrotable[i].name) { if (macrotable[i].help) ffprintf(STDOUT," %-10s %s\n", macrotable[i].name, macrotable[i].help); else notext++; } if (notext) { int j; ffprintf(STDOUT,"\nUndocumented macros are:\n"); for (i = 0, j = 0; i < maxmacro; i++) if (macrotable[i].name) if (!macrotable[i].help) { ffprintf(STDOUT," %-10s%s", macrotable[i].name, j == NCO-1? "\n" : ""); j = (j+1) % NCO; } if (j) ffprintf(STDOUT,"\n"); } } int fsp_macro_long_help(char *name) { MACRO *macro; macro = lookup_macro(name); if (macro) { if (macro->help) ffprintf(STDOUT,"%-10s %s\n", macro->name, macro->help); else ffprintf(STDOUT, "no help available for macro `%s'\n", name); } else return 1; return 0; } void fsp_macro_short_help(void) { int i, j; if (macrotable == (MACRO*)0 || nummacro == 0) { ffprintf(STDOUT,"No macros defined\n"); return; } ffprintf(STDOUT,"Macros are:\n"); for (i = 0, j = 0; i < maxmacro; i++) if (macrotable[i].name) { ffprintf(STDOUT," %-10s%s", macrotable[i].name, j == NCO-1? "\n" : ""); j = (j+1) % NCO; } if (j) ffprintf(STDOUT,"\n"); }