00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdio.h>
00022 #include <stdlib.h>
00023 #include <ctype.h>
00024 #include <string.h>
00025
00026 #include "cmd.h"
00027
00028 static Enum_T BoolEnum[] = {
00029 { "FALSE", 0 },
00030 { "TRUE", 1 },
00031 { 0, 0 }
00032 };
00033
00034 #ifdef NEEDSTRDUP
00035 char *strdup();
00036 #endif
00037
00038 #define FALSE 0
00039 #define TRUE 1
00040
00041 #define LINSIZ 10240
00042 #define MAXPARAM 256
00043
00044 static char *GetLine(),
00045 **str2array();
00046 static int Scan(),
00047 SetParam(),
00048 SetEnum(),
00049 SetSubrange(),
00050 SetStrArray(),
00051 SetGte(),
00052 SetLte(),
00053 CmdError(),
00054 EnumError(),
00055 SubrangeError(),
00056 GteError(),
00057 LteError(),
00058 PrintParam(),
00059 PrintEnum(),
00060 PrintStrArray();
00061
00062 static Cmd_T cmds[MAXPARAM+1];
00063 static char *SepString = " \t\n";
00064
00065 #if defined(__STDC__)
00066 #include <stdarg.h>
00067 int DeclareParams(const char *ParName, ...)
00068 #else
00069 #include <varargs.h>
00070 int DeclareParams(ParName, va_alist)
00071 char *ParName;
00072 va_dcl
00073 #endif
00074 {
00075 va_list args;
00076 static int ParamN = 0;
00077 int j,
00078 c;
00079 char *s;
00080
00081 #if defined(__STDC__)
00082 va_start(args, ParName);
00083 #else
00084 va_start(args);
00085 #endif
00086 for(;ParName;) {
00087 if(ParamN==MAXPARAM) {
00088 fprintf(stderr, "Too many parameters !!\n");
00089 break;
00090 }
00091 for(j=0,c=1; j<ParamN&&(c=strcmp(cmds[j].Name,ParName))<0; j++)
00092 ;
00093 if(!c) {
00094 fprintf(stderr,
00095 "Warning: parameter \"%s\" declared twice.\n",
00096 ParName);
00097 }
00098 for(c=ParamN; c>j; c--) {
00099 cmds[c] = cmds[c-1];
00100 }
00101 cmds[j].Name = ParName;
00102 cmds[j].Type = va_arg(args, int);
00103 cmds[j].Val = va_arg(args, void *);
00104 switch(cmds[j].Type) {
00105 case CMDENUMTYPE:
00106 cmds[j].p = va_arg(args, void *);
00107 break;
00108 case CMDSUBRANGETYPE:
00109 cmds[j].p = (void*) calloc(2, sizeof(int));
00110 ((int*)cmds[j].p)[0] = va_arg(args, int);
00111 ((int*)cmds[j].p)[1] = va_arg(args, int);
00112 break;
00113 case CMDGTETYPE:
00114 case CMDLTETYPE:
00115 cmds[j].p = (void*) calloc(1, sizeof(int));
00116 ((int*)cmds[j].p)[0] = va_arg(args, int);
00117 break;
00118 case CMDSTRARRAYTYPE:
00119 cmds[j].p = (s=va_arg(args, char*))
00120 ? (void*)strdup(s) : 0;
00121 break;
00122 case CMDBOOLTYPE:
00123 cmds[j].Type = CMDENUMTYPE;
00124 cmds[j].p = BoolEnum;
00125 break;
00126 case CMDDOUBLETYPE:
00127 case CMDINTTYPE:
00128 case CMDSTRINGTYPE:
00129 break;
00130 default:
00131 fprintf(stderr, "%s: %s %d %s \"%s\"\n",
00132 "DeclareParam()", "Unknown Type",
00133 cmds[j].Type, "for parameter", cmds[j].Name);
00134 exit(1);
00135 }
00136 ParamN++;
00137 ParName = va_arg(args, char *);
00138 }
00139 cmds[ParamN].Name = NULL;
00140 va_end(args);
00141 return 0;
00142 }
00143
00144 int GetParams(n, a, CmdFileName)
00145 int *n;
00146 char ***a;
00147 char *CmdFileName;
00148 {
00149 char *Line,
00150 *ProgName;
00151 int argc = *n;
00152 char **argv = *a,
00153 *s;
00154 FILE *fp;
00155 int IsPipe;
00156
00157 #ifdef MSDOS
00158 #define PATHSEP '\\'
00159 char *dot = NULL;
00160 #else
00161 #define PATHSEP '/'
00162 #endif
00163
00164 if(!(Line=malloc(LINSIZ))) {
00165 fprintf(stderr, "GetParams(): Unable to alloc %d bytes\n",
00166 LINSIZ);
00167 exit(1);
00168 }
00169 if((ProgName=strrchr(*argv, PATHSEP))) {
00170 ++ProgName;
00171 } else {
00172 ProgName = *argv;
00173 }
00174 #ifdef MSDOS
00175 if(dot=strchr(ProgName, '.')) *dot = 0;
00176 #endif
00177 --argc;
00178 ++argv;
00179 for(;;) {
00180 if(argc && argv[0][0]=='-' && argv[0][1]=='=') {
00181 CmdFileName = argv[0]+2;
00182 ++argv;
00183 --argc;
00184 }
00185 if(!CmdFileName) {
00186 break;
00187 }
00188 IsPipe = !strncmp(CmdFileName, "@@", 2);
00189 fp = IsPipe
00190 ? popen(CmdFileName+2, "r")
00191 : strcmp(CmdFileName, "-")
00192 ? fopen(CmdFileName, "r")
00193 : stdin;
00194 if(!fp) {
00195 fprintf(stderr, "Unable to open command file %s\n",
00196 CmdFileName);
00197 exit(1);
00198 }
00199 while(GetLine(fp, LINSIZ, Line) && strcmp(Line, "\\End")) {
00200 if(Scan(ProgName, cmds, Line)) {
00201 CmdError(Line);
00202 }
00203 }
00204 if(fp!=stdin) {
00205 if(IsPipe) pclose(fp); else fclose(fp);
00206 }
00207 CmdFileName = NULL;
00208 }
00209 while(argc && **argv=='-' && (s=strchr(*argv, '='))) {
00210 *s = ' ';
00211 sprintf(Line, "%s/%s", ProgName, *argv+1);
00212 *s = '=';
00213 if(Scan(ProgName, cmds, Line)) CmdError(*argv);
00214 --argc;
00215 ++argv;
00216 }
00217 *n = argc;
00218 *a = argv;
00219 #ifdef MSDOS
00220 if(dot) *dot = '.';
00221 #endif
00222 free(Line);
00223 return 0;
00224 }
00225
00226 int PrintParams(ValFlag, fp)
00227 int ValFlag;
00228 FILE *fp;
00229 {
00230 int i;
00231
00232 fflush(fp);
00233 if(ValFlag) {
00234 fprintf(fp, "Parameters Values:\n");
00235 } else {
00236 fprintf(fp, "Parameters:\n");
00237 }
00238 for(i=0; cmds[i].Name; i++) PrintParam(cmds+i, ValFlag, fp);
00239 fprintf(fp, "\n");
00240 fflush(fp);
00241 return 0;
00242 }
00243
00244 int SPrintParams(a, pfx)
00245 char ***a,
00246 *pfx;
00247 {
00248 int l,
00249 n;
00250 Cmd_T *cmd;
00251
00252 if(!pfx) pfx="";
00253 l = strlen(pfx);
00254 for(n=0, cmd=cmds; cmd->Name; cmd++) n += !!cmd->ArgStr;
00255 a[0] = calloc(n, sizeof(char*));
00256 for(n=0, cmd=cmds; cmd->Name; cmd++) {
00257 if(!cmd->ArgStr) continue;
00258 a[0][n] = malloc(strlen(cmd->Name)+strlen(cmd->ArgStr)+l+2);
00259 sprintf(a[0][n], "%s%s=%s", pfx, cmd->Name, cmd->ArgStr);
00260 ++n;
00261 }
00262 return n;
00263 }
00264
00265 static int CmdError(opt)
00266 char *opt;
00267 {
00268 fprintf(stderr, "Invalid option \"%s\"\n", opt);
00269 fprintf(stderr, "This program expectes the following parameters:\n");
00270 PrintParams(FALSE, stderr);
00271 exit(0);
00272 }
00273
00274 static int PrintParam(cmd, ValFlag, fp)
00275 Cmd_T *cmd;
00276 int ValFlag;
00277 FILE *fp;
00278 {
00279 fprintf(fp, "%4s", "");
00280 switch(cmd->Type) {
00281 case CMDDOUBLETYPE:
00282 fprintf(fp, "%s", cmd->Name);
00283 if(ValFlag) fprintf(fp, ": %22.15e", *(double *)cmd->Val);
00284 fprintf(fp, "\n");
00285 break;
00286 case CMDENUMTYPE:
00287 PrintEnum(cmd, ValFlag, fp);
00288 break;
00289 case CMDINTTYPE:
00290 case CMDSUBRANGETYPE:
00291 case CMDGTETYPE:
00292 case CMDLTETYPE:
00293 fprintf(fp, "%s", cmd->Name);
00294 if(ValFlag) fprintf(fp, ": %d", *(int *)cmd->Val);
00295 fprintf(fp, "\n");
00296 break;
00297 case CMDSTRINGTYPE:
00298 fprintf(fp, "%s", cmd->Name);
00299 if(ValFlag) {
00300 if(*(char **)cmd->Val) {
00301 fprintf(fp, ": \"%s\"", *(char **)cmd->Val);
00302 } else {
00303 fprintf(fp, ": %s", "NULL");
00304 }
00305 }
00306 fprintf(fp, "\n");
00307 break;
00308 case CMDSTRARRAYTYPE:
00309 PrintStrArray(cmd, ValFlag, fp);
00310 break;
00311 default:
00312 fprintf(stderr, "%s: %s %d %s \"%s\"\n",
00313 "PrintParam",
00314 "Unknown Type",
00315 cmd->Type,
00316 "for parameter",
00317 cmd->Name);
00318 exit(1);
00319 }
00320 return 0;
00321 }
00322
00323 static char *GetLine(fp, n, Line)
00324 FILE *fp;
00325 int n;
00326 char *Line;
00327 {
00328 int j,
00329 l,
00330 offs=0;
00331
00332 for(;;) {
00333 if(!fgets(Line+offs, n-offs, fp)) {
00334 return NULL;
00335 }
00336 if(Line[offs]=='#') continue;
00337 l = strlen(Line+offs)-1;
00338 Line[offs+l] = 0;
00339 for(j=offs; Line[j] && isspace(Line[j]); j++, l--)
00340 ;
00341 if(l<1) continue;
00342 if(j > offs) {
00343 char *s = Line+offs,
00344 *q = Line+j;
00345
00346 while((*s++=*q++))
00347 ;
00348 }
00349 if(Line[offs+l-1]=='\\') {
00350 offs += l;
00351 Line[offs-1] = ' ';
00352 } else {
00353 break;
00354 }
00355 }
00356 return Line;
00357 }
00358
00359 static int Scan(ProgName, cmds, Line)
00360 char *ProgName,
00361 *Line;
00362 Cmd_T *cmds;
00363 {
00364 char *q,
00365 *p;
00366 int i,
00367 hl,
00368 HasToMatch = FALSE,
00369 c0,
00370 c;
00371
00372 p = Line+strspn(Line, SepString);
00373 if(!(hl=strcspn(p, SepString))) {
00374 return 0;
00375 }
00376 if((q=strchr(p, '/')) && q-p<hl) {
00377 *q = 0;
00378 if(strcmp(p, ProgName)) {
00379 *q = '/';
00380 return 0;
00381 }
00382 *q = '/';
00383 HasToMatch=TRUE;
00384 p = q+1;
00385 }
00386 if(!(hl = strcspn(p, SepString))) {
00387 return 0;
00388 }
00389 c0 = p[hl];
00390 p[hl] = 0;
00391 for(i=0, c=1; cmds[i].Name&&(c=strcmp(cmds[i].Name, p))<0; i++)
00392 ;
00393 p[hl] = c0;
00394 if(!c) return SetParam(cmds+i, p+hl+strspn(p+hl, SepString));
00395 return HasToMatch && c;
00396 }
00397
00398 static int SetParam(cmd, s)
00399 Cmd_T *cmd;
00400 char *s;
00401 {
00402 if(!*s && cmd->Type != CMDSTRINGTYPE) {
00403 fprintf(stderr,
00404 "WARNING: No value specified for parameter \"%s\"\n",
00405 cmd->Name);
00406 return 0;
00407 }
00408 switch(cmd->Type) {
00409 case CMDDOUBLETYPE:
00410 if(sscanf(s, "%lf", (double*)cmd->Val)!=1) {
00411 fprintf(stderr,
00412 "Float value required for parameter \"%s\"\n",
00413 cmd->Name);
00414 exit(1);
00415 }
00416 break;
00417 case CMDENUMTYPE:
00418 SetEnum(cmd, s);
00419 break;
00420 case CMDINTTYPE:
00421 if(sscanf(s, "%d", (int*)cmd->Val)!=1) {
00422 fprintf(stderr,
00423 "Integer value required for parameter \"%s\"\n",
00424 cmd->Name);
00425 exit(1);
00426 }
00427 break;
00428 case CMDSTRINGTYPE:
00429 *(char **)cmd->Val = (strcmp(s, "<NULL>") && strcmp(s, "NULL"))
00430 ? strdup(s)
00431 : 0;
00432 break;
00433 case CMDSTRARRAYTYPE:
00434 SetStrArray(cmd, s);
00435 break;
00436 case CMDGTETYPE:
00437 SetGte(cmd, s);
00438 break;
00439 case CMDLTETYPE:
00440 SetLte(cmd, s);
00441 break;
00442 case CMDSUBRANGETYPE:
00443 SetSubrange(cmd, s);
00444 break;
00445 default:
00446 fprintf(stderr, "%s: %s %d %s \"%s\"\n",
00447 "SetParam",
00448 "Unknown Type",
00449 cmd->Type,
00450 "for parameter",
00451 cmd->Name);
00452 exit(1);
00453 }
00454 cmd->ArgStr = strdup(s);
00455 return 0;
00456 }
00457
00458 static int SetEnum(cmd, s)
00459 Cmd_T *cmd;
00460 char *s;
00461 {
00462 Enum_T *en;
00463
00464 for(en=(Enum_T *)cmd->p; en->Name; en++) {
00465 if(*en->Name && !strcmp(s, en->Name)) {
00466 *(int *) cmd->Val = en->Idx;
00467 return 0;
00468 }
00469 }
00470 return EnumError(cmd, s);
00471 }
00472
00473 static int SetSubrange(cmd, s)
00474 Cmd_T *cmd;
00475 char *s;
00476 {
00477 int n;
00478
00479 if(sscanf(s, "%d", &n)!=1) {
00480 fprintf(stderr,
00481 "Integer value required for parameter \"%s\"\n",
00482 cmd->Name);
00483 exit(1);
00484 }
00485 if(n < *(int *)cmd->p || n > *((int *)cmd->p+1)) {
00486 return SubrangeError(cmd, n);
00487 }
00488 *(int *)cmd->Val = n;
00489 return 0;
00490 }
00491
00492 static int SetGte(cmd, s)
00493 Cmd_T *cmd;
00494 char *s;
00495 {
00496 int n;
00497
00498 if(sscanf(s, "%d", &n)!=1) {
00499 fprintf(stderr,
00500 "Integer value required for parameter \"%s\"\n",
00501 cmd->Name);
00502 exit(1);
00503 }
00504 if(n<*(int *)cmd->p) {
00505 return GteError(cmd, n);
00506 }
00507 *(int *)cmd->Val = n;
00508 return 0;
00509 }
00510
00511 static int SetStrArray(cmd, s)
00512 Cmd_T *cmd;
00513 char *s;
00514 {
00515 *(char***)cmd->Val = str2array(s, (char*)cmd->p);
00516 return 0;
00517 }
00518
00519 static int SetLte(cmd, s)
00520 Cmd_T *cmd;
00521 char *s;
00522 {
00523 int n;
00524
00525 if(sscanf(s, "%d", &n)!=1) {
00526 fprintf(stderr,
00527 "Integer value required for parameter \"%s\"\n",
00528 cmd->Name);
00529 exit(1);
00530 }
00531 if(n > *(int *)cmd->p) {
00532 return LteError(cmd, n);
00533 }
00534 *(int *)cmd->Val = n;
00535 return 0;
00536 }
00537
00538 static int EnumError(cmd, s)
00539 Cmd_T *cmd;
00540 char *s;
00541 {
00542 Enum_T *en;
00543
00544 fprintf(stderr,
00545 "Invalid value \"%s\" for parameter \"%s\"\n", s, cmd->Name);
00546 fprintf(stderr, "Valid values are:\n");
00547 for(en=(Enum_T *)cmd->p; en->Name; en++) {
00548 if(*en->Name) {
00549 fprintf(stderr, " %s\n", en->Name);
00550 }
00551 }
00552 fprintf(stderr, "\n");
00553 exit(1);
00554 }
00555
00556 static int GteError(cmd, n)
00557 Cmd_T *cmd;
00558 int n;
00559 {
00560 fprintf(stderr,
00561 "Value %d out of range for parameter \"%s\"\n", n, cmd->Name);
00562 fprintf(stderr, "Valid values must be greater than or equal to %d\n",
00563 *(int *)cmd->p);
00564 exit(1);
00565 }
00566
00567 static int LteError(cmd, n)
00568 Cmd_T *cmd;
00569 int n;
00570 {
00571 fprintf(stderr,
00572 "Value %d out of range for parameter \"%s\"\n", n, cmd->Name);
00573 fprintf(stderr, "Valid values must be less than or equal to %d\n",
00574 *(int *)cmd->p);
00575 exit(1);
00576 }
00577
00578 static int SubrangeError(cmd, n)
00579 Cmd_T *cmd;
00580 int n;
00581 {
00582 fprintf(stderr,
00583 "Value %d out of range for parameter \"%s\"\n", n, cmd->Name);
00584 fprintf(stderr, "Valid values range from %d to %d\n",
00585 *(int *)cmd->p, *((int *)cmd->p+1));
00586 exit(1);
00587 }
00588
00589 static int PrintEnum(cmd, ValFlag, fp)
00590 Cmd_T *cmd;
00591 int ValFlag;
00592 FILE *fp;
00593 {
00594 Enum_T *en;
00595
00596 fprintf(fp, "%s", cmd->Name);
00597 if(ValFlag) {
00598 for(en=(Enum_T *)cmd->p; en->Name; en++) {
00599 if(*en->Name && en->Idx==*(int *)cmd->Val) {
00600 fprintf(fp, ": %s", en->Name);
00601 }
00602 }
00603 }
00604 fprintf(fp, "\n");
00605 return 0;
00606 }
00607
00608 static int PrintStrArray(cmd, ValFlag, fp)
00609 Cmd_T *cmd;
00610 int ValFlag;
00611 FILE *fp;
00612 {
00613 char *indent,
00614 **s = *(char***)cmd->Val;
00615 int l = 4+strlen(cmd->Name);
00616
00617 fprintf(fp, "%s", cmd->Name);
00618 indent = malloc(l+2);
00619 memset(indent, ' ', l+1);
00620 indent[l+1] = 0;
00621 if(ValFlag) {
00622 fprintf(fp, ": %s", s ? (*s ? *s++ : "NULL") : "");
00623 if(s) while(*s) {
00624 fprintf(fp, "\n%s %s", indent, *s++);
00625 }
00626 }
00627 free(indent);
00628 fprintf(fp, "\n");
00629 return 0;
00630 }
00631
00632 static char **str2array(s, sep)
00633 char *s,
00634 *sep;
00635 {
00636 char *p,
00637 **a;
00638 int n = 0,
00639 l;
00640
00641 if(!sep) sep = SepString;
00642 p = s += strspn(s, sep);
00643 while(*p) {
00644 p += strcspn(p, sep);
00645 p += strspn(p, sep);
00646 ++n;
00647 }
00648 a = calloc(n+1, sizeof(char *));
00649 p = s;
00650 n = 0;
00651 while(*p) {
00652 l = strcspn(p, sep);
00653 a[n] = malloc(l+1);
00654 memcpy(a[n], p, l);
00655 a[n][l] = 0;
00656 ++n;
00657 p += l;
00658 p += strspn(p, sep);
00659 }
00660 return a;
00661 }