Subversion Repositories Vertical

Rev

Rev 11 | Details | Compare with Previous | Last modification | View Log | RSS feed

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