home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / ncftp-2.3.0-src.tgz / tar.out / contrib / ncftp / Macro.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  6KB  |  292 lines

  1. /* Macro.c
  2.  *
  3.  * Purpose:  Let the user create and execute macros.
  4.  */
  5.  
  6. #include "Sys.h"
  7.  
  8. #include <ctype.h>
  9.  
  10. #include "Util.h"
  11. #include "Macro.h"
  12. #include "Cmds.h"
  13. #include "Cmdline.h"
  14. #include "MakeArgv.h"
  15.  
  16. /* First and last nodes in the macro list. */
  17. MacroNodePtr gFirstMacro = NULL;
  18. MacroNodePtr gLastMacro = NULL;
  19.  
  20. /* Number of macros in the macro list. */
  21. int gNumGlobalMacros = 0;
  22.  
  23. /* We need this routine in case the user wants to redefine an existing
  24.  * macro.
  25.  */
  26. void DisposeMacro(MacroNodePtr macro)
  27. {
  28.     MacroNodePtr prevMac, nextMac;
  29.  
  30.     if (macro == NULL)
  31.         return;
  32.  
  33.     /* Dispose of the linked-list of data lines first. */
  34.     DisposeLineListContents(¯o->macroData);
  35.  
  36.     /* Repair the macro list. */
  37.     prevMac = macro->prev;
  38.     nextMac = macro->next;
  39.     
  40.     if (prevMac == NULL)
  41.         gFirstMacro = nextMac;
  42.     if (nextMac != NULL)
  43.         nextMac->prev = prevMac;
  44.     
  45.     if (nextMac == NULL)
  46.         gLastMacro = prevMac;
  47.     if (prevMac != NULL)
  48.         prevMac->next = nextMac;
  49.     
  50.     free(macro->name);
  51.     free(macro);
  52.     --gNumGlobalMacros;
  53. }    /* DisposeMacro */
  54.  
  55.  
  56.  
  57.  
  58. char *MacroGetLine(char *macline, FILE *fp)
  59. {
  60.     char *cp;
  61.     string str;
  62.     
  63.     *macline = '\0';
  64.     while ((fgets(str, ((int) sizeof(str)) - 1, fp)) != NULL) {
  65.         cp = strrchr(str, '#');
  66.         if (cp != NULL)
  67.             *cp = '\0';
  68.         cp = str + strlen(str) - 1;
  69.         /* Strip trailing space. */
  70.         while (cp >= str && isspace(*cp))
  71.             *cp-- = '\0';
  72.  
  73.         /* Strip leading space. */
  74.         for (cp = str; isspace(*cp); ) ++cp;
  75.  
  76.         if (*cp != '\0') {
  77.             Strncpy(macline, cp, sizeof(string));
  78.             return (macline);
  79.         }
  80.     }
  81.     return (NULL);
  82. }    /* MacroGetLine */
  83.  
  84.  
  85.  
  86.  
  87.  
  88. /* Reads in the macro line by line, until we reach a special keyword
  89.  * that designates the end.
  90.  */
  91. MacroNodePtr CollectMacro(char *macroName, char *endKeyword, FILE *fp)
  92. {
  93.     string macline;
  94.     MacroNodePtr macro;
  95.     char *name;
  96.  
  97.     /* If we already have a macro by that name, we'll dispose of this
  98.      * macro and replace it.
  99.      */
  100.     DisposeMacro(FindMacro(macroName));
  101.  
  102.     if ((name = StrDup(macroName)) == NULL)
  103.         return NULL;
  104.  
  105.     macro = (MacroNodePtr) calloc((size_t)1, sizeof(MacroNode));
  106.     if (macro == NULL)
  107.         return NULL;
  108.  
  109.     macro->name = name;
  110.     InitLineList(¯o->macroData);
  111.  
  112.     while (1) {
  113.         if ((MacroGetLine(macline, fp)) == NULL)
  114.             return NULL;    /* incomplete macro. */
  115.         
  116.         /* See if we have found the terminating keyword. */
  117.         if (STREQ(endKeyword, macline))
  118.             break;
  119.  
  120.         AddLine(¯o->macroData, macline);
  121.     }
  122.     
  123.     return (macro);
  124. }    /* CollectMacro */
  125.  
  126.  
  127.  
  128. /* Adds a macro to the macro list.  */
  129. void AttachMacro(MacroNodePtr macro)
  130. {
  131.     if (macro != NULL) {
  132.         macro->next = NULL;
  133.         if (gFirstMacro == NULL) {
  134.             macro->prev = NULL;
  135.             gFirstMacro = gLastMacro = macro;
  136.         } else {
  137.             gLastMacro->next = macro;
  138.             macro->prev = gLastMacro;
  139.             gLastMacro = macro;
  140.         }
  141.         ++gNumGlobalMacros;
  142.     }
  143. }    /* AttachMacro */
  144.  
  145.  
  146.  
  147.  
  148. void ReadMacroFile(void)
  149. {
  150.     FILE *fp;
  151.     string str;
  152.     longstring fName;
  153.     char *cp;
  154.     MacroNodePtr macp;
  155.     size_t len;
  156.  
  157.     (void) OurDirectoryPath(fName, sizeof(fName), kMacroFileName);
  158.     fp = fopen(fName, "r");
  159.     if (fp == NULL)    /* It's okay not to have one.  Most folks won't. */
  160.         return;
  161.     
  162.     len = strlen(kMacroStartToken);
  163.     while (1) {
  164.         if ((MacroGetLine(str, fp)) == NULL)
  165.             break;
  166.         
  167.         /* See if we have found a starting keyword. */
  168.         if (STRNEQ(kMacroStartToken, str, len)) {
  169.             cp = str + 6;
  170.             if (*cp != '\0') {
  171.                 macp = CollectMacro(cp, kMacroEndToken, fp);
  172.                 AttachMacro(macp);
  173.             }
  174.         }
  175.     }
  176.     
  177.     DebugMsg("Read %d macros from %s.\n", gNumGlobalMacros, fName);
  178.     (void) fclose(fp);
  179. }    /* ReadMacroFile */
  180.  
  181.  
  182.  
  183.  
  184. /* Runs each line in a macro. */
  185. int ExecuteMacro(MacroNodePtr macro, int argc, char **argv)
  186. {
  187.     LinePtr mlp;
  188.     int err, i;
  189.     char *line2;
  190.  
  191.     if (macro == NULL)
  192.         return -1;
  193.  
  194.     line2 = (char *) malloc((size_t) 1024);
  195.     if (line2 == NULL) {
  196.         Error(kDontPerror,
  197.             "Not enough memory to run macro \"%s.\"\n", macro->name);
  198.         return -1;
  199.     }
  200.  
  201.     DebugMsg("Macro: %s\n", macro->name);
  202.     for (i=1; i<argc; i++)
  203.         DebugMsg("    %s\n", argv[i]);
  204.  
  205.     err = kNoErr;
  206.     for (mlp = macro->macroData.first; mlp != NULL; mlp = mlp->next) {
  207.         /* Insert arguments passed to the macro. */
  208.         (void) Strncpy(line2, mlp->line, (size_t)1024);
  209.         ExpandDollarVariables(line2, (size_t)1024, argc, argv);
  210.  
  211.         DebugMsg("%s: %s\n", macro->name, line2);
  212.         
  213.         if ((err = ExecCommandLine(line2)) != 0)
  214.             break;
  215.     }
  216.     free(line2);
  217.     return err;
  218. }    /* ExecuteMacro */
  219.  
  220.  
  221.  
  222.  
  223. int ShowMacro(MacroNodePtr macro)
  224. {
  225.     LinePtr mlp;
  226.  
  227.     if (macro == NULL)
  228.         return -1;
  229.  
  230.     PrintF("macro %s\n", macro->name);
  231.     for (mlp = macro->macroData.first; mlp != NULL; mlp = mlp->next) {
  232.         PrintF("    %s\n", mlp->line);
  233.     }
  234.     PrintF("end\n\n"); 
  235.     return 0;
  236. }    /* ShowMacro */
  237.  
  238.  
  239.  
  240.  
  241. void DumpMacro(char *macName)
  242. {
  243.     MacroNodePtr mnp;
  244.  
  245.     if (macName == NULL) {
  246.         /* Dump 'em all. */
  247.         for (mnp = gFirstMacro; mnp != NULL; mnp = mnp->next)
  248.             (void) ShowMacro(mnp);
  249.     } else {
  250.         mnp = FindMacro(macName);
  251.         (void) ShowMacro(mnp);
  252.     }
  253. }    /* DumpMacro */
  254.  
  255.  
  256.  
  257.  
  258. /* This routine can be used before the CAName list has been constructed
  259.  * (see cmdtab.c).  We use this to make sure we don't have any duplicate
  260.  * macro names when we try to add a new macro.  You can also use this
  261.  * if you only want to look for a macro, but don't want to bother with
  262.  * the possibility of GetCommandOrMacro() returning a command, or an
  263.  * ambiguous name error.
  264.  */
  265. MacroNodePtr FindMacro(char *macroName)
  266. {
  267.     MacroNodePtr mnp;
  268.  
  269.     for (mnp = gFirstMacro; mnp != NULL; mnp = mnp->next) {
  270.         if (STREQ(mnp->name, macroName))
  271.             break;
  272.     }
  273.     return mnp;
  274. }    /* FindMacro */
  275.  
  276.  
  277.  
  278.  
  279. int RunPrefixedMacro(char *pfx, char *sfx)
  280. {
  281.     string macName;
  282.     MacroNodePtr mnp;
  283.     
  284.     STRNCPY(macName, ".");
  285.     STRNCAT(macName, pfx);
  286.     STRNCAT(macName, sfx);
  287.     mnp = FindMacro(macName);
  288.     return ExecuteMacro(mnp, 0, NULL);
  289. }    /* RunPrefixedMacro */
  290.  
  291. /* eof Macro.c */
  292.