Subversion Repositories Vertical

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 mjames 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
/*********************************************************************************************************/