/**********
* $Id: cmdparse.c,v 1.1.1.1 2003/11/04 23:34:56 mjames Exp $ **********
One time Author: Kevin Ross (x6143)
Philips Semiconductors Limited.
Millbrook Industrial Estate, Southampton, SO9 7BH. England.
Date: 13th May 1993
Mostly by Mike James these days
Comment: This program parses the input commands for the SFC3 evaluation software
$Log: cmdparse.c,v $
Revision 1.1.1.1 2003/11/04 23:34:56 mjames
Imported into local repositrory
Revision 1.18 2002/09/09 10:26:56 mjames
Removed set generic range and replaced it with a set generic value command
that takes both integers and ranges.
Revision 1.17 2002/01/16 11:22:41 mjames
database.h header file is read in first as it undefined DLL stuff irrelevant
to HPUX
Revision 1.16 2001/12/20 13:49:48 mjames
force ?
Revision 1.15 2001/12/13 22:14:26 mjames
Corrected nested command handlers to allow variable passing without corruption.
Revision 1.14 2001/10/31 22:20:00 mjames
Tidying up problematical comments caused by CVS
'intelligent' comment guessing
Revision 1.13 2001/10/10 20:19:56 mjames
Adjustment of handling of escapes and comments
Revision 1.12 2001/10/10 10:02:59 mjames
Final tweaks to work with end-of line at end-of-file
Revision 1.11 2001/10/10 09:54:30 mjames
Modified command line handler to correctly recognise
comment leaders anywhere on line, not just as first character.
Revision 1.10 2001/07/09 15:08:44 mjames
Check the last character of a line of text to see if it is actually a control code
before deleting it
Revision 1.9 2001/06/19 05:24:57 mjames
Created a trap_fopen to overcome trying to write to read only files.
If this attempted in NT the file can be opened but not written to.
Revision 1.8 2001/06/06 12:10:24 mjames
Move from HPUX
Revision 1.7 2001/05/01 15:21:18 mjames
Added comment leaders on printout of commands executed
Revision 1.6 2001/04/06 22:47:01 mjames
Added doc2, the creator of documentation to Vertical scripts uses PERL
Also correcting generic behaviour and the printing of Verilog.
Revision 1.5 2001/02/06 22:41:14 mjames
Added correct argument passing for 'read file comp_suffix arg0 arg1 arg2 ...
Revision 1.4 2001/01/26 21:50:10 mjames
Managed to get vertical non TCL to compile again
Conversion to argv, argc[] mode of operation continues
Revision 1.3 2001/01/04 21:26:54 mjames
Modifications to add in the TCL style
argument list to all of the functions
.
Revision 1.2 2001/01/02 07:53:52 mjames
Made changes to allow for interface with TCL/Tk
Revision 1.1.1.1 2000/10/19 21:58:35 mjames
Mike put it here
There has been a lot more development, but the comments have been
removed in order to cut down the junk
*********************************************************************************************************/
#include "cmdparse.h"
#include "cmdexec.h"
#include "cmdlog.h"
#include "cmdutil.h"
#include "database.h"
#include "expression.h"
#include "generic.h"
#include "vertcl_main.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* used for dynamic string allocation/deallocation code
* used here for command keywords May 2 2000 */
#include "lx_support.h"
/*********************************************************************************************************/
#ident \
"@(#)$Header: c:\\cygwin\\cvsroot/Vert03/cmdlib/cmdparse.c,v 1.1.1.1 2003/11/04 23:34:56 mjames Exp $"
/******************************************* Execute a command
* ******************************************/
/* define flag for global control of execution mode
* can be Tcl_Cmd or Tcl_GUI : default to be Tcl_Cmd for
* backwards compatibility */
tcl_mode_t tcl_mode = Tcl_Cmd;
#define WORDWIDTH 100 /* max command word ever expected */
#define CMDWIDTH 20 /*Field width for printing CMD word */
int Execute (int argc, char *argv[], struct command Dispatch[])
{
int i, j, FinalResult = UNKNOWNCMD;
if (!argc)
return (NARGS);
if (argv[0][0] == '?')
{
printf ("Commands available;\nHelp on:");
for (i = 0; i < argc; i++)
for (i = 0; Dispatch[i].name; i++)
{
int p;
for (j = 0; j < Dispatch[i].NumChar;
j++) /* upper case significant chars */
for (; Dispatch[i].name[j];
j++) /* and all of the rest, we just print */
j++;
if (Dispatch[i].extras)
{
p = j;
for (; Dispatch[i].extras[j - p];
j++) /* and all of the extras field we just print */
putchar (Dispatch
[i
].
extras[j
- p
]);
};
for (; j < CMDWIDTH; j++) /* create spacing , relies on auto - wrap */
puts (Dispatch
[i
].
helpstr);
}
FinalResult = OKCMD; /* ? is a valid command at this level */
}
else
{
for (i = 0; Dispatch[i].name; i++)
if (strncmp (argv
[0], Dispatch
[i
].
name, Dispatch
[i
].
NumChar) == 0)
{
/* Dispatch the next level command */
if (Dispatch[i].function)
{ /* call function if there */
FinalResult = (*Dispatch[i].function) (
Tcl_interp, NULL, argc - 1, argv + 1);
}
else /* call down the menu */
FinalResult =
Execute (argc - 1, argv + 1, Dispatch[i].Menu);
break;
}
}
return (FinalResult);
}
/******************************************** Strip off words
* ********************************************/
/* this needs repairing . This code is unsafe.
* Needs to keep a record of how many chars copied !!
* and stop when in danger of a buffer overflow.
*
* Did not work properly if expanded strings are longer than the
* original strings. This now fixed.
*
* Code modified to use some string allocation functions in lx_support.c
*/
/*char wordbuff[1024];
*/
typedef enum
{
SPACES,
CHARS
} Phase_t;
int FindWords (
char *linebuff,
int *pargc,
char *argv[],
int nArgs,
char *Args[],
struct str **cmd_first,
struct str **cmd_last)
{
char *WordPtr;
char *BasePtr;
int argc = 0;
int term = ' ', escape, comment, done_word, chars_seen;
char *copy_buff;
Phase_t Phase;
copy_buff
= malloc (strlen (linebuff
) + 1); /* make a safe copy */
/* for (i=0; i<Len; i++) */
/* Cmd->Text[i] = tolower(Cmd->Text[i]); */ /* convert text to lower
case */
WordPtr = linebuff; /* set LineStart to beginning of string */
escape = 0;
comment = 0;
/* Now split off the words */
BasePtr = NULL;
while (*WordPtr && argc < WORDSINLINE && comment < 2)
{
BasePtr = copy_buff;
Phase = SPACES;
term = ' ';
done_word = 0;
chars_seen = 0;
while (*WordPtr && !done_word && comment < 2)
{
switch (Phase)
{
case SPACES:
if (isspace (*WordPtr
)) /* skip leading spaces */
WordPtr++;
else
Phase = CHARS;
break;
case CHARS:
if (!escape && *WordPtr == '\\')
{
escape = 1;
WordPtr++;
}
else
{
if (term == ' ' && !escape &&
(*WordPtr == '"' || *WordPtr == '\''))
{ /* sigle or double quotes ? */
term = *WordPtr++;
chars_seen = 1;
}
else
{
/* handle ordinary chars */
if (!escape && term == ' ' &&
WordPtr[0] == '#')
{
comment = 2;
done_word =
chars_seen; /* comment is appended
to valid chars */
WordPtr++;
}
else if (
!escape && term == ' ' &&
WordPtr[0] == '-')
{
comment++;
WordPtr++;
if (comment == 2)
done_word =
chars_seen; /* comment is
appended to
valid chars
*/
}
else if (
(*WordPtr == '\r') || (*WordPtr == '\n') ||
(!escape && (*WordPtr == term)))
{
if (comment == 1)
*BasePtr++ = '-';
comment = 0;
Phase = SPACES;
*BasePtr = '\0';
done_word = 1;
WordPtr++;
}
else
{
if (escape)
*BasePtr++ = '\\';
if (comment == 1)
*BasePtr++ = '-';
chars_seen = 1;
comment = 0;
escape = 0;
*BasePtr++ = *WordPtr++;
}
}
}
break;
} /* switch */
} /* while */
*BasePtr = '\0';
/* make_string now performs an expand_string call */
if (chars_seen)
{
argv[argc++] = make_string (copy_buff, cmd_first, cmd_last);
}
}
*pargc = argc;
return (OKCMD);
}
/********************************* executes the command from stdin or a do file
* **************************/
int ExecuteCommand (FILE *CmdFile, int nArgs, char *Args[])
{
char Buff[PATHLENGTH];
int i, Status;
char *p;
int argc;
char *argv[WORDSINLINE];
struct str *cmd_first, *cmd_last;
cmd_first = NULL;
cmd_last = NULL;
if (!CmdFile
|| feof (CmdFile
))
return (QUITCMD);
p
= fgets (Buff
, PATHLENGTH
- 1, CmdFile
); /* read the command from the input stream */
argc = 0; /* place the command in the command structure */
if (p == NULL || *Buff == '\0')
return (OKCMD);
/* convert control codes to spaces */
i = 0;
while (Buff[i])
{
if (Buff[i] < ' ')
Buff[i] = ' ';
i++;
}
FindWords (Buff, &argc, argv, nArgs, Args, &cmd_first, &cmd_last); /* split off the
words and save in
structure */
if (1 || CmdFile != stdin)
{
for (i = 0; i < argc; i++)
"%s ",
ISNULLSTR (argv[i]) ? "\"\""
: argv[i]); /* log the command word by word if
its not given interactively */
}
/* the code below is not as helpful as it seems . Moved recognizer for comments into
Execute as the comments can appear at any point on the command line */
/* if (argc ==0 ||
argv[0][0] == '-' ||
argv[0][0] == '#') */
if (argc == 0)
{
/* deallocate any previous structures */
free_strings (&cmd_first, &cmd_last);
return (OKCMD); /* comment or a null string */
}
Status =
Execute (argc, argv, TopMenu); /* pass the command through the top-level menu */
switch (Status)
{
case UNKNOWNCMD:
Log (LOG_ERROR, "# Unknown command\n");
break;
case NARGS:
Log (LOG_ERROR, "# Too few parameters\n");
break;
case FAILED:
Log (LOG_ERROR, "# Problem with command\n");
break;
};
if (Status != OKCMD)
{
Log (LOG_ERROR, "-- ? ");
for (i = 0; i < argc; i++) /* display offending command */
Log (LOG_ERROR, " %s", ISNULLSTR (argv[i]) ? "\"\"" : argv[i]);
Log (LOG_ERROR, "\n");
};
/* deallocate any previous structures */
free_strings (&cmd_first, &cmd_last);
return (Status);
}
/********************************* Execute a command string
* ******************************************/
int ExecuteString (char *commandstring, int nArgs, char *Args[])
{
int argc = 0;
char *argv[WORDSINLINE];
int Status = 0;
struct str *cmd_first, *cmd_last;
cmd_first = NULL;
cmd_last = NULL;
FindWords (
commandstring, &argc, argv, nArgs, Args, &cmd_first, &cmd_last); /* split off the
words and save
in structure */
Status =
Execute (argc, argv, TopMenu); /* pass the command through the top-level menu */
/* deallocate any previous structures */
free_strings (&cmd_first, &cmd_last);
return (Status);
}
/********************************* A parser for the '*.do files
* ******************************************/
static int Depth = 0;
#define MAXDEPTH 10 /* maximum depth of 'do' files */
#define MAXARGV 10
int ParseFile (FILE *CmdFile, int nArgs, char *Args[])
{
int Status = 0;
char *argp[MAXARGV];
char **argp_prev;
int nArgs_prev;
int i;
/* diagnosis */
if (nArgs > MAXARGV)
nArgs = MAXARGV;
if (nArgs < 0)
nArgs = 0;
/* belt and braces null check */
if (!CmdFile)
return (FAILED);
for (i = 0; i < MAXARGV; i++)
{
if (i < nArgs)
argp[i] = strdup (Args[i]);
else
argp[i] = NULL;
/* printf("Arg [%2d]='%s'\n",i,argp[i]); */
}
nArgs_prev = yy_nArgs;
argp_prev = yy_Args;
yy_nArgs = nArgs;
yy_Args = argp;
Depth++; /* keep a count of recursion depth */
printf ("-- Command file nesting level = %d\n", Depth
);
if (Depth > MAXDEPTH)
{
Log (LOG_ERROR, "Recursive call of files is greater than %d\n", MAXDEPTH);
Depth--;
return (FAILED);
}
while (Status == OKCMD) /* execute the command from do file input stream */
Status = ExecuteCommand (CmdFile, nArgs, argp);
Depth--;
yy_nArgs = nArgs_prev;
yy_Args = argp_prev;
for (i = 0; i < MAXARGV; i++)
if (argp[i])
{
argp[i] = NULL;
}
return (Status);
}
/*********************************************************************************************************/