00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef _WIN32_WCE
00022 #include <stdio.h>
00023 #endif
00024
00025 #include <stdlib.h>
00026 #include <ctype.h>
00027 #include <string.h>
00028 #include <stdarg.h>
00029 #if defined(_WIN32)
00030 #include <windows.h>
00031 #else
00032 #include <unistd.h>
00033 #endif
00034
00035 #ifdef USE_UPIO
00036 #include "missing.h"
00037 #include "updef.h"
00038 #endif
00039
00040 #include "cmd.h"
00041
00042
00043 #define FALSE 0
00044 #define TRUE 1
00045
00046 static Enum_T BoolEnum[] = {
00047 { (char*)"FALSE", FALSE},
00048 { (char*)"TRUE", TRUE},
00049 { (char*)"false", FALSE},
00050 { (char*)"true", TRUE},
00051 { (char*)"0", FALSE},
00052 { (char*)"1", TRUE},
00053 { (char*)"NO", FALSE},
00054 { (char*)"YES", TRUE},
00055 { (char*)"No", FALSE},
00056 { (char*)"Yes", TRUE},
00057 { (char*)"no", FALSE},
00058 { (char*)"yes", TRUE},
00059 { (char*)"N", FALSE},
00060 { (char*)"Y", TRUE},
00061 { (char*)"n", FALSE},
00062 { (char*)"y", TRUE},
00063 { 0, 0 }
00064 };
00065
00066 #ifdef NEEDSTRDUP
00067 char *strdup(const char *s);
00068 #endif
00069
00070 #define LINSIZ 10240
00071
00072 static char
00073 *GetLine(FILE *fp,
00074 int n,
00075 char *Line),
00076 **str2array(char *s,
00077 char *sep);
00078 static int
00079 str2narray(int type,
00080 char *s,
00081 char *sep,
00082 void **a);
00083
00084 static int
00085 Scan(char *ProgName,
00086 Cmd_T *cmds,
00087 char *Line),
00088 SetParam(Cmd_T *cmd,
00089 char *s),
00090 SetEnum(Cmd_T *cmd,
00091 char *s),
00092 SetFlag(Cmd_T *cmd,
00093 char *s),
00094 SetSubrange(Cmd_T *cmd,
00095 char *s),
00096 SetStrArray(Cmd_T *cmd,
00097 char *s),
00098 SetNumArray(Cmd_T *cmd,
00099 char *s),
00100 SetGte(Cmd_T *cmd,
00101 char *s),
00102 SetLte(Cmd_T *cmd,
00103 char *s),
00104 CmdError(char *opt),
00105 EnumError(Cmd_T *cmd,
00106 char *s),
00107 SubrangeError(Cmd_T *cmd,
00108 int n),
00109 GteError(Cmd_T *cmd,
00110 int n),
00111 LteError(Cmd_T *cmd,
00112 int n),
00113 PrintParam(Cmd_T *cmd,
00114 int TypeFlag,
00115 int ValFlag,
00116 FILE *fp),
00117 PrintParams4(int TypeFlag,
00118 int ValFlag,
00119 int MsgFlag,
00120 FILE *fp),
00121 FreeParam(Cmd_T *cmd),
00122 PrintEnum(Cmd_T *cmd,
00123 int TypeFlag,
00124 int ValFlag,
00125 FILE *fp),
00126 PrintFlag(Cmd_T *cmd,
00127 int TypeFlag,
00128 int ValFlag,
00129 FILE *fp),
00130 PrintStrArray(Cmd_T *cmd,
00131 int TypeFlag,
00132 int ValFlag,
00133 FILE *fp),
00134 PrintIntArray(Cmd_T *cmd,
00135 int TypeFlag,
00136 int ValFlag,
00137 FILE *fp),
00138 PrintDblArray(Cmd_T *cmd,
00139 int TypeFlag,
00140 int ValFlag,
00141 FILE *fp),
00142 BuildCmdList(Cmd_T **cmdp,
00143 int *cmdSz,
00144 char *ParName,
00145 va_list args),
00146 StoreCmdLine(char *s);
00147
00148 static Cmd_T *pgcmds = 0;
00149 static int pgcmdN = 0;
00150 static int pgcmdSz = 0;
00151 static char *SepString = " \t\r\n";
00152 static char *ProgName = 0;
00153 static char **CmdLines = 0;
00154 static int CmdLinesSz = 0,
00155 CmdLinesL = 0;
00156
00157 int
00158 DeclareParams(char *ParName,
00159 ...)
00160 {
00161 va_list args;
00162
00163 va_start(args, ParName);
00164 pgcmdN = BuildCmdList(&pgcmds, &pgcmdSz, ParName, args);
00165 va_end(args);
00166 return 0;
00167 }
00168
00169 int
00170 GetParams(int *n,
00171 char ***a,
00172 char *DefCmd)
00173 {
00174 char *Line;
00175 int i,
00176 argc = *n;
00177 char **argv = *a,
00178 *s,
00179 *p,
00180 *CmdFile,
00181 *defCmd;
00182 FILE *fp;
00183 int IsPipe;
00184
00185 #if defined(MSDOS)||defined(_WIN32)
00186 char *dot = 0;
00187 #endif
00188 extern char **environ;
00189
00190 if(!(Line=malloc(LINSIZ))) {
00191 fprintf(stderr, "GetParams(): Unable to alloc %d bytes\n",
00192 LINSIZ);
00193 exit(1);
00194 }
00195 for(ProgName=*argv+strlen(*argv);
00196 ProgName-->*argv && *ProgName!='/' && *ProgName!='\\';);
00197 ++ProgName;
00198 #if defined(MSDOS)||defined(_WIN32)
00199 if((dot=strchr(ProgName, '.'))) *dot=0;
00200 #endif
00201 --argc;
00202 ++argv;
00203 for(i=0; environ[i]; i++) {
00204 if(strncmp(environ[i], "cmd_", 4)) continue;
00205 strcpy(Line, environ[i]+4);
00206 if(!(p=strchr(Line, '='))) continue;
00207 *p=' ';
00208 StoreCmdLine(Line);
00209 if(Scan(ProgName, pgcmds, Line)) CmdError(environ[i]);
00210 }
00211 if((defCmd=DefCmd?(DefCmd=strdup(DefCmd)):0)) {
00212 defCmd += strspn(defCmd, "\n\r");
00213 }
00214 for(;;) {
00215 CmdFile=0;
00216 if(argc && argv[0][0]=='-' && argv[0][1]=='=') {
00217 CmdFile = argv[0]+2;
00218 ++argv;
00219 --argc;
00220 defCmd = 0;
00221 }
00222 if(!CmdFile) {
00223 int i;
00224 char ch;
00225
00226 if(!defCmd||!(i=strcspn(defCmd, "\n\r"))) break;
00227 ch = defCmd[i];
00228 defCmd[i] = 0;
00229 CmdFile = defCmd;
00230 defCmd += i+!!ch;
00231 defCmd += strspn(defCmd, "\n\r");
00232 }
00233
00234 IsPipe = !strncmp(CmdFile, "@@", 2);
00235 fp = IsPipe
00236 ? popen(CmdFile+2, "r")
00237 : strcmp(CmdFile, "-")
00238 ? fopen(CmdFile, "r")
00239 : stdin;
00240
00241
00242 if(!fp) {
00243 if(defCmd) continue;
00244 fprintf(stderr, "Unable to open command file %s\n",
00245 CmdFile);
00246 exit(1);
00247 }
00248 while(GetLine(fp, LINSIZ, Line) && strcmp(Line, "\\End")) {
00249 StoreCmdLine(Line);
00250 if(Scan(ProgName, pgcmds, Line)) CmdError(Line);
00251 }
00252
00253 if(fp!=stdin) {
00254 if(IsPipe)
00255 pclose(fp);
00256 else
00257 fclose(fp);
00258 }
00259 CmdFile = NULL;
00260 }
00261 if(DefCmd) free(DefCmd);
00262
00263
00264 while(argc){
00265 if (**argv=='-'){
00266 s=strchr(*argv, '=');
00267
00268
00269 int dash_number=1;
00270 if (*(*argv+1) == '-') dash_number++;
00271 if (s){
00272 *s = ' ';
00273 if((p=strchr(*argv+dash_number, '.'))&&p<s) {
00274 strcpy(Line, *argv+dash_number);
00275 } else {
00276 sprintf(Line, "%s/%s", ProgName, *argv+dash_number);
00277 }
00278 *s = '=';
00279 }else{
00280 sprintf(Line, "%s/%s", ProgName, *argv+dash_number);
00281 }
00282
00283 StoreCmdLine(Line);
00284 if(Scan(ProgName, pgcmds, Line)) CmdError(*argv);
00285 --argc;
00286 ++argv;
00287 }else{
00288 --argc;
00289 ++argv;
00290 }
00291 }
00292 *n = argc;
00293 *a = argv;
00294
00295 #if defined(MSDOS)||defined(_WIN32)
00296 if(dot) *dot = '.';
00297 #endif
00298 free(Line);
00299 return 0;
00300 }
00301
00302 int
00303 GetDotParams(char *ParName,
00304 ...)
00305 {
00306 va_list args;
00307 int j,
00308 cmdN,
00309 cmdSz = 0;
00310 Cmd_T *cmds = 0;
00311
00312 va_start(args, ParName);
00313 cmdN = BuildCmdList(&cmds, &cmdSz, ParName, args);
00314 va_end(args);
00315 for(j=0; j<CmdLinesL; j++) Scan(ProgName, cmds, CmdLines[j]);
00316 for(j=0; j<cmdN; j++) FreeParam(cmds+j);
00317 if(cmds) free(cmds);
00318 return 0;
00319 }
00320
00321 int
00322 GetStrParams(char **lines,
00323 int n,
00324 char *parName,
00325 ...)
00326 {
00327 va_list args;
00328 int j,
00329 cmdN,
00330 cmdSz = 0;
00331 Cmd_T *cmds = 0;
00332
00333 va_start(args, parName);
00334 cmdN = BuildCmdList(&cmds, &cmdSz, parName, args);
00335 va_end(args);
00336 for(j=0; j<n; j++) Scan((char*)0, cmds, lines[j]);
00337 for(j=0; j<cmdN; j++) FreeParam(cmds+j);
00338 if(cmds) free(cmds);
00339 return 0;
00340 }
00341
00342 int
00343 PrintParams(int ValFlag,
00344 FILE *fp)
00345 {
00346 int TypeFlag=0;
00347 int MsgFlag=1;
00348 return PrintParams4(TypeFlag, ValFlag, MsgFlag, fp);
00349 }
00350
00351 int
00352 FullPrintParams(int TypeFlag,
00353 int ValFlag,
00354 int MsgFlag,
00355 FILE *fp)
00356 {
00357 return PrintParams4(TypeFlag, ValFlag, MsgFlag, fp);
00358 }
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368 static int
00369 PrintParams4(int TypeFlag,
00370 int ValFlag,
00371 int MsgFlag,
00372 FILE *fp)
00373 {
00374 int i;
00375
00376 fflush(fp);
00377 if(ValFlag) {
00378 fprintf(fp, "Parameters Values:\n");
00379 } else {
00380 fprintf(fp, "Parameters:\n");
00381 }
00382 for(i=0; pgcmds[i].Name; i++) {
00383 PrintParam(pgcmds+i, TypeFlag, ValFlag, fp);
00384 if(MsgFlag&&pgcmds[i].Msg) {
00385 char *s=pgcmds[i].Msg,
00386 *p;
00387 for(;(p=strchr(s, '\n')); s=++p) {
00388 fprintf(fp, "%6s%*.*s\n", "", (int)(p-s), (int)(p-s), s);
00389 }
00390 if(s) fprintf(fp, "%6s%s", "", s);
00391 }
00392 fprintf(fp, "\n");
00393 }
00394 fprintf(fp, "\n");
00395 fflush(fp);
00396 return 0;
00397 }
00398
00399 int
00400 SPrintParams(char ***a,
00401 char *pfx)
00402 {
00403 int l,
00404 n;
00405 Cmd_T *cmd;
00406
00407 if(!pfx) pfx="";
00408 l = strlen(pfx);
00409 for(n=0, cmd=pgcmds; cmd->Name; cmd++) n += !!cmd->ArgStr;
00410 a[0] = calloc(n, sizeof(char*));
00411 for(n=0, cmd=pgcmds; cmd->Name; cmd++) {
00412 if(!cmd->ArgStr) continue;
00413 a[0][n] = malloc(strlen(cmd->Name)+strlen(cmd->ArgStr)+l+2);
00414 sprintf(a[0][n], "%s%s=%s", pfx, cmd->Name, cmd->ArgStr);
00415 ++n;
00416 }
00417 return n;
00418 }
00419
00420 static int
00421 BuildCmdList(Cmd_T **cmdp,
00422 int *cmdSz,
00423 char *ParName,
00424 va_list args)
00425 {
00426 int j,
00427 c,
00428 cmdN=0;
00429 char *s;
00430 Cmd_T *cmd,
00431 *cmds;
00432
00433 if(!*cmdSz) {
00434 if(!(cmds=*cmdp=malloc((1+(*cmdSz=BUFSIZ))*sizeof(Cmd_T)))) {
00435 fprintf(stderr, "BuildCmdList(): malloc() failed\n");
00436 exit(-1);
00437 }
00438 } else {
00439 for(cmds=*cmdp; cmds[cmdN].Name; ++cmdN);
00440 }
00441 while(ParName) {
00442 if(cmdN==*cmdSz) {
00443 cmds=*cmdp=realloc(cmds,
00444 (1+(*cmdSz+=BUFSIZ))*sizeof(Cmd_T));
00445 if(!cmds) {
00446 fprintf(stderr,
00447 "BuildCmdList(): realloc() failed\n");
00448 exit(-1);
00449 }
00450 }
00451 for(j=0; j<cmdN&&strcmp(cmds[j].Name, ParName)<0; j++);
00452 for(c=cmdN; c>j; c--) cmds[c] = cmds[c-1];
00453 cmd = cmds+j;
00454 cmd->Name = ParName;
00455 cmd->Type = va_arg(args, int);
00456 cmd->Val = va_arg(args, void*);
00457 cmd->Msg = 0;
00458 cmd->Flag = 0;
00459 switch(cmd->Type&~CMDMSG) {
00460 case CMDENUMTYPE:
00461 case CMDFLAGTYPE:
00462 cmd->p = va_arg(args, void*);
00463 break;
00464 case CMDSUBRANGETYPE:
00465 cmd->p = (void*)calloc(2, sizeof(int));
00466 ((int*)cmd->p)[0] = va_arg(args, int);
00467 ((int*)cmd->p)[1] = va_arg(args, int);
00468 break;
00469 case CMDGTETYPE:
00470 case CMDLTETYPE:
00471 cmd->p = (void*)calloc(1, sizeof(int));
00472 ((int*)cmd->p)[0] = va_arg(args, int);
00473 break;
00474 case CMDSTRARRAYTYPE:
00475 cmd->p = (s=va_arg(args, char*)) ? (void*)strdup(s) : 0;
00476 break;
00477 case CMDDBLARRAYTYPE:
00478 case CMDINTARRAYTYPE:
00479 cmd->p = (void*)calloc(2, sizeof(void*));
00480 s = va_arg(args, char*);
00481 ((char**)cmd->p)[0] = s ? strdup(s) : 0;
00482 ((int**)cmd->p)[1] = va_arg(args, int*);
00483 *((int**)cmd->p)[1] = 0;
00484 break;
00485 case CMDBOOLTYPE:
00486 cmd->Type = CMDENUMTYPE|(cmd->Type&CMDMSG);
00487 cmd->p = BoolEnum;
00488 cmd->Flag = 1;
00489 break;
00490 case CMDDOUBLETYPE:
00491 case CMDFLOATTYPE:
00492 case CMDINTTYPE:
00493 case CMDSTRINGTYPE:
00494 break;
00495 default:
00496 fprintf(stderr, "%s: %s %d %s \"%s\"\n",
00497 "BuildCmdList()", "Unknown Type",
00498 cmd->Type&~CMDMSG, "for parameter", cmd->Name);
00499 exit(1);
00500 }
00501 if(cmd->Type&CMDMSG) {
00502 cmd->Type&=~CMDMSG;
00503 cmd->Msg = va_arg(args, char*);
00504 }
00505 cmdN++;
00506 ParName = va_arg(args, char*);
00507 }
00508 cmds[cmdN].Name = 0;
00509 return cmdN;
00510 }
00511
00512 static int
00513 CmdError(char *opt)
00514 {
00515 fprintf(stderr, "Invalid option \"%s\"\n", opt);
00516 fprintf(stderr, "This program expects the following parameters:\n");
00517 PrintParams4(TRUE, FALSE, TRUE, stderr);
00518 exit(0);
00519 return 0;
00520 }
00521
00522 static int
00523 FreeParam(Cmd_T *cmd)
00524 {
00525 switch(cmd->Type) {
00526 case CMDSUBRANGETYPE:
00527 case CMDGTETYPE:
00528 case CMDLTETYPE:
00529 case CMDSTRARRAYTYPE:
00530 if(cmd->p) free(cmd->p);
00531 break;
00532 case CMDINTARRAYTYPE:
00533 case CMDDBLARRAYTYPE:
00534 if(!cmd->p) break;
00535 if(*(char**)cmd->p) free(*(char**)cmd->p);
00536 free(cmd->p);
00537 break;
00538 }
00539 return 0;
00540 }
00541
00542 static int
00543 PrintParam(Cmd_T *cmd,
00544 int TypeFlag,
00545 int ValFlag,
00546 FILE *fp)
00547 {
00548 char ts[128];
00549
00550 *ts=0;
00551 fprintf(fp, "%4s", "");
00552 switch(cmd->Type) {
00553 case CMDDOUBLETYPE:
00554 fprintf(fp, "%s", cmd->Name);
00555 if(TypeFlag) fprintf(fp, " [double]");
00556 if(ValFlag) fprintf(fp, ": %22.15e", *(double*)cmd->Val);
00557 break;
00558 case CMDFLOATTYPE:
00559 fprintf(fp, "%s", cmd->Name);
00560 if(TypeFlag) fprintf(fp, " [float]");
00561 if(ValFlag) fprintf(fp, ": %22.15e", *(float *)cmd->Val);
00562 break;
00563 case CMDENUMTYPE:
00564 PrintEnum(cmd, TypeFlag, ValFlag, fp);
00565 break;
00566 case CMDFLAGTYPE:
00567 PrintFlag(cmd, TypeFlag, ValFlag, fp);
00568 break;
00569 case CMDINTTYPE:
00570 if(TypeFlag) sprintf(ts, " [int]");
00571 case CMDSUBRANGETYPE:
00572 if(TypeFlag&&!*ts) sprintf(ts, " [int %d ... %d]",
00573 ((int*)cmd->p)[0],
00574 ((int*)cmd->p)[1]);
00575 case CMDGTETYPE:
00576 if(TypeFlag&&!*ts) sprintf(ts, " [int >= %d]",
00577 ((int*)cmd->p)[0]);
00578 case CMDLTETYPE:
00579 if(TypeFlag&&!*ts) sprintf(ts, " [int <= %d]",
00580 ((int*)cmd->p)[0]);
00581 fprintf(fp, "%s", cmd->Name);
00582 if(*ts) fprintf(fp, " %s", ts);
00583 if(ValFlag) fprintf(fp, ": %d", *(int*)cmd->Val);
00584 break;
00585 case CMDSTRINGTYPE:
00586 fprintf(fp, "%s", cmd->Name);
00587 if(TypeFlag) fprintf(fp, " [string]");
00588 if(ValFlag) {
00589 if(*(char **)cmd->Val) {
00590 fprintf(fp, ": \"%s\"", *(char**)cmd->Val);
00591 } else {
00592 fprintf(fp, ": %s", "NULL");
00593 }
00594 }
00595 break;
00596 case CMDSTRARRAYTYPE:
00597 PrintStrArray(cmd, TypeFlag, ValFlag, fp);
00598 break;
00599 case CMDINTARRAYTYPE:
00600 PrintIntArray(cmd, TypeFlag, ValFlag, fp);
00601 break;
00602 case CMDDBLARRAYTYPE:
00603 PrintDblArray(cmd, TypeFlag, ValFlag, fp);
00604 break;
00605 default:
00606 fprintf(stderr, "%s: %s %d %s \"%s\"\n",
00607 "PrintParam",
00608 "Unknown Type",
00609 cmd->Type,
00610 "for parameter",
00611 cmd->Name);
00612 exit(1);
00613 }
00614 fprintf(fp, ":");
00615
00616 fflush(fp);
00617 return 0;
00618 }
00619
00620 static char *
00621 GetLine(FILE *fp,
00622 int n,
00623 char *Line)
00624 {
00625 int j,
00626 l,
00627 offs=0;
00628
00629 for(;;) {
00630 if(!fgets(Line+offs, n-offs, fp)) {
00631 return 0;
00632 }
00633 if(Line[offs]=='#') continue;
00634 l = strlen(Line+offs)-1;
00635 Line[offs+l] = 0;
00636 for(j=offs; Line[j]&&isspace((unsigned char)Line[j]); j++,l--);
00637 if(l<1) continue;
00638 if(j > offs) {
00639 char *s = Line+offs,
00640 *q = Line+j;
00641
00642 while((*s++=*q++))
00643 ;
00644 }
00645 if(Line[offs+l-1]=='\\') {
00646 offs += l;
00647 Line[offs-1] = ' ';
00648 } else {
00649 break;
00650 }
00651 }
00652 return Line;
00653 }
00654
00655 static int
00656 Scan(char *ProgName,
00657 Cmd_T *cmds,
00658 char *Line)
00659 {
00660 char *q,
00661 *p;
00662 int i,
00663 hl,
00664 HasToMatch = FALSE,
00665 c0,
00666 c;
00667
00668 p = Line+strspn(Line, SepString);
00669 if(!(hl=strcspn(p, SepString))) return 0;
00670 if(ProgName&&(q=strchr(p, '/')) && q-p<hl) {
00671 *q = 0;
00672 if(strcmp(p, ProgName)) {
00673 *q = '/';
00674 return 0;
00675 }
00676 *q = '/';
00677 HasToMatch=TRUE;
00678 p = q+1;
00679 }
00680 if(!(hl=strcspn(p, SepString))) return 0;
00681 c0 = p[hl];
00682 p[hl] = 0;
00683 for(i=0, c=1; cmds[i].Name&&(c=strcmp(cmds[i].Name, p))<0; i++)
00684 ;
00685 p[hl] = c0;
00686 if(!c) return SetParam(cmds+i, p+hl+strspn(p+hl, SepString));
00687 return HasToMatch && c;
00688 }
00689
00690 static int
00691 SetParam(Cmd_T *cmd,
00692 char *_s)
00693 {
00694 char *s;
00695
00696 if(!*_s && cmd->Type==CMDENUMTYPE && cmd->Flag==1){
00697 s=(char*) malloc(5);
00698 strcpy(s,"TRUE");
00699 }else{
00700 s=_s;
00701 }
00702
00703 if (!*s || (s=='\0' && cmd->Flag==0)){
00704 fprintf(stderr,
00705 "WARNING: No value specified for parameter \"%s\"\n",
00706 cmd->Name);
00707 return 0;
00708 }
00709
00710 switch(cmd->Type) {
00711 case CMDDOUBLETYPE:
00712 if(sscanf(s, "%lf", (double*)cmd->Val)!=1) {
00713 fprintf(stderr,
00714 "Float value required for parameter \"%s\"\n",
00715 cmd->Name);
00716 exit(1);
00717 }
00718 break;
00719 case CMDFLOATTYPE:
00720 if(sscanf(s, "%f", (float*)cmd->Val)!=1) {
00721 fprintf(stderr,
00722 "Float value required for parameter \"%s\"\n",
00723 cmd->Name);
00724 exit(1);
00725 }
00726 break;
00727 case CMDENUMTYPE:
00728 SetEnum(cmd, s);
00729 break;
00730 case CMDFLAGTYPE:
00731 SetFlag(cmd, s);
00732 break;
00733 case CMDINTTYPE:
00734 if(sscanf(s, "%i", (int*)cmd->Val)!=1) {
00735 fprintf(stderr,
00736 "Integer value required for parameter \"%s\"\n",
00737 cmd->Name);
00738 exit(1);
00739 }
00740 break;
00741 case CMDSTRINGTYPE:
00742 *(char **)cmd->Val = (strcmp(s, "<NULL>") && strcmp(s, "NULL"))
00743 ? strdup(s)
00744 : 0;
00745 break;
00746 case CMDSTRARRAYTYPE:
00747 SetStrArray(cmd, s);
00748 break;
00749 case CMDINTARRAYTYPE:
00750 case CMDDBLARRAYTYPE:
00751 SetNumArray(cmd, s);
00752 break;
00753 case CMDGTETYPE:
00754 SetGte(cmd, s);
00755 break;
00756 case CMDLTETYPE:
00757 SetLte(cmd, s);
00758 break;
00759 case CMDSUBRANGETYPE:
00760 SetSubrange(cmd, s);
00761 break;
00762 default:
00763 fprintf(stderr, "%s: %s %d %s \"%s\"\n",
00764 "SetParam",
00765 "Unknown Type",
00766 cmd->Type,
00767 "for parameter",
00768 cmd->Name);
00769 exit(1);
00770 }
00771 cmd->ArgStr = strdup(s);
00772
00773 if(!*_s && cmd->Type==CMDENUMTYPE && cmd->Flag==1){
00774 free (s);
00775 }
00776
00777 return 0;
00778 }
00779
00780 static int
00781 SetEnum(Cmd_T *cmd,
00782 char *s)
00783 {
00784 Enum_T *en;
00785
00786 for(en=(Enum_T*)cmd->p; en->Name; en++) {
00787 if(*en->Name && !strcmp(s, en->Name)) {
00788 *(int*)cmd->Val = en->Idx;
00789 return 0;
00790 }
00791 }
00792 return EnumError(cmd, s);
00793 }
00794
00795 int
00796 EnumIdx(Enum_T *en,
00797 char *s)
00798 {
00799 if(en) for(; en->Name; en++) {
00800 if(*en->Name && !strcmp(s, en->Name)) return en->Idx;
00801 }
00802 return -1;
00803 }
00804
00805 char *
00806 EnumStr(Enum_T *en,
00807 int i)
00808 {
00809 if(en) for(; en->Name; en++) if(en->Idx==i) return en->Name;
00810 return 0;
00811 }
00812
00813 static int
00814 SetFlag(Cmd_T *cmd,
00815 char *s)
00816 {
00817 Enum_T *en;
00818 int l;
00819
00820 for(; (l=strcspn(s, "+"))>0; s+=l,s+=!!*s) {
00821 for(en=(Enum_T*)cmd->p;
00822 en->Name&&(l!=strlen(en->Name)||strncmp(s, en->Name, l));
00823 en++);
00824 if(!en->Name) return EnumError(cmd, s);
00825 *(int*)cmd->Val |= en->Idx;
00826 }
00827 return 0;
00828 }
00829
00830 static int
00831 SetSubrange(Cmd_T *cmd,
00832 char *s)
00833 {
00834 int n;
00835
00836 if(sscanf(s, "%i", &n)!=1) {
00837 fprintf(stderr,
00838 "Integer value required for parameter \"%s\"\n",
00839 cmd->Name);
00840 exit(1);
00841 }
00842 if(n < *(int*)cmd->p || n > *((int*)cmd->p+1)) {
00843 return SubrangeError(cmd, n);
00844 }
00845 *(int*)cmd->Val = n;
00846 return 0;
00847 }
00848
00849 static int
00850 SetGte(Cmd_T *cmd,
00851 char *s)
00852 {
00853 int n;
00854
00855 if(sscanf(s, "%i", &n)!=1) {
00856 fprintf(stderr,
00857 "Integer value required for parameter \"%s\"\n",
00858 cmd->Name);
00859 exit(1);
00860 }
00861 if(n<*(int*)cmd->p) {
00862 return GteError(cmd, n);
00863 }
00864 *(int*)cmd->Val = n;
00865 return 0;
00866 }
00867
00868 static int
00869 SetStrArray(Cmd_T *cmd,
00870 char *s)
00871 {
00872 *(char***)cmd->Val = str2array(s, (char*)cmd->p);
00873 return 0;
00874 }
00875
00876 static int
00877 SetNumArray(Cmd_T *cmd,
00878 char *s)
00879 {
00880 *((int**)cmd->p)[1] = str2narray(cmd->Type, s,
00881 *((char**)cmd->p), cmd->Val);
00882 return 0;
00883 }
00884
00885 static int
00886 SetLte(Cmd_T *cmd,
00887 char *s)
00888 {
00889 int n;
00890
00891 if(sscanf(s, "%i", &n)!=1) {
00892 fprintf(stderr,
00893 "Integer value required for parameter \"%s\"\n",
00894 cmd->Name);
00895 exit(1);
00896 }
00897 if(n > *(int*)cmd->p) {
00898 return LteError(cmd, n);
00899 }
00900 *(int*)cmd->Val = n;
00901 return 0;
00902 }
00903
00904 static int
00905 EnumError(Cmd_T *cmd,
00906 char *s)
00907 {
00908 Enum_T *en;
00909
00910 fprintf(stderr,
00911 "Invalid value \"%s\" for parameter \"%s\"\n", s, cmd->Name);
00912 fprintf(stderr, "Valid values are:\n");
00913 for(en=(Enum_T*)cmd->p; en->Name; en++) {
00914 if(*en->Name) fprintf(stderr, " %s\n", en->Name);
00915 }
00916 fprintf(stderr, "\n");
00917 exit(1);
00918 return 0;
00919 }
00920
00921 static int
00922 GteError(Cmd_T *cmd,
00923 int n)
00924 {
00925 fprintf(stderr,
00926 "Value %d out of range for parameter \"%s\"\n", n, cmd->Name);
00927 fprintf(stderr, "Valid values must be greater than or equal to %d\n",
00928 *(int*)cmd->p);
00929 exit(1);
00930 return 0;
00931 }
00932
00933 static int
00934 LteError(Cmd_T *cmd,
00935 int n)
00936 {
00937 fprintf(stderr,
00938 "Value %d out of range for parameter \"%s\"\n", n, cmd->Name);
00939 fprintf(stderr, "Valid values must be less than or equal to %d\n",
00940 *(int*)cmd->p);
00941 exit(1);
00942 return 0;
00943 }
00944
00945 static int
00946 SubrangeError(Cmd_T *cmd,
00947 int n)
00948 {
00949 fprintf(stderr,
00950 "Value %d out of range for parameter \"%s\"\n", n, cmd->Name);
00951 fprintf(stderr, "Valid values range from %d to %d\n",
00952 *(int*)cmd->p, *((int*)cmd->p+1));
00953 exit(1);
00954 return 0;
00955 }
00956
00957 static int
00958 PrintEnum(Cmd_T *cmd,
00959 int TypeFlag,
00960 int ValFlag,
00961 FILE *fp)
00962 {
00963 Enum_T *en;
00964 char *sep="";
00965
00966 fprintf(fp, "%s", cmd->Name);
00967 if(TypeFlag) {
00968 fprintf(fp, " [enum { ");
00969 for(en=(Enum_T*)cmd->p; en->Name; en++) {
00970 if(*en->Name) {
00971 fprintf(fp, "%s%s", sep, en->Name);
00972 sep=", ";
00973 }
00974 }
00975 fprintf(fp, " }]");
00976 }
00977 if(ValFlag) {
00978 for(en=(Enum_T*)cmd->p; en->Name; en++) {
00979 if(*en->Name && en->Idx==*(int*)cmd->Val) {
00980 fprintf(fp, ": %s", en->Name);
00981 }
00982 }
00983 }
00984
00985 return 0;
00986 }
00987
00988 static int
00989 PrintFlag(Cmd_T *cmd,
00990 int TypeFlag,
00991 int ValFlag,
00992 FILE *fp)
00993 {
00994 Enum_T *en;
00995 char *sep="";
00996
00997 fprintf(fp, "%s", cmd->Name);
00998 if(TypeFlag) {
00999 fprintf(fp, ": flag { ");
01000 for(en=(Enum_T*)cmd->p; en->Name; en++) {
01001 if(*en->Name) {
01002 fprintf(fp, "%s%s", sep, en->Name);
01003 sep=", ";
01004 }
01005 }
01006 fprintf(fp, " }");
01007 }
01008 if(ValFlag) {
01009 fprintf(fp, ": ");
01010 for(en=(Enum_T*)cmd->p; en->Name; en++) {
01011 if(*en->Name && (en->Idx&*(int*)cmd->Val)==en->Idx) {
01012 fprintf(fp, "%s%s", sep, en->Name);
01013 sep="+";
01014 }
01015 }
01016 }
01017 fprintf(fp, "\n");
01018 return 0;
01019 }
01020
01021 static int
01022 PrintStrArray(Cmd_T *cmd,
01023 int TypeFlag,
01024 int ValFlag,
01025 FILE *fp)
01026 {
01027 char *indent,
01028 **s = *(char***)cmd->Val;
01029 int l = 4+strlen(cmd->Name);
01030
01031 fprintf(fp, "%s", cmd->Name);
01032 if(TypeFlag) {
01033 fprintf(fp, ": string array, separator \"%s\"",
01034 cmd->p?(char*)cmd->p:"");
01035 }
01036 indent = malloc(l+2);
01037 memset(indent, ' ', l+1);
01038 indent[l+1] = 0;
01039 if(ValFlag) {
01040 fprintf(fp, ": %s", s ? (*s ? *s++ : "NULL") : "");
01041 if(s) while(*s) {
01042 fprintf(fp, "\n%s %s", indent, *s++);
01043 }
01044 }
01045 free(indent);
01046 fprintf(fp, "\n");
01047 return 0;
01048 }
01049
01050 static int
01051 PrintIntArray(Cmd_T *cmd,
01052 int TypeFlag,
01053 int ValFlag,
01054 FILE *fp)
01055 {
01056 char *indent;
01057 int l = 4+strlen(cmd->Name),
01058 n,
01059 *i = *(int**)cmd->Val;
01060
01061 fprintf(fp, "%s", cmd->Name);
01062 if(TypeFlag) {
01063 fprintf(fp, ": int array, separator \"%s\"",
01064 *(char**)cmd->p?*(char**)cmd->p:"");
01065 }
01066 n = *((int**)cmd->p)[1];
01067 indent = malloc(l+2);
01068 memset(indent, ' ', l+1);
01069 indent[l+1] = 0;
01070 if(ValFlag) {
01071 fprintf(fp, ":");
01072 if(i&&n>0) {
01073 fprintf(fp, " %d", *i++);
01074 while(--n) fprintf(fp, "\n%s %d", indent, *i++);
01075 }
01076 }
01077 free(indent);
01078 fprintf(fp, "\n");
01079 return 0;
01080 }
01081
01082 static int
01083 PrintDblArray(Cmd_T *cmd,
01084 int TypeFlag,
01085 int ValFlag,
01086 FILE *fp)
01087 {
01088 char *indent;
01089 int l = 4+strlen(cmd->Name),
01090 n;
01091 double *x = *(double**)cmd->Val;
01092
01093 fprintf(fp, "%s", cmd->Name);
01094 if(TypeFlag) {
01095 fprintf(fp, ": double array, separator \"%s\"",
01096 *(char**)cmd->p?*(char**)cmd->p:"");
01097 }
01098 n = *((int**)cmd->p)[1];
01099 indent = malloc(l+2);
01100 memset(indent, ' ', l+1);
01101 indent[l+1] = 0;
01102 if(ValFlag) {
01103 fprintf(fp, ":");
01104 if(x&&n>0) {
01105 fprintf(fp, " %e", *x++);
01106 while(--n) fprintf(fp, "\n%s %e", indent, *x++);
01107 }
01108 }
01109 free(indent);
01110 fprintf(fp, "\n");
01111 return 0;
01112 }
01113
01114 static char **
01115 str2array(char *s,
01116 char *sep)
01117 {
01118 char *p,
01119 **a;
01120 int n = 0,
01121 l;
01122
01123 if(!sep) sep = SepString;
01124 p = s += strspn(s, sep);
01125 if(!*p) return 0;
01126 while(*p) {
01127 p += strcspn(p, sep);
01128 p += strspn(p, sep);
01129 ++n;
01130 }
01131 a = calloc(n+1, sizeof(char*));
01132 p = s;
01133 n = 0;
01134 while(*p) {
01135 l = strcspn(p, sep);
01136 a[n] = malloc(l+1);
01137 memcpy(a[n], p, l);
01138 a[n][l] = 0;
01139 ++n;
01140 p += l;
01141 p += strspn(p, sep);
01142 }
01143 return a;
01144 }
01145
01146 int
01147 str2narray(int type,
01148 char *s,
01149 char *sep,
01150 void **a)
01151 {
01152 char *p;
01153 double *x;
01154 int *i;
01155 int n = 0;
01156
01157 if(!sep) sep=SepString;
01158 for(p=s; *p; ) {
01159 p += strcspn(p, sep);
01160 p += !!*p;
01161 ++n;
01162 }
01163 *a = 0;
01164 if(!n) return 0;
01165 *a = calloc(n, (type==CMDINTARRAYTYPE)?sizeof(int):sizeof(double));
01166 i = (int*)*a;
01167 x = (double*)*a;
01168 p = s;
01169 n = 0;
01170 while(*p) {
01171 switch(type) {
01172 case CMDINTARRAYTYPE:
01173 *i++ = atoi(p);
01174 break;
01175 case CMDDBLARRAYTYPE:
01176 *x++ = atof(p);
01177 break;
01178 }
01179 ++n;
01180 p += strcspn(p, sep);
01181 p += !!*p;
01182 }
01183 return n;
01184 }
01185
01186 static int
01187 StoreCmdLine(char *s)
01188 {
01189 s += strspn(s, SepString);
01190 if(!*s) return 0;
01191 if(CmdLinesL>=CmdLinesSz) {
01192 CmdLines=CmdLinesSz
01193 ? (char**)realloc(CmdLines,
01194 (CmdLinesSz+=BUFSIZ)*sizeof(char**))
01195 : (char**)malloc((CmdLinesSz=BUFSIZ)*sizeof(char**));
01196 if(!CmdLines) {
01197 fprintf(stderr, "%s\n",
01198 "StoreCmdLine(): malloc() failed");
01199 exit(-1);
01200 }
01201 }
01202 CmdLines[CmdLinesL++] = strdup(s);
01203 return 0;
01204 }