home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR3 / KA9Q212.ZIP / CMDPARSE.C < prev    next >
C/C++ Source or Header  |  1993-07-16  |  8KB  |  402 lines

  1. /* Parse command line, set up command arguments Unix-style, and call function.
  2.  * Note: argument is modified (delimiters are overwritten with nulls)
  3.  *
  4.  * Copyright 1991 Phil Karn, KA9Q
  5.  *
  6.  * Improved error handling by Brian Boesch of Stanford University
  7.  * Feb '91 - Bill Simpson
  8.  *        bit16cmd for PPP
  9.  * Mar '91 - Glenn McGregor
  10.  *        handle string escaped sequences
  11.  */
  12.  
  13. /****************************************************************************
  14. *    $Id: cmdparse.c 1.3 93/07/16 11:43:18 ROOT_DOS Exp $
  15. *    24 Aug 92    1.2        CMS    Expand environment variables.                    *
  16. *    10 Jul 93    1.3        GT    Fix warnings.                                    *
  17. ****************************************************************************/
  18.  
  19. #include <stdio.h>
  20. #include "global.h"
  21. #include "proc.h"
  22. #include "cmdparse.h"
  23.  
  24. struct boolcmd {
  25.     char *str;    /* Token */
  26.     int val;    /* Value */
  27. };
  28.  
  29. static struct boolcmd Boolcmds[] = {
  30.     { "y",        1 },    /* Synonyms for "true" */
  31.     { "yes",    1 },
  32.     { "true",        1 },
  33.     { "on",        1 },
  34.     { "1",        1 },
  35.     { "set",        1 },
  36.     { "enable",    1 },
  37.  
  38.     { "n",        0 },    /* Synonyms for "false" */
  39.     { "no",        0 },
  40.     { "false",    0 },
  41.     { "off",        0 },
  42.     { "0",        0 },
  43.     { "clear",    0 },
  44.     { "disable",    0 },
  45.     { NULLCHAR }
  46. };
  47.  
  48. static char *stringparse __ARGS((char *line));
  49.  
  50. static char *
  51. stringparse(line)
  52. char *line;
  53. {
  54.     register char *cp = line;
  55.     unsigned long num;
  56.  
  57.     while ( *line != '\0' && *line != '\"' ) {
  58.         if ( *line == '\\' ) {
  59.             line++;
  60.             switch ( *line++ ) {
  61.             case 'n':
  62.                 *cp++ = '\n';
  63.                 break;
  64.             case 't':
  65.                 *cp++ = '\t';
  66.                 break;
  67.             case 'v':
  68.                 *cp++ = '\v';
  69.                 break;
  70.             case 'b':
  71.                 *cp++ = '\b';
  72.                 break;
  73.             case 'r':
  74.                 *cp++ = '\r';
  75.                 break;
  76.             case 'f':
  77.                 *cp++ = '\f';
  78.                 break;
  79.             case 'a':
  80.                 *cp++ = '\a';
  81.                 break;
  82.             case '\\':
  83.                 *cp++ = '\\';
  84.                 break;
  85.             case '\?':
  86.                 *cp++ = '\?';
  87.                 break;
  88.             case '\'':
  89.                 *cp++ = '\'';
  90.                 break;
  91.             case '\"':
  92.                 *cp++ = '\"';
  93.                 break;
  94.             case 'x':
  95.                 num = strtoul( --line, &line, 16 );
  96.                 *cp++ = (char) num;
  97.                 break;
  98.             case '0':
  99.             case '1':
  100.             case '2':
  101.             case '3':
  102.             case '4':
  103.             case '5':
  104.             case '6':
  105.             case '7':
  106.                 num = strtoul( --line, &line, 8 );
  107.                 *cp++ = (char) num;
  108.                 break;
  109.             case '\0':
  110.                 return NULLCHAR;
  111.             default:
  112.                 *cp++ = *(line - 1);
  113.                 break;
  114.             };
  115.         } else {
  116.             *cp++ = *line++;
  117.         }
  118.     }
  119.  
  120.     if ( *line == '\"' )
  121.         line++;     /* skip final quote */
  122.     *cp = '\0';        /* terminate string */
  123.     return line;
  124. }
  125.  
  126. int
  127. cmdparse(cmds,line,p)
  128. struct cmds cmds[];
  129. register char *line;
  130. void *p;
  131. {
  132.     struct cmds *cmdp;
  133.     char *argv[NARG],*cp;
  134.     char **pargv;
  135.     int argc,i;
  136.  
  137.     /* Remove cr/lf */
  138.     rip(line);
  139.  
  140.     for(argc = 0;argc < NARG;argc++)
  141.         argv[argc] = NULLCHAR;
  142.  
  143.     for(argc = 0;argc < NARG;){
  144.         register int qflag = FALSE;
  145.  
  146.         /* Skip leading white space */
  147.         while(*line == ' ' || *line == '\t')
  148.             line++;
  149.         if(*line == '\0')
  150.             break;
  151.         /* return if comment character first non-white */
  152.         if ( argc == 0  &&  *line == '#' )
  153.             return 0;
  154.         /* Check for quoted token */
  155.         if(*line == '"'){
  156.             line++;    /* Suppress quote */
  157.             qflag = TRUE;
  158.         }
  159.         argv[argc++] = line;    /* Beginning of token */
  160.  
  161.         if(qflag){
  162.             /* Find terminating delimiter */
  163.             if((line = stringparse(line)) == NULLCHAR){
  164.                 return -1;
  165.             }
  166.         } else {
  167.             /* Find space or tab. If not present,
  168.              * then we've already found the last
  169.              * token.
  170.              */
  171.             if((cp = strchr(line,' ')) == NULLCHAR
  172.              && (cp = strchr(line,'\t')) == NULLCHAR){
  173.                 break;
  174.             }
  175.             *cp++ = '\0';
  176.             line = cp;
  177.         }
  178.     }
  179.     if (argc < 1) {        /* empty command line */
  180.         argc = 1;
  181.         argv[0] = "";
  182.     }
  183.     /* Check for $ commands and substitute environment variables */
  184.     for (i = 0; i < argc; i++) {
  185.         char *p;
  186.         int j;
  187.         if (*argv[i] == '$') {
  188.             strupr(argv[i]);
  189.             if ((p = getenv(argv[i] + 1)) != NULL && *p)
  190.                 argv[i] = p;
  191.             else {
  192.                 for (j = i + 1; j < argc; j++)
  193.                     argv[j - 1] = argv[j];
  194.                 argv[argc - 1] = NULL;
  195.                 argc--;
  196.             }
  197.         }
  198.     }
  199.     if (*argv[0] == '#')
  200.         return 0;
  201.     /* Look up command in table; prefix matches are OK */
  202.     for(cmdp = cmds;cmdp->name != NULLCHAR;cmdp++){
  203.         if(strncmp(argv[0],cmdp->name,strlen(argv[0])) == 0)
  204.             break;
  205.     }
  206.     if(cmdp->name == NULLCHAR) {
  207.         if(cmdp->argc_errmsg != NULLCHAR)
  208.             tprintf("%s\n",cmdp->argc_errmsg);
  209.         return -1;
  210.     } else {
  211.         if(argc < cmdp->argcmin) {
  212.             /* Insufficient arguments */
  213.             tprintf("Usage: %s\n",cmdp->argc_errmsg);
  214.             return -1;
  215.         } else {
  216.             if(cmdp->stksize == 0){
  217.                 return (*cmdp->func)(argc,argv,p);
  218.             } else {
  219.                 /* Make private copy of argv and args,
  220.                  * spawn off subprocess and return.
  221.                  */
  222.                 pargv = (char **)callocw(argc,sizeof(char *));
  223.                 for(i=0;i<argc;i++)
  224.                     pargv[i] = strdup(argv[i]);
  225.                 newproc(cmdp->name,cmdp->stksize,
  226.                 (void (*)())cmdp->func,argc,pargv,p,1);
  227.                 return(0);
  228.             }
  229.         }
  230.     }
  231. }
  232.  
  233. /* Call a subcommand based on the first token in an already-parsed line */
  234. int
  235. subcmd(tab,argc,argv,p)
  236. struct cmds tab[];
  237. int argc;
  238. char *argv[];
  239. void *p;
  240. {
  241.     register struct cmds *cmdp;
  242.     char **pargv;
  243.     int found = 0;
  244.     int i;
  245.  
  246.     /* Strip off first token and pass rest of line to subcommand */
  247.     if (argc < 2) {
  248.         if (argc < 1)
  249.             tprintf("SUBCMD - Don't know what to do?\n");
  250.         else
  251.             tprintf("\"%s\" - takes at least one argument\n",argv[0]);
  252.         return -1;
  253.     }
  254.     argc--;
  255.     argv++;
  256.     for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++){
  257.         if(strncmp(argv[0],cmdp->name,strlen(argv[0])) == 0){
  258.             found = 1;
  259.             break;
  260.         }
  261.     }
  262.     if(!found){
  263.         tprintf("valid subcommands:");
  264.         for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++)
  265.             if(tprintf(" %s",cmdp->name) == EOF)
  266.                 return -1;
  267.         tprintf("\n");
  268.         return -1;
  269.     }
  270.     if(argc < cmdp->argcmin){
  271.         if(cmdp->argc_errmsg != NULLCHAR)
  272.             tprintf("Usage: %s\n",cmdp->argc_errmsg);
  273.         return -1;
  274.     }
  275.     if(cmdp->stksize == 0){
  276.         return (*cmdp->func)(argc,argv,p);
  277.     } else {
  278.         /* Make private copy of argv and args */
  279.         pargv = (char **)callocw(argc,sizeof(char *));
  280.         for(i=0;i<argc;i++)
  281.             pargv[i] = strdup(argv[i]);
  282.         newproc(cmdp->name,cmdp->stksize,
  283.          (void (*)())cmdp->func,argc,pargv,p,1);
  284.         return(0);
  285.     }
  286. }
  287.  
  288. /* Subroutine for setting and displaying boolean flags */
  289. int
  290. setbool(var,label,argc,argv)
  291. int *var;
  292. char *label;
  293. int argc;
  294. char *argv[];
  295. {
  296.     struct boolcmd *bc;
  297.  
  298.     if(argc < 2){
  299.         tprintf("%s: %s\n",label,*var ? "on":"off");
  300.         return 0;
  301.     }
  302.     for(bc = Boolcmds;bc->str != NULLCHAR;bc++){
  303.         if(strcmpi(argv[1],bc->str) == 0){
  304.             *var = bc->val;
  305.             return 0;
  306.         }
  307.     }
  308.     tprintf("Valid options:");
  309.     for(bc = Boolcmds;bc->str != NULLCHAR;bc++)
  310.         if(tprintf(" %s",bc->str) == EOF)
  311.             return 1;
  312.     tprintf("\n");
  313.     return 1;
  314. }
  315.  
  316.  
  317. /* Subroutine for setting and displaying bit values */
  318. int
  319. bit16cmd(bits,mask,label,argc,argv)
  320. int16 *bits;
  321. int16 mask;
  322. char *label;
  323. int argc;
  324. char *argv[];
  325. {
  326.     int doing = (*bits & mask);
  327.     int result = setbool( &doing, label, argc, argv );
  328.  
  329.     if ( !result ) {
  330.         if ( doing )
  331.             *bits |= mask;
  332.         else
  333.             *bits &= ~mask;
  334.     }
  335.     return result;
  336. }
  337.  
  338.  
  339. /* Subroutine for setting and displaying long variables */
  340. int
  341. setlong(var,label,argc,argv)
  342. long *var;
  343. char *label;
  344. int argc;
  345. char *argv[];
  346. {
  347.     if(argc < 2)
  348.         tprintf("%s: %ld\n",label,*var);
  349.     else
  350.         *var = atol(argv[1]);
  351.  
  352.     return 0;
  353. }
  354. /* Subroutine for setting and displaying short variables */
  355. int
  356. setshort(var,label,argc,argv)
  357. unsigned short *var;
  358. char *label;
  359. int argc;
  360. char *argv[];
  361. {
  362.     if(argc < 2)
  363.         tprintf("%s: %u\n",label,*var);
  364.     else
  365.         *var = atoi(argv[1]);
  366.  
  367.     return 0;
  368. }
  369. /* Subroutine for setting and displaying integer variables */
  370. int
  371. setint(var,label,argc,argv)
  372. int *var;
  373. char *label;
  374. int argc;
  375. char *argv[];
  376. {
  377.     if(argc < 2)
  378.         tprintf("%s: %i\n",label,*var);
  379.     else
  380.         *var = atoi(argv[1]);
  381.  
  382.     return 0;
  383. }
  384.  
  385. /* Subroutine for setting and displaying unsigned integer variables */
  386. int
  387. setuns(var,label,argc,argv)
  388. unsigned *var;
  389. char *label;
  390. int argc;
  391. char *argv[];
  392. {
  393.     if(argc < 2)
  394.         tprintf("%s: %u\n",label,*var);
  395.     else
  396.         *var = atoi(argv[1]);
  397.  
  398.     return 0;
  399. }
  400.  
  401.  
  402.