Subversion Repositories Vertical

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /**********
  2.  * $Id: cmdparse.c,v 1.18 2002/09/09 10:26:56 mjames Exp $ **********
  3.  
  4.              One time Author: Kevin Ross (x6143)
  5.                       Philips Semiconductors Limited.
  6.                       Millbrook Industrial Estate, Southampton, SO9 7BH. England.
  7.  
  8.                 Date: 13th May 1993
  9.  
  10.              Mostly by Mike James these days
  11.  
  12.              Comment: This program parses the input commands for the SFC3 evaluation software
  13. $Log: cmdparse.c,v $
  14. Revision 1.18  2002/09/09 10:26:56  mjames
  15. Removed set generic range and replaced it with a set generic value command
  16. that takes both integers and ranges.
  17.  
  18. Revision 1.17  2002/01/16 11:22:41  mjames
  19. database.h header file is read in first as it undefined DLL stuff irrelevant
  20. to HPUX
  21.  
  22. Revision 1.16  2001/12/20 13:49:48  mjames
  23. force ?
  24.  
  25. Revision 1.15  2001/12/13 22:14:26  mjames
  26. Corrected nested command handlers to allow variable passing without corruption.
  27.  
  28. Revision 1.14  2001/10/31 22:20:00  mjames
  29. Tidying up problematical comments caused by CVS
  30. 'intelligent' comment guessing
  31.  
  32. Revision 1.13  2001/10/10 20:19:56  mjames
  33. Adjustment of handling of escapes and comments
  34.  
  35. Revision 1.12  2001/10/10 10:02:59  mjames
  36. Final tweaks to work with end-of line at end-of-file
  37.  
  38. Revision 1.11  2001/10/10 09:54:30  mjames
  39. Modified command line handler to correctly recognise
  40. comment leaders anywhere on line, not just as first character.
  41.  
  42. Revision 1.10  2001/07/09 15:08:44  mjames
  43. Check the last character of a line of text to see if it is actually a control code
  44. before deleting it
  45.  
  46. Revision 1.9  2001/06/19 05:24:57  mjames
  47. Created a trap_fopen to overcome trying to write to read only files.
  48. If this attempted in NT the file can be opened but not written to.
  49.  
  50. Revision 1.8  2001/06/06 12:10:24  mjames
  51. Move from HPUX
  52.  
  53. Revision 1.7  2001/05/01 15:21:18  mjames
  54. Added comment leaders on printout of commands executed
  55.  
  56. Revision 1.6  2001/04/06 22:47:01  mjames
  57. Added doc2, the creator of documentation to Vertical scripts uses PERL
  58.  
  59.  
  60. Also correcting generic behaviour and the printing of Verilog.
  61.  
  62. Revision 1.5  2001/02/06 22:41:14  mjames
  63. Added correct argument passing for 'read file comp_suffix arg0 arg1 arg2 ...
  64.  
  65. Revision 1.4  2001/01/26 21:50:10  mjames
  66. Managed to get vertical non TCL to compile again
  67.  
  68. Conversion to argv, argc[] mode of operation continues
  69.  
  70. Revision 1.3  2001/01/04 21:26:54  mjames
  71. Modifications to add in the TCL style
  72. argument list to all of the functions
  73. .
  74.  
  75. Revision 1.2  2001/01/02 07:53:52  mjames
  76. Made changes to allow for interface with TCL/Tk
  77.  
  78. Revision 1.1.1.1  2000/10/19 21:58:35  mjames
  79. Mike put it here
  80.  
  81. There has been a lot more development, but the comments have been
  82. removed in order to cut down the junk
  83.  
  84. *********************************************************************************************************/
  85.  
  86. #include <stdio.h>
  87. #include <string.h>
  88. #include <stdlib.h>
  89. #include <ctype.h>
  90.  
  91. #include "expression.h"
  92. #include "generic.h"
  93. #include "database.h"
  94.  
  95. #include "vertcl_main.h"
  96. #include "cmdparse.h"
  97. #include "cmdlog.h"
  98. #include "cmdutil.h"
  99. #include "cmdexec.h"
  100. /* used for dynamic string allocation/deallocation code
  101.  * used here for command keywords May 2 2000 */
  102. #include "lx_support.h"
  103.  
  104. /*********************************************************************************************************/
  105. #ident "@(#)$Header: /cygwin/cvsroot/vertical/cmdparse.c,v 1.18 2002/09/09 10:26:56 mjames Exp $"
  106.  
  107. /******************************************* Execute a command  ******************************************/
  108. /* define flag for global control of execution mode
  109.  * can be Tcl_Cmd or  Tcl_GUI : default to be Tcl_Cmd for
  110.  * backwards compatibility */
  111.  
  112. tcl_mode_t tcl_mode = Tcl_Cmd;
  113.  
  114.  
  115.  
  116. #define WORDWIDTH 100 /* max command word  ever expected */
  117. #define CMDWIDTH  20 /*Field width for printing CMD word */
  118. int Execute (int argc,char * argv[], struct command Dispatch[])
  119.    {
  120.    int i,j, FinalResult = UNKNOWNCMD;
  121.  
  122.    if(!argc)
  123.      return(NARGS);
  124.    if(argv[0][0] == '?')
  125.      {
  126.      printf("Commands available;\nHelp on:");
  127.      for(i=0; i< argc;i++)
  128.        printf("%s ",argv[i]);
  129.      putchar ('\n');
  130.      for (i=0; Dispatch[i].name; i++)
  131.        {
  132.        int p;
  133.        for(j=0;j<Dispatch[i].NumChar;j++)     /* upper case significant chars */
  134.          putchar(toupper(Dispatch[i].name[j]));
  135.        for(;Dispatch[i].name[j];j++)          /* and all of the rest, we just print */
  136.          putchar(Dispatch[i].name[j]);
  137.        putchar(' '); j++;
  138.        if(Dispatch[i].extras) {
  139.          p=j;
  140.          for(;Dispatch[i].extras[j-p];j++)    /* and all of the extras field we just print */
  141.          putchar(Dispatch[i].extras[j-p]);
  142.          };
  143.       for(;j<CMDWIDTH;j++)                  /* create spacing , relies on auto - wrap */
  144.          putchar(j&1 ? '.' : ' ');
  145.        putchar(' ');
  146.        puts(Dispatch[i].helpstr);
  147.        }
  148.      putchar('\n');
  149.      FinalResult = OKCMD; /* ? is a valid command at this level */
  150.      }
  151.    else
  152.      {
  153.      for (i=0; Dispatch[i].name; i++)
  154.        if (strncmp (argv[0], Dispatch[i].name, Dispatch[i].NumChar)==0)
  155.          {
  156.           /* Dispatch the next level command */
  157.          if (Dispatch[i].function){ /* call function if there */
  158.            FinalResult=(*Dispatch[i].function) (Tcl_interp,NULL,argc-1,argv+1);
  159.            }
  160.          else                      /* call down the menu */
  161.            FinalResult=Execute(argc-1,argv+1,Dispatch[i].Menu);
  162.          break;
  163.          }
  164.      }
  165.    return (FinalResult);
  166.    }
  167.  
  168. /******************************************** Strip off words ********************************************/
  169. /* this needs repairing . This code is unsafe.
  170.  * Needs to keep a record of how many chars copied !!
  171.  * and stop when in danger of a buffer overflow.
  172.  *
  173.  * Did not work properly if expanded strings are longer than the
  174.  * original strings. This now fixed.
  175.  *
  176.  * Code modified to use some string allocation functions in lx_support.c  
  177.  */
  178. /*char wordbuff[1024];
  179. */
  180. typedef enum  { SPACES,CHARS } Phase_t;
  181.  
  182. int FindWords (char * linebuff, int * pargc, char * argv[],int nArgs, char *  Args[],
  183.        struct str ** cmd_first,struct str ** cmd_last
  184.         )
  185.    {
  186.    char  *WordPtr;
  187.    char * BasePtr;
  188.    int  argc = 0;
  189.    int  term = ' ',escape,comment,done_word,chars_seen;
  190.    char * copy_buff;
  191.    Phase_t Phase ;
  192.    
  193.  
  194.    copy_buff = malloc(strlen(linebuff)+1); /* make a safe copy */
  195.  
  196. /*      for (i=0; i<Len; i++)                               */
  197. /*         Cmd->Text[i] = tolower(Cmd->Text[i]);            */     /* convert text to lower case */
  198.    WordPtr = linebuff;                                   /* set LineStart to beginning of string */
  199.    escape = 0;                          
  200.    comment = 0;
  201.                                /* Now split off the words */
  202.    BasePtr = NULL;
  203.    while (*WordPtr && argc < WORDSINLINE && comment<2)
  204.      {
  205.      BasePtr = copy_buff;
  206.      Phase = SPACES;      
  207.      term = ' ';
  208.      done_word = 0;
  209.      chars_seen = 0;
  210.      while(*WordPtr && !done_word && comment <2)
  211.        {
  212.        switch (Phase)
  213.          {
  214.          case SPACES:
  215.            if(isspace(*WordPtr))                  /* skip leading spaces */
  216.              WordPtr++;
  217.            else
  218.              Phase = CHARS;
  219.            break;
  220.          case CHARS:
  221.            if(!escape && *WordPtr == '\\')
  222.              {
  223.              escape = 1;
  224.              WordPtr ++;
  225.              }
  226.            else
  227.              {
  228.              if(term==' ' && !escape && (*WordPtr=='"' || *WordPtr == '\'') )
  229.                {              /* sigle or double quotes ? */
  230.                term = *WordPtr++;
  231.                chars_seen = 1;        
  232.                }
  233.              else
  234.                {
  235.                /* handle ordinary chars */
  236.                if(!escape && term==' ' && WordPtr[0]=='#')
  237.                  {
  238.                  comment=2;
  239.                  done_word = chars_seen; /* comment is appended to valid chars */
  240.                  WordPtr++;
  241.                  }
  242.                else if (!escape && term == ' ' && WordPtr[0]=='-')
  243.                  {
  244.                  comment++;
  245.                  WordPtr++;
  246.                  if(comment==2)
  247.                    done_word = chars_seen; /* comment is appended to valid chars */
  248.                  }
  249.                else if ((*WordPtr=='\r') ||
  250.                         (*WordPtr=='\n') ||
  251.                         (!escape && (*WordPtr == term)))
  252.                  {
  253.                  if (comment==1)
  254.                    *BasePtr++ = '-';
  255.                  comment = 0;
  256.                  Phase = SPACES;
  257.                  *BasePtr = '\0';
  258.                  done_word = 1;
  259.                  WordPtr++;
  260.                  }
  261.                else
  262.                  {
  263.                  if(escape)
  264.                    *BasePtr++ = '\\';
  265.                  if (comment==1)
  266.                    *BasePtr++ = '-';
  267.                  chars_seen = 1;
  268.                  comment = 0;
  269.                  escape = 0;
  270.                  *BasePtr++ = *WordPtr++;
  271.                  }
  272.                }
  273.              }
  274.             break;
  275.             } /* switch */
  276.           } /* while */
  277.           *BasePtr = '\0';
  278.             /* make_string now performs an expand_string call */
  279.           if(chars_seen)
  280.               {
  281.               argv[argc++] = make_string(copy_buff,cmd_first,cmd_last);
  282.              }
  283.            
  284.        }
  285.    * pargc = argc;    
  286.    free(copy_buff);
  287.  
  288.    return (OKCMD);
  289.    }
  290.  
  291. /********************************* executes the command from stdin or a do file **************************/
  292.  
  293. int ExecuteCommand (FILE * CmdFile,int nArgs, char * Args[])
  294.    {
  295.    char Buff[PATHLENGTH];
  296.    int  i, Status;
  297.    char * p;
  298.    int    argc;
  299.    char * argv[WORDSINLINE];
  300.    struct str * cmd_first, * cmd_last;
  301.    cmd_first = NULL;
  302.    cmd_last  = NULL;
  303.  
  304.  
  305.  
  306.    if(!CmdFile || feof(CmdFile))
  307.      return(QUITCMD);
  308.  
  309.    p=fgets(Buff,PATHLENGTH-1,CmdFile);                                    /* read the command from the input stream */
  310.    argc=0;                                    /* place the command in the command structure */
  311.    if(p==NULL || *Buff=='\0')
  312.      return(OKCMD);
  313.  
  314.    /* convert control codes to spaces */
  315.    i=0;
  316.    while(Buff[i]) {
  317.      if (Buff[i]<' ')
  318.        Buff[i]=' ';
  319.      i++;
  320.      }
  321.    
  322.    FindWords (Buff,&argc,argv, nArgs,Args,&cmd_first,&cmd_last);                                   /* split off the words and save in structure */
  323.    if (1 || CmdFile != stdin) {
  324.      printf("-- ");
  325.      for(i=0;i<argc;i++)
  326.       printf("%s ",ISNULLSTR(argv[i])?"\"\"":argv[i]); /* log the command word by word if its not given interactively */
  327.      printf("\n"); /*  */
  328.      }
  329. /* the code below is not as helpful as it seems . Moved recognizer for comments into
  330.    Execute as the comments can appear at any point on the command line */
  331. /*   if (argc ==0 ||
  332.        argv[0][0] == '-' ||
  333.        argv[0][0] == '#') */
  334.    if(argc==0)
  335.      {
  336.  
  337. /* deallocate any previous structures */
  338.      free_strings(&cmd_first,&cmd_last);
  339.      return (OKCMD) ; /* comment or a null string */
  340.      }
  341.  
  342.    Status = Execute(argc,argv,TopMenu);                            /* pass the command through the top-level menu */
  343.    switch (Status) {
  344.      case UNKNOWNCMD :
  345.        Log (LOG_ERROR, "# Unknown command\n");
  346.        break;
  347.      case NARGS :
  348.        Log (LOG_ERROR, "# Too few parameters\n");
  349.        break;
  350.      case FAILED     :
  351.        Log (LOG_ERROR, "# Problem with command\n");
  352.        break;
  353.      };
  354.  
  355.    if (Status !=OKCMD) {
  356.      Log(LOG_ERROR,"-- ? ");
  357.      for (i=0; i < argc; i++)     /*    display offending command */
  358.        Log (LOG_ERROR,  " %s", ISNULLSTR(argv[i])?"\"\"":argv[i]);
  359.  
  360.      Log(LOG_ERROR,"\n");
  361.  
  362.      };
  363.  
  364. /* deallocate any previous structures */
  365.    free_strings(&cmd_first,&cmd_last);
  366.  
  367.  
  368.    return(Status);
  369.    }
  370.    
  371. /********************************* Execute a command string ******************************************/
  372. int ExecuteString (char * commandstring , int nArgs, char * Args[]) {
  373.   int argc =0;
  374.   char * argv[WORDSINLINE];
  375.   int     Status = 0;
  376.  
  377.   struct str * cmd_first, * cmd_last;
  378.   cmd_first = NULL;
  379.   cmd_last  = NULL;
  380.   FindWords (commandstring,&argc,argv, nArgs,Args,&cmd_first,&cmd_last);                                   /* split off the words and save in structure */
  381.   Status = Execute(argc,argv,TopMenu);                            /* pass the command through the top-level menu */
  382. /* deallocate any previous structures */
  383.   free_strings(&cmd_first,&cmd_last);
  384.   return(Status);
  385.   }
  386.  
  387.    
  388.    
  389.    
  390.    
  391.    
  392. /********************************* A parser for the '*.do files ******************************************/
  393. static int Depth=0;
  394. #define MAXDEPTH 10                    /* maximum depth of 'do' files */
  395. #define MAXARGV  10
  396. int ParseFile (FILE * CmdFile,int nArgs,char * Args[])
  397.    {
  398.    int     Status = 0;
  399.    char * argp[MAXARGV];
  400.    char ** argp_prev;
  401.    int     nArgs_prev;
  402.    int i;
  403. /* diagnosis */
  404.    if ( nArgs > MAXARGV )
  405.      nArgs = MAXARGV;
  406.    if ( nArgs < 0 )
  407.      nArgs = 0;
  408. /* belt and braces null check */
  409.    if(!CmdFile)
  410.      return(FAILED);
  411.    
  412.    if(feof(CmdFile))
  413.      return(FAILED);
  414.  
  415.    for(i=0;i<MAXARGV;i++) {
  416.    
  417.      if (i < nArgs)
  418.        argp[i] = strdup(Args[i]);
  419.      else
  420.        argp[i] = NULL;
  421.        
  422.        
  423.      /* printf("Arg [%2d]='%s'\n",i,argp[i]);  */
  424.      
  425.      }
  426.    nArgs_prev = yy_nArgs;
  427.    argp_prev  = yy_Args;
  428.    yy_nArgs = nArgs;
  429.    yy_Args  = argp;
  430.  
  431.    Depth ++;                                 /* keep a count of recursion depth */
  432.    printf("-- Command file nesting level = %d\n",Depth);
  433.    if (Depth > MAXDEPTH)
  434.       {
  435.       Log (LOG_ERROR, "Recursive call of files is greater than %d\n", MAXDEPTH);
  436.       Depth--;
  437.       return (FAILED);
  438.  
  439.       }
  440.    while(Status == OKCMD )                    /* execute the command from do file input stream */
  441.       Status = ExecuteCommand(CmdFile, nArgs, argp);
  442.   Depth--;
  443.   yy_nArgs = nArgs_prev;
  444.   yy_Args  = argp_prev;
  445.   for(i=0;i<MAXARGV;i++)
  446.      if (argp[i]) {
  447.        free(argp[i]);
  448.        argp[i] = NULL;
  449.        }
  450.    return(Status);
  451.    }
  452.  
  453. /*********************************************************************************************************/
  454.