home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / internet / tcpip / src205 / TCPIP_Src / Main / c / ncmdparse < prev    next >
Encoding:
Text File  |  1995-02-27  |  7.7 KB  |  331 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5.  
  6. #include "cmdparse.h"
  7. #include "cmdparse.h"
  8. #include "misc.h"
  9. #include "var.h"
  10.  
  11. varlist global_vars = NULL;
  12.  
  13. static char *skipspace(char *p);
  14. static int report(int errnum, char *info, vterm vt);
  15. static int helplist(cmdtab_str *tab, vterm vt);
  16.  
  17. /* Skip past space (' ', '\t', '\r', '\n')
  18.    in a string */
  19. static char *skipspace(char *p)
  20. {
  21.   while (isspace(*p))
  22.     p++;
  23.   return p;
  24. }
  25.  
  26. static int report(int errnum, char *info, vterm vt)
  27. {
  28.   switch (errnum)
  29.   {
  30.     case CMD_OK:
  31.       return NULL;
  32.     case CMD_HELP:
  33.       vterm_printf(vt, -1, "Sorry no help available on subject \"%s\"\n", info);
  34.       break;
  35.     case CMD_SYNTAX:
  36.       vterm_printf(vt, -1, "Usage: %s\n", info);
  37.       break;
  38.     case CMD_PARSEERR:
  39.       vterm_printf(vt, -1, "Parse error (missing quote, bad escape sequence etc) in \"%s\"\n", info);
  40.       break;
  41.     case CMD_FAIL:
  42.       vterm_printf(vt, -1, "Sorry, insufficient resources\n");
  43.       break;
  44.     case CMD_UNKNOWN:
  45.       vterm_printf(vt, -1, "Unrecognised command \"%s\"\n", info);
  46.       break;
  47.   }
  48.   return CMD_FAIL;
  49. }
  50.  
  51. static int helplist(cmdtab_str *tab, vterm vt)
  52. {
  53.   int c, x, n;
  54.  
  55.   vterm_printf(vt, -1, "Commands available:\n");
  56.  
  57.   n = 0;
  58.  
  59.   for (c=0; tab[c].command!=NULL; c++)
  60.   {
  61.     n += ((strlen(tab[c].command)+16)&~0x0f);
  62.     if (n>80)
  63.     {
  64.       vterm_printf(vt, -1, "\r\n");
  65.       n = 0;
  66.     }
  67.     vterm_printf(vt, -1, "%-16s", tab[c].command);
  68.   }
  69.   if (n>0)
  70.     vterm_printf(vt, -1, "\r\n");
  71.  
  72.   return CMD_OK;
  73. }
  74.  
  75. /* Examine a strings for flags. The presence of flags
  76.    is indicated by the 1st char being a '-'.
  77.  
  78.    If it is a flags string, for each character in the flags
  79.    string, set a or clear a bit in the flag word according
  80.    the the position of the char in the flags list string.
  81.    Prefixing any flag with '!' or '~' clear the flag.
  82.  */
  83.  
  84. unsigned int command_flags(unsigned int opts, char *cmd, char *flags)
  85. {
  86.   int i;
  87.   char *n;
  88.  
  89.   if (*cmd=='-')
  90.   {
  91.     opts = 1<<31; /* Top bit set for flags present */
  92.     while(++cmd!='\0')
  93.     {
  94.       i = (*cmd == '!' || *cmd=='~');
  95.       n = strchr(flags, *cmd);
  96.       if (n)
  97.       {
  98.         if (i)
  99.           opts &= ~( 1 << (n-flags) );
  100.         else
  101.           opts |= ( 1 << (n-flags) );
  102.       }
  103.     }
  104.   } else
  105.     opts = 0;
  106.   return opts;
  107. }
  108.  
  109.  
  110. /* Command args extraction function
  111.    can be used in two ways:
  112.    1. Entered with argv==NULL to count the args only
  113.       for eg to determin size of array needed for
  114.       arg pointers.
  115.    2. Entered with argv pointing to an array of char*
  116.       with sufficient entries for number of args present
  117.    cmd is the command line being processed.
  118.  
  119.    Returns number of args present, ignoring tail comments
  120.    or <0 if a parse error occurs (eg missing quote)
  121.  
  122.    No escape sequence processing is done, other than to not count
  123.    '\"' as a '"', as may need to be handed differently according to usage
  124.  */
  125. static int command_tokenise(char *line, char *argv[])
  126. {
  127.   int n = 0;
  128.   char *p = line;
  129.  
  130.   strterm(line); /* Remove eol from command */
  131.  
  132.   while (*p!='\0')
  133.   {
  134.     p = skipspace(p);
  135.  
  136.     /* Non escaped quote? (ie start of token) */
  137.     if (*p=='\"')
  138.     {
  139.       ++p;
  140.  
  141.       if (argv!=NULL)
  142.         argv[n] = p;
  143.       ++n;
  144.  
  145.       /* scan forward for another non escaped quote */
  146.       while ( !(*p=='\"' && *(p-1)!='\\') && *p!='\0')
  147.         ++p;
  148.  
  149.       /* Test for missing closing quote,
  150.          and return a parse error if missing
  151.        */
  152.       if (*p=='\0')
  153.         return -1;
  154.  
  155.       if (argv!=NULL)  /* Terminate arg if extracting */
  156.         *p = '\0';
  157.  
  158.       ++p;
  159.     }
  160.     else if (*p!='\0')
  161.     {
  162.       /* Added to allow comments on end of script command to be ignored
  163.          Tail comments may be either C++ style "// ..."
  164.          or the style commonly used in scripts "# ..." and "; ..."
  165.        */
  166.       if (!strncmp("#", p, 1) || !strncmp(";", p, 1) || !strncmp("//", p, 2))
  167.         break;
  168.  
  169.       if (argv!=NULL)
  170.         argv[n] = p;
  171.       ++n;
  172.  
  173.       while (!isspace(*p) && *p!='\0')
  174.         ++p;
  175.  
  176.       if (argv!=NULL && *p!='\0')  /* Terminate arg if extracting */
  177.         *p++ = '\0';
  178.     }
  179.   }
  180.   return n; /* Number of args found */
  181. }
  182.  
  183.  
  184. /* Parse, Tokenise and Execute a command
  185.  * table is a list of commands (see cmdparse.h)
  186.  * cmd is the command to be parsed
  187.  * handle is a user suplied value to be passed back to user functions
  188.  * Returns completion code (see cmdparse.h)
  189.  */
  190. cmderr_str *command_parse(cmdtab table, char *cmd, vterm vt)
  191. {
  192.   int argc;
  193.   char **argv;
  194.   char *s;
  195.   cmderr_str *e;
  196.  
  197.   /* Count number of argc present */
  198.   if (argc = command_tokenise(cmd, NULL), argc<=0)
  199.     return make_report((argc<0)?CMD_PARSEERR:CMD_OK, cmd, vt);
  200.  
  201.   if (argv = (char**)malloc(sizeof(char*)*argc), argv==NULL)
  202.     return make_report(CMD_FAIL, cmd, vt);
  203.  
  204.   /* Make a working copy of the command line */
  205.   if (s = strdup(cmd), s==NULL)
  206.     return make_report(CMD_FAIL, cmd, vt);
  207.  
  208.   /* Extract the args this time into argv[]
  209.      no need to error check as is done at count stage
  210.    */
  211.   command_tokenise(s, argv);
  212.  
  213.   /* Lookup and execute the comand */
  214.   e = command_process(table, argc, argv, vt);
  215.  
  216.   free(s);
  217.   free(argv);
  218.   return e; /* Completion code - see cmdparse.h */
  219. }
  220.  
  221.  
  222. /* Lookup and Execute a command
  223.  * table is a list of commands (see cmdparse.h)
  224.  * argc is number of valid args
  225.  * argv is a list of args
  226.  * handle is a user suplied value to be passed back to user functions
  227.  * Returns completion code (see cmdparse.h)
  228.  */
  229. cmderr_str *command_process(cmdtab table, int argc, char* argv[], vterm vt)
  230. {
  231.   int i,n,help;
  232.  
  233.   /* no args = no action */
  234.   if (argc==0)
  235.     return CMD_OK;
  236.  
  237.   /* is whole command a comment ? ("#" and ";" are command prefixes) */
  238.   if (*argv[0]=='#' || *argv[0]==';')
  239.     return CMD_OK;
  240.  
  241.   /* Scan through a command table
  242.    */
  243.   if (help = ( !strcmp(argv[0], "?") || !strincmp(argv[0],"help",strlen(argv[0])) ), help)
  244.   {
  245.     --argc;  ++argv;
  246.   }
  247.  
  248.   /* help on its own yields a commads list */
  249.   if (help && argc==0)
  250.     return helplist(table, vt);
  251.  
  252.   /* Locate command in table, abbreviations allowed */
  253.   n = strlen(argv[0]);
  254.   for (i=0; table[i].command!=NULL && strincmp(table[i].command, argv[0], n); i++);
  255.  
  256.   if (table[i].command!=NULL)
  257.   {
  258.     /* is it a help request? */
  259.     if (help || (argc>1 && *argv[1]=='?'))
  260.       return report(CMD_HELP, table[i].help, vt);
  261.  
  262.     /* Check that sufficient args have been given,
  263.        return syntax error if not.
  264.      */
  265.     if (argc<=table[i].minargs)
  266.       return report(CMD_SYNTAX, table[i].syntax, vt);
  267.  
  268.     (table[i].proc)(argc, argv, handle);
  269.     return NULL;
  270.   }
  271.   return report(CMD_UNKNOWN, argv[0], vt);
  272. }
  273.  
  274. /*
  275.  * From old cmdparse code:
  276.  * Variable handle code
  277.  */
  278. void cmdparse_init(void)
  279. {
  280.   global_vars = varlist_create(NULL);
  281.   var_init_osvars(global_vars, vart_string, "TCPIP$String$*" );
  282.   var_init_osvars(global_vars, vart_osvar, "TCPIP$OSVar$*" );
  283. }
  284.  
  285. int dosetvar(int argc, char **argv)
  286. {
  287.   var_create_string(global_vars, argv[1], 0, argv[2]);
  288.   return 0;
  289. }
  290.  
  291. int dosetosvar(int argc, char **argv)
  292. {
  293.   var_create_osvar(global_vars, argv[1], 0, argv[2]);
  294.   return 0;
  295. }
  296.  
  297. int doshowvar(int argc, char **argv)
  298. {
  299.   char buf[256];
  300.   var vp;
  301.  
  302.   if (argc<2)
  303.   {
  304.     for (vp = global_vars->head; vp!=NULL; vp = vp->link)
  305.     {
  306.       var_output(vp, buf, 256);
  307.       if (vp->type==vart_osvar)
  308.         cwprintf(NULL, "  %-16s: <%s> = \"%s\"\r\n", vp->name+1, vp->value.string, buf);
  309.       else
  310.         cwprintf(NULL, "  %-16s: \"%s\"\r\n", vp->name+1, buf);
  311.     }
  312.   }
  313.   else
  314.   {
  315.     if (vp = var_lookup(global_vars, argv[1], 0), vp!=NULL)
  316.     {
  317.       var_output(vp, buf, 256);
  318.       if (vp->type==vart_osvar)
  319.         cwprintf(NULL, "  %-16s: <%s> = \"%s\"\r\n", vp->name+1, vp->value.string, buf);
  320.       else
  321.         cwprintf(NULL, "  %-16s: \"%s\"\r\n", vp->name+1, buf);
  322.     }
  323.     else
  324.     {
  325.       cwprintf(NULL, "Variable not known\r\n");
  326.       return 1;
  327.     }
  328.   }
  329.   return 0;
  330. }
  331.