Subversion Repositories Vertical

Rev

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

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