Subversion Repositories Vertical

Rev

Blame | 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 "cmdparse.h"
  87.  
  88. #include "cmdexec.h"
  89. #include "cmdlog.h"
  90. #include "cmdutil.h"
  91. #include "database.h"
  92. #include "expression.h"
  93. #include "generic.h"
  94. #include "vertcl_main.h"
  95.  
  96. #include <ctype.h>
  97. #include <stdio.h>
  98. #include <stdlib.h>
  99. #include <string.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                                                                                        \
  106.     "@(#)$Header: /cygwin/cvsroot/vertical/cmdparse.c,v 1.18 2002/09/09 10:26:56 mjames Exp $"
  107.  
  108. /******************************************* Execute a command
  109.  * ******************************************/
  110. /* define flag for global control of execution mode
  111.  * can be Tcl_Cmd or  Tcl_GUI : default to be Tcl_Cmd for
  112.  * backwards compatibility */
  113.  
  114. tcl_mode_t tcl_mode = Tcl_Cmd;
  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;
  134.                              j++) /* upper case significant chars */
  135.                                 putchar (toupper (Dispatch[i].name[j]));
  136.                         for (; Dispatch[i].name[j];
  137.                              j++) /* and all of the rest, we just print */
  138.                                 putchar (Dispatch[i].name[j]);
  139.                         putchar (' ');
  140.                         j++;
  141.                         if (Dispatch[i].extras)
  142.                         {
  143.                                 p = j;
  144.                                 for (; Dispatch[i].extras[j - p];
  145.                                      j++) /* and all of the extras field we just print */
  146.                                         putchar (Dispatch[i].extras[j - p]);
  147.                         };
  148.                         for (; j < CMDWIDTH; j++) /* create spacing , relies on auto - wrap */
  149.                                 putchar (j & 1 ? '.' : ' ');
  150.                         putchar (' ');
  151.                         puts (Dispatch[i].helpstr);
  152.                 }
  153.                 putchar ('\n');
  154.                 FinalResult = OKCMD; /* ? is a valid command at this level */
  155.         }
  156.         else
  157.         {
  158.                 for (i = 0; Dispatch[i].name; i++)
  159.                         if (strncmp (argv[0], Dispatch[i].name, Dispatch[i].NumChar) == 0)
  160.                         {
  161.                                 /* Dispatch the next level command */
  162.                                 if (Dispatch[i].function)
  163.                                 { /* call function if there */
  164.                                         FinalResult = (*Dispatch[i].function) (
  165.                                             Tcl_interp, NULL, argc - 1, argv + 1);
  166.                                 }
  167.                                 else /* call down the menu */
  168.                                         FinalResult =
  169.                                             Execute (argc - 1, argv + 1, Dispatch[i].Menu);
  170.                                 break;
  171.                         }
  172.         }
  173.         return (FinalResult);
  174. }
  175.  
  176. /******************************************** Strip off words
  177.  * ********************************************/
  178. /* this needs repairing . This code is unsafe.
  179.  * Needs to keep a record of how many chars copied !!
  180.  * and stop when in danger of a buffer overflow.
  181.  *
  182.  * Did not work properly if expanded strings are longer than the
  183.  * original strings. This now fixed.
  184.  *
  185.  * Code modified to use some string allocation functions in lx_support.c
  186.  */
  187. /*char wordbuff[1024];
  188.  */
  189. typedef enum
  190. {
  191.         SPACES,
  192.         CHARS
  193. } Phase_t;
  194.  
  195. int FindWords (
  196.     char *linebuff,
  197.     int *pargc,
  198.     char *argv[],
  199.     int nArgs,
  200.     char *Args[],
  201.     struct str **cmd_first,
  202.     struct str **cmd_last)
  203. {
  204.         char *WordPtr;
  205.         char *BasePtr;
  206.         int argc = 0;
  207.         int term = ' ', escape, comment, done_word, chars_seen;
  208.         char *copy_buff;
  209.         Phase_t Phase;
  210.  
  211.         copy_buff = malloc (strlen (linebuff) + 1); /* make a safe copy */
  212.  
  213.         /*      for (i=0; i<Len; i++)                               */
  214.         /*         Cmd->Text[i] = tolower(Cmd->Text[i]);            */ /* convert text to lower
  215.                                                                           case */
  216.         WordPtr = linebuff; /* set LineStart to beginning of string */
  217.         escape = 0;
  218.         comment = 0;
  219.         /* Now split off the words */
  220.         BasePtr = NULL;
  221.         while (*WordPtr && argc < WORDSINLINE && comment < 2)
  222.         {
  223.                 BasePtr = copy_buff;
  224.                 Phase = SPACES;
  225.                 term = ' ';
  226.                 done_word = 0;
  227.                 chars_seen = 0;
  228.                 while (*WordPtr && !done_word && comment < 2)
  229.                 {
  230.                         switch (Phase)
  231.                         {
  232.                         case SPACES:
  233.                                 if (isspace (*WordPtr)) /* skip leading spaces */
  234.                                         WordPtr++;
  235.                                 else
  236.                                         Phase = CHARS;
  237.                                 break;
  238.                         case CHARS:
  239.                                 if (!escape && *WordPtr == '\\')
  240.                                 {
  241.                                         escape = 1;
  242.                                         WordPtr++;
  243.                                 }
  244.                                 else
  245.                                 {
  246.                                         if (term == ' ' && !escape &&
  247.                                             (*WordPtr == '"' || *WordPtr == '\''))
  248.                                         { /* sigle or double quotes ? */
  249.                                                 term = *WordPtr++;
  250.                                                 chars_seen = 1;
  251.                                         }
  252.                                         else
  253.                                         {
  254.                                                 /* handle ordinary chars */
  255.                                                 if (!escape && term == ' ' &&
  256.                                                     WordPtr[0] == '#')
  257.                                                 {
  258.                                                         comment = 2;
  259.                                                         done_word =
  260.                                                             chars_seen; /* comment is appended
  261.                                                                            to valid chars */
  262.                                                         WordPtr++;
  263.                                                 }
  264.                                                 else if (
  265.                                                     !escape && term == ' ' &&
  266.                                                     WordPtr[0] == '-')
  267.                                                 {
  268.                                                         comment++;
  269.                                                         WordPtr++;
  270.                                                         if (comment == 2)
  271.                                                                 done_word =
  272.                                                                     chars_seen; /* comment is
  273.                                                                                    appended to
  274.                                                                                    valid chars
  275.                                                                                  */
  276.                                                 }
  277.                                                 else if (
  278.                                                     (*WordPtr == '\r') || (*WordPtr == '\n') ||
  279.                                                     (!escape && (*WordPtr == term)))
  280.                                                 {
  281.                                                         if (comment == 1)
  282.                                                                 *BasePtr++ = '-';
  283.                                                         comment = 0;
  284.                                                         Phase = SPACES;
  285.                                                         *BasePtr = '\0';
  286.                                                         done_word = 1;
  287.                                                         WordPtr++;
  288.                                                 }
  289.                                                 else
  290.                                                 {
  291.                                                         if (escape)
  292.                                                                 *BasePtr++ = '\\';
  293.                                                         if (comment == 1)
  294.                                                                 *BasePtr++ = '-';
  295.                                                         chars_seen = 1;
  296.                                                         comment = 0;
  297.                                                         escape = 0;
  298.                                                         *BasePtr++ = *WordPtr++;
  299.                                                 }
  300.                                         }
  301.                                 }
  302.                                 break;
  303.                         } /* switch */
  304.                 }         /* while */
  305.                 *BasePtr = '\0';
  306.                 /* make_string now performs an expand_string call */
  307.                 if (chars_seen)
  308.                 {
  309.                         argv[argc++] = make_string (copy_buff, cmd_first, cmd_last);
  310.                 }
  311.         }
  312.         *pargc = argc;
  313.         free (copy_buff);
  314.  
  315.         return (OKCMD);
  316. }
  317.  
  318. /********************************* executes the command from stdin or a do file
  319.  * **************************/
  320.  
  321. int ExecuteCommand (FILE *CmdFile, int nArgs, char *Args[])
  322. {
  323.         char Buff[PATHLENGTH];
  324.         int i, Status;
  325.         char *p;
  326.         int argc;
  327.         char *argv[WORDSINLINE];
  328.         struct str *cmd_first, *cmd_last;
  329.         cmd_first = NULL;
  330.         cmd_last = NULL;
  331.  
  332.         if (!CmdFile || feof (CmdFile))
  333.                 return (QUITCMD);
  334.  
  335.         p = fgets (Buff, PATHLENGTH - 1, CmdFile); /* read the command from the input stream */
  336.         argc = 0; /* place the command in the command structure */
  337.         if (p == NULL || *Buff == '\0')
  338.                 return (OKCMD);
  339.  
  340.         /* convert control codes to spaces */
  341.         i = 0;
  342.         while (Buff[i])
  343.         {
  344.                 if (Buff[i] < ' ')
  345.                         Buff[i] = ' ';
  346.                 i++;
  347.         }
  348.  
  349.         FindWords (Buff, &argc, argv, nArgs, Args, &cmd_first, &cmd_last); /* split off the
  350.                                                                               words and save in
  351.                                                                               structure */
  352.         if (1 || CmdFile != stdin)
  353.         {
  354.                 printf ("-- ");
  355.                 for (i = 0; i < argc; i++)
  356.                         printf (
  357.                             "%s ",
  358.                             ISNULLSTR (argv[i]) ? "\"\""
  359.                                                 : argv[i]); /* log the command word by word if
  360.                                                                its not given interactively */
  361.                 printf ("\n");                              /*  */
  362.         }
  363.         /* the code below is not as helpful as it seems . Moved recognizer for comments into
  364.            Execute as the comments can appear at any point on the command line */
  365.         /*   if (argc ==0 ||
  366.                argv[0][0] == '-' ||
  367.                argv[0][0] == '#') */
  368.         if (argc == 0)
  369.         {
  370.                 /* deallocate any previous structures */
  371.                 free_strings (&cmd_first, &cmd_last);
  372.                 return (OKCMD); /* comment or a null string */
  373.         }
  374.  
  375.         Status =
  376.             Execute (argc, argv, TopMenu); /* pass the command through the top-level menu */
  377.         switch (Status)
  378.         {
  379.         case UNKNOWNCMD:
  380.                 Log (LOG_ERROR, "# Unknown command\n");
  381.                 break;
  382.         case NARGS:
  383.                 Log (LOG_ERROR, "# Too few parameters\n");
  384.                 break;
  385.         case FAILED:
  386.                 Log (LOG_ERROR, "# Problem with command\n");
  387.                 break;
  388.         };
  389.  
  390.         if (Status != OKCMD)
  391.         {
  392.                 Log (LOG_ERROR, "-- ? ");
  393.                 for (i = 0; i < argc; i++) /*    display offending command */
  394.                         Log (LOG_ERROR, " %s", ISNULLSTR (argv[i]) ? "\"\"" : argv[i]);
  395.  
  396.                 Log (LOG_ERROR, "\n");
  397.         };
  398.  
  399.         /* deallocate any previous structures */
  400.         free_strings (&cmd_first, &cmd_last);
  401.  
  402.         return (Status);
  403. }
  404.  
  405. /********************************* Execute a command string
  406.  * ******************************************/
  407. int ExecuteString (char *commandstring, int nArgs, char *Args[])
  408. {
  409.         int argc = 0;
  410.         char *argv[WORDSINLINE];
  411.         int Status = 0;
  412.  
  413.         struct str *cmd_first, *cmd_last;
  414.         cmd_first = NULL;
  415.         cmd_last = NULL;
  416.         FindWords (
  417.             commandstring, &argc, argv, nArgs, Args, &cmd_first, &cmd_last); /* split off the
  418.                                                                                 words and save
  419.                                                                                 in structure */
  420.         Status =
  421.             Execute (argc, argv, TopMenu); /* pass the command through the top-level menu */
  422.                                            /* deallocate any previous structures */
  423.         free_strings (&cmd_first, &cmd_last);
  424.         return (Status);
  425. }
  426.  
  427. /********************************* A parser for the '*.do files
  428.  * ******************************************/
  429. static int Depth = 0;
  430. #define MAXDEPTH 10 /* maximum depth of 'do' files */
  431. #define MAXARGV 10
  432. int ParseFile (FILE *CmdFile, int nArgs, char *Args[])
  433. {
  434.         int Status = 0;
  435.         char *argp[MAXARGV];
  436.         char **argp_prev;
  437.         int nArgs_prev;
  438.         int i;
  439.         /* diagnosis */
  440.         if (nArgs > MAXARGV)
  441.                 nArgs = MAXARGV;
  442.         if (nArgs < 0)
  443.                 nArgs = 0;
  444.         /* belt and braces null check */
  445.         if (!CmdFile)
  446.                 return (FAILED);
  447.  
  448.         if (feof (CmdFile))
  449.                 return (FAILED);
  450.  
  451.         for (i = 0; i < MAXARGV; i++)
  452.         {
  453.                 if (i < nArgs)
  454.                         argp[i] = strdup (Args[i]);
  455.                 else
  456.                         argp[i] = NULL;
  457.  
  458.                 /* printf("Arg [%2d]='%s'\n",i,argp[i]);  */
  459.         }
  460.         nArgs_prev = yy_nArgs;
  461.         argp_prev = yy_Args;
  462.         yy_nArgs = nArgs;
  463.         yy_Args = argp;
  464.  
  465.         Depth++; /* keep a count of recursion depth */
  466.         printf ("-- Command file nesting level = %d\n", Depth);
  467.         if (Depth > MAXDEPTH)
  468.         {
  469.                 Log (LOG_ERROR, "Recursive call of files is greater than %d\n", MAXDEPTH);
  470.                 Depth--;
  471.                 return (FAILED);
  472.         }
  473.         while (Status == OKCMD) /* execute the command from do file input stream */
  474.                 Status = ExecuteCommand (CmdFile, nArgs, argp);
  475.         Depth--;
  476.         yy_nArgs = nArgs_prev;
  477.         yy_Args = argp_prev;
  478.         for (i = 0; i < MAXARGV; i++)
  479.                 if (argp[i])
  480.                 {
  481.                         free (argp[i]);
  482.                         argp[i] = NULL;
  483.                 }
  484.         return (Status);
  485. }
  486.  
  487. /*********************************************************************************************************/
  488.