home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / internet / tcpip / src205 / TCPIP_Src / Main / c / cmdparse next >
Encoding:
Text File  |  1995-03-06  |  8.1 KB  |  363 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <ctype.h>
  4.  
  5. #include "global.h"
  6. #include "cmdparse.h"
  7. #include "misc.h"
  8. #include "var.h"
  9.  
  10. varlist global_vars = NULL;
  11.  
  12. static int command_tokenise(char *line, char *argv[]);
  13. static char *skipspace(char *p);
  14. static int unescape(char *s);
  15.  
  16. void cmdparse_init(void)
  17. {
  18.   global_vars = varlist_create(NULL);
  19.   var_init_osvars(global_vars, vart_string, "TCPIP$String$*" );
  20.   var_init_osvars(global_vars, vart_osvar, "TCPIP$OSVar$*" );
  21. }
  22.  
  23. int dosetvar(int argc, char **argv)
  24. {
  25.   var_create_string(global_vars, argv[1], 0, argv[2]);
  26.   return 0;
  27. }
  28.  
  29. int dosetosvar(int argc, char **argv)
  30. {
  31.   var_create_osvar(global_vars, argv[1], 0, argv[2]);
  32.   return 0;
  33. }
  34.  
  35. int doshowvar(int argc, char **argv)
  36. {
  37.   char buf[256];
  38.   var vp;
  39.  
  40.   if (argc<2)
  41.   {
  42.     for (vp = global_vars->head; vp!=NULL; vp = vp->link)
  43.     {
  44.       var_output(vp, buf, 256);
  45.       if (vp->type==vart_osvar)
  46.         cwprintf(NULL, "  %-16s: <%s> = \"%s\"\r\n", vp->name+1, vp->value.string, buf);
  47.       else
  48.         cwprintf(NULL, "  %-16s: \"%s\"\r\n", vp->name+1, buf);
  49.     }
  50.   }
  51.   else
  52.   {
  53.     if (vp = var_lookup(global_vars, argv[1], 0), vp!=NULL)
  54.     {
  55.       var_output(vp, buf, 256);
  56.       if (vp->type==vart_osvar)
  57.         cwprintf(NULL, "  %-16s: <%s> = \"%s\"\r\n", vp->name+1, vp->value.string, buf);
  58.       else
  59.         cwprintf(NULL, "  %-16s: \"%s\"\r\n", vp->name+1, buf);
  60.     }
  61.     else
  62.     {
  63.       cwprintf(NULL, "Variable not known\r\n");
  64.       return 1;
  65.     }
  66.   }
  67.   return 0;
  68. }
  69.  
  70. /* Call a subcommand based on the first token in an already-parsed line */
  71. int subcmd(struct cmds *cmdtable, int argc, char **argv)
  72. {
  73.   int loop, rslt;
  74.  
  75.   /* Strip off first token and pass rest of line to subcommand */
  76.   if (argc < 2 || argv[1][0] == '?' || strnicmp(argv[1], "help", strlen(argv[1])) == NULL)
  77.   {
  78.     if (argc < 1)
  79.     {
  80.       cwprintf(NULL, "SUBCMD - Don't know what to do?\r\n");
  81.     }
  82.     else
  83.     {
  84.       cwprintf(NULL, "\"%s\" - takes at least one argument\r\n",argv[0]);
  85.       for (loop = 0; cmdtable[loop].name != NULLCHAR; loop++)
  86.       {
  87.         cwprintf(NULL, "%20s", cmdtable[loop].name);
  88.         if (cmdtable[loop].argc_errmsg != NULLCHAR)
  89.           cwprintf(NULL, " - %s\r\n", cmdtable[loop].argc_errmsg);
  90.         else
  91.           cwprintf(NULL, "\r\n");
  92.       }
  93.     }
  94.     return -1;
  95.   }
  96.   argc--;
  97.   argv++;
  98.   for (loop = 0; cmdtable[loop].name != NULLCHAR; loop++)
  99.   {
  100.     if (strnicmp(argv[0], cmdtable[loop].name, strlen(argv[0])) == 0)
  101.     {
  102.       if (argc < cmdtable[loop].argcmin)
  103.       {
  104.         if (cmdtable[loop].argc_errmsg != NULLCHAR)
  105.           cwprintf(NULL, "Usage: %s\r\n", cmdtable[loop].argc_errmsg);
  106.         return -1;
  107.       }
  108.       else
  109.       {
  110.         rslt = (cmdtable[loop].func)(argc, argv); /* Shouldn't call (*func) should we? */
  111.         if ((rslt < 0) && (cmdtable[loop].exec_errmsg != NULLCHAR))
  112.           cwprintf(NULL, "%s\r\n", cmdtable[loop].exec_errmsg);
  113.         return(rslt);
  114.       }
  115.     }
  116.   }
  117.   if (cmdtable[loop].argc_errmsg != NULLCHAR)
  118.     cwprintf(NULL, "%s\r\n", cmdtable[loop].argc_errmsg);
  119.  
  120.   return -1;
  121. }
  122.  
  123. extern Terminal *MWin;
  124.  
  125. int cmdparse(struct cmds *cmdtable, register char *line, Terminal *Window)
  126. {
  127.   char *argv[NARG];
  128.   int argc, loop, rslt;
  129.   char xcmd[1024];
  130.   Terminal *temp;
  131.  
  132.   /* Remove cr/lf */
  133.   rip(line);
  134.  
  135.   var_translate(global_vars, line, 0, xcmd, 1024);
  136.   line = xcmd;
  137.  
  138.   for (argc = 0; argc < NARG; argc++)
  139.     argv[argc] = NULLCHAR;
  140.  
  141.   temp = Window;
  142.   if (Window == NULL)
  143.     Window = MWin;
  144.  
  145.   if (command_tokenise(xcmd, NULL)>NARG)
  146.   {
  147.     /*
  148.      * Too many arguments for this poxy CLI to deal with...
  149.      */
  150.     cwprintf(Window, "Too many tokens for CLI\r\n");
  151.     return 1;
  152.   }
  153.   else
  154.   {
  155.     argc = command_tokenise(xcmd, argv);
  156.     if (argc==0)
  157.       return 0;
  158.   }
  159.  
  160.   /* Look up command in table; prefix matches are OK */
  161.   for (loop = 0; cmdtable[loop].name != NULLCHAR; loop++)
  162.   {
  163.     if (strncmp(argv[0], cmdtable[loop].name, strlen(argv[0])) == 0)
  164.       break;
  165.   }
  166.   if (cmdtable[loop].name == NULLCHAR)
  167.   {
  168.     if (cmdtable[loop].argc_errmsg != NULLCHAR)
  169.     {
  170.       cwprintf(Window, "%s\r\n", cmdtable[loop].argc_errmsg);
  171.     }
  172.     return -1;
  173.   }
  174.   else
  175.   {
  176.     if (argc < cmdtable[loop].argcmin)
  177.     {
  178.       /* Insufficient arguments */
  179.       if (cmdtable[loop].argc_errmsg != NULLCHAR)
  180.         cwprintf(Window, "Usage: %s\r\n", cmdtable[loop].argc_errmsg);
  181.       return(-1);
  182.     }
  183.     else
  184.     {
  185.       rslt = (cmdtable[loop].func)(argc, argv); /* Shouldn't call (*func) should we? */
  186.       if ((rslt < 0) && (cmdtable[loop].exec_errmsg != NULLCHAR))
  187.       {
  188.         cwprintf(Window, "%s\r\n", cmdtable[loop].exec_errmsg);
  189.       }
  190.       return(rslt);
  191.     }
  192.   }
  193. }
  194.  
  195.  
  196. static char *skipspace(char *p)
  197. {
  198.   while (isspace(*p))
  199.     p++;
  200.   return p;
  201. }
  202.  
  203. /*
  204.  * Escape sequence stripper to get rid of sequences
  205.  * added to keep command interpreter happy
  206.  *
  207.  * Stripping done in place
  208.  *
  209.  * Returns length of resulting string.
  210.  */
  211. static int unescape(char *s)
  212. {
  213.   int i, j;
  214.  
  215.   for (i=0, j=0; s[i]!='\0'; i++)
  216.   {
  217.     if (s[i] == '\\')
  218.     {
  219.       i++;
  220.       switch (s[i])
  221.       {
  222.         case '\\':
  223.           s[j++] = '\\';
  224.           break;
  225.         case '\"':
  226.           s[j++] = '\"';
  227.           break;
  228.         case '{':
  229.           s[j++] = '{';
  230.           break;
  231.         case '}':
  232.           s[j++] = '}';
  233.           break;
  234.         default:
  235.           s[j++] = s[--i];
  236.           break;
  237.       }
  238.     }
  239.     else
  240.       s[j++] = s[i];
  241.   }
  242.   s[j] = '\0';
  243.  
  244.   return j;
  245. }
  246.  
  247. /* Command args extraction function
  248.  * can be used in two ways:
  249.  * 1. Entered with argv==NULL to count the args only
  250.  *    for eg to determin size of array needed for
  251.  *    arg pointers.
  252.  * 2. Entered with argv pointing to an array of char*
  253.  *    with sufficient entries for number of args present
  254.  * cmd is the command line being processed.
  255.  *
  256.  * Returns number of args present, ignoring tail comments
  257.  * or <0 if a parse error occurs (eg missing quote)
  258.  *
  259.  * No escape sequence processing is done, other than to not count
  260.  * '\"' as a '"', as may need to be handled differently according to
  261.  * usage
  262.  */
  263. static int command_tokenise(char *line, char *argv[])
  264. {
  265.   int n = 0;
  266.   char *p = line;
  267.  
  268.   while (*p!='\0')
  269.   {
  270.     p = skipspace(p);
  271.  
  272.     /* Non escaped quote? (ie start of token) */
  273.     if (*p=='\"')
  274.     {
  275.       ++p;
  276.  
  277.       if (argv!=NULL)
  278.         argv[n] = p;
  279.  
  280.       /* scan forward for another non escaped quote */
  281.       while ( !(*p=='\"' && *(p-1)!='\\') && *p!='\0')
  282.         ++p;
  283.  
  284.       /* Test for missing closing quote,
  285.          and return a parse error if missing
  286.        */
  287.       if (*p=='\0')
  288.         return -1;
  289.  
  290.       if (argv!=NULL)  /* Terminate arg if extracting */
  291.         *p = '\0';
  292.  
  293.       ++p;
  294.  
  295.       if (argv!=NULL)
  296.         unescape(argv[n]);
  297.       ++n;
  298.     }
  299.     else if (*p!='\0')
  300.     {
  301.       /* Added to allow comments on end of script command to be ignored
  302.          Tail comments may be either C++ style "// ..."
  303.          or the style commonly used in scripts "# ..." and "; ..."
  304.        */
  305.       if (!strncmp("#", p, 1) || !strncmp(";", p, 1) || !strncmp("//", p, 2))
  306.         break;
  307.  
  308.       if (argv!=NULL)
  309.         argv[n] = p;
  310.  
  311.       while (!isspace(*p) && *p!='\0')
  312.         ++p;
  313.  
  314.       if (argv!=NULL && *p!='\0')  /* Terminate arg if extracting */
  315.         *p++ = '\0';
  316.  
  317.       if (argv!=NULL)
  318.         unescape(argv[n]);
  319.       ++n;
  320.     }
  321.   }
  322.   return n; /* Number of args found */
  323. }
  324.  
  325. /* Examine a strings for flags. The presence of flags
  326.  * is indicated by the 1st char being a '-'.
  327.  *
  328.  * If it is a flags string, for each character in the flags
  329.  * string, set a or clear a bit in the flag word according
  330.  * the the position of the char in the flags list string.
  331.  * Prefixing any flag with '!' or '~' clear the flag.
  332.  *
  333.  * opts is the current options flags
  334.  * the updated options flags are returned.
  335.  * flags is a pointer to a flag characters string.
  336.  *
  337.  */
  338.  
  339. unsigned int command_flags(unsigned int opts, char *cmd, char *flags)
  340. {
  341.   int i;
  342.   char *n;
  343.  
  344.   if (*cmd=='-')
  345.   {
  346.     opts = 1<<31; /* Top bit set for flags present */
  347.     while(++cmd!='\0')
  348.     {
  349.       i = (*cmd == '!' || *cmd=='~');
  350.       n = strchr(flags, *cmd);
  351.       if (n)
  352.       {
  353.         if (i)
  354.           opts &= ~( 1 << (n-flags) );
  355.         else
  356.           opts |= ( 1 << (n-flags) );
  357.       }
  358.     }
  359.   } else
  360.     opts = 0;
  361.   return opts;
  362. }
  363.