Subversion Repositories Vertical

Rev

Rev 2 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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