Subversion Repositories Vertical

Rev

Rev 2 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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