Subversion Repositories Vertical

Rev

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