00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "program.h"
00017 #include <string.h>
00018 #include <stdlib.h>
00019
00020 #define PROGRAM_VERSION "Program:: Version 0.2 5-jun-97 PJT"
00021
00022 #define MINMATCH
00023
00024
00025
00026
00027
00028
00029 static int xstrlen(void *xspt,int nbyt);
00030 static string parname(string arg);
00031 static string parvalue(string arg);
00032 static string parhelp(string arg);
00033
00034 Program *Program::self = 0;
00035
00036
00037 Program::Program() {
00038 package = 0;
00039 progname = 0;
00040 }
00041
00042 Program::Program(string p) {
00043 package = p;
00044 progname = 0;
00045 }
00046
00047 Program::~Program() {
00048 if (debug_level>9) {
00049 cerr << "[DEBUG " << debug_level << "] dtor " << progname << endl;
00050 }
00051 }
00052
00053
00054 void Program::init(int argc, string *argv) {
00055 char *sp = strrchr(argv[0],'/');
00056 if (sp == 0)
00057 progname = argv[0];
00058 else
00059 progname = sp+1;
00060
00061 Program::argc = argc;
00062 Program::argv = argv;
00063 self = this;
00064
00065 debug_level = 0;
00066 error_level = 0;
00067 help_level = 0;
00068
00069 nkeys = xstrlen(keywords, sizeof(string));
00070 keys = new keyword[nkeys];
00071 addkey(0," argv0=\n Program name",1);
00072 keys[0].val = progname;
00073 for (int i=1; i<nkeys; i++)
00074 addkey(i,keywords[i-1],0);
00075 }
00076
00077 void Program::append(string skeyvalhelp) {
00078 Warning("Program::append - not implemented yet");
00079 }
00080
00081 void Program::parse(void) {
00082 #if 0
00083 int posflag = FALSE;
00084 #else
00085 int posflag = TRUE;
00086 #endif
00087 string name;
00088
00089 for (int i=1; argv[i] ; i++) {
00090 if (debug_level > 0)
00091 cout << "Parsing " << argv[i] << endl;
00092 name = parname(argv[i]);
00093 posflag = posflag && (name == 0);
00094 if (posflag) {
00095 if (i >= nkeys) Error("Too many un-named arguments");
00096
00097 keys[i].val = strdup(argv[i]);
00098 keys[i].count++;
00099 } else {
00100 if (name == 0) {
00101 cerr << "Parameter " << name << "must be named" << endl;
00102 exit(1);
00103 }
00104 int j = findkey(name);
00105 if (j >= 0) {
00106 if(keys[j].count)
00107 Error("Parameter duplicated");
00108
00109 keys[j].val = strdup(parvalue(argv[i]));
00110 keys[j].count++;
00111 } else {
00112 if (strcmp(name,"help")==0)
00113 cout << "SET_HELP" << endl;
00114 else if (strcmp(name,"debug")==0)
00115 set_debug(parvalue(argv[i]));
00116 else if (strcmp(name,"error")==0)
00117 set_error(parvalue(argv[i]));
00118 else
00119 Error("Parameter %s unknown",name);
00120 }
00121 }
00122 }
00123 }
00124
00125 void Program::fini(void) {
00126 int i, n=0;
00127
00128 for (i=1; i<nkeys; i++)
00129 n += keys[i].upd ? 1 : 0;
00130 if (n && debug_level > 0) {
00131 Warning("The following keywords have never been read:");
00132 for (i=1; i<nkeys; i++)
00133 if (keys[i].upd) cerr << " " << keys[i].key;
00134 cerr << endl;
00135 }
00136 }
00137
00138 int Program::go(void) {
00139
00140 if (argc > 1) {
00141 if (strcmp(argv[1],"--help") == 0) {
00142 cerr << PROGRAM_VERSION << endl;
00143 cerr << "Current system options:" << endl;
00144 cerr << " --help this help" << endl;
00145 cerr << " --keywords show program keys, values and help" << endl;
00146 cerr << " --version show program version" << endl;
00147 cerr << " --usage show program usage line" << endl;
00148 cerr << " --description show program description" << endl;
00149 cerr << " --examples show program examples" << endl;
00150 cerr << " --show show some debugging info" << endl;
00151 if (argc==2) return 0;
00152 }
00153 if (strcmp(argv[1],"--keywords") == 0) {
00154 for (int i=1; i<nkeys; i++) {
00155 cout << keys[i].key << "=" << keys[i].val << endl;
00156 cout << "\t" << keys[i].help << endl;
00157 }
00158 if (argc==2) return 0;
00159 }
00160 if (strcmp(argv[1],"--version") == 0) {
00161 cout << progname << " : " << version << endl;
00162 if (argc==2) return 0;
00163 return 0;
00164 }
00165 if (strcmp(argv[1],"--usage") == 0) {
00166 cout << usage << endl;
00167 if (argc==2) return 0;
00168 }
00169 if (strcmp(argv[1],"--description") == 0) {
00170 cout << description << endl;
00171 if (argc==2) return 0;
00172 }
00173 if (strcmp(argv[1],"--examples") == 0) {
00174 cout << examples << endl;
00175 if (argc==2) return 0;
00176 }
00177 if (strcmp(argv[1],"--show") == 0) {
00178 show();
00179 if (argc==2) return 0;
00180 }
00181 }
00182
00183
00184
00185
00186 int missing = 0;
00187 for (int i=1; i<nkeys; i++)
00188 if (strcmp(keys[i].val,"???")==0) {
00189 missing++;
00190 break;
00191 }
00192 if (missing) {
00193 cerr << "Insufficient parameters" << endl;
00194 cerr << "Usage: " << progname;
00195 int otherargs = FALSE;
00196 for (int i=1; i<nkeys; i++)
00197 if (strcmp(keys[i].val,"???") == 0)
00198 printf(" %s=???", keys[i].key);
00199 else
00200 otherargs = TRUE;
00201 cerr << (otherargs ? " ...\n" : "\n");
00202 Error("The above required keywords have no value");
00203 }
00204 return 1;
00205 }
00206
00207 void Program::show(void) {
00208 string *sp;
00209 int i;
00210 cout << "Program: " << progname << endl;
00211 cout << "Usage: " << usage << endl;
00212 cout << "Description: " << endl << description << endl;
00213 cout << "Version: " << version << endl;
00214 cout << "Examples: " << examples << endl;
00215 for (i=0, sp=keywords; *sp; i++, sp++)
00216 cout << "key(" << i+1 << ") = " << *sp << endl;
00217 for (i=1; i<argc; i++)
00218 cout << "arg(" << i << ") = " << argv[i] << endl;
00219 for (i=1; i<nkeys; i++) {
00220 cout << "key(" << i << ") = " << keys[i].key << endl;
00221 cout << "def(" << i << ") = " << keys[i].val << endl;
00222 cout << "help(" << i << ") = " << keys[i].help << endl;
00223 }
00224 cout << "debug_level: " << debug_level << endl;
00225 cout << "error_level: " << error_level << endl;
00226
00227 }
00228
00229 Program *Program::main(void) {
00230 return self;
00231 }
00232
00233 int Program::get_argc(void) {
00234 return argc;
00235 }
00236
00237 char **Program::get_argv(void) {
00238 return argv;
00239 }
00240
00241
00242
00243
00244
00245
00246
00247 void Program::help(void) {
00248
00249 }
00250
00251 void Program::addkey(int i, string skeyvalhelp, int system=0)
00252 {
00253 int j;
00254 if (i >= nkeys) Error("addkey internal error");
00255
00256 keys[i].keyval = skeyvalhelp;
00257 keys[i].option = *skeyvalhelp;
00258 keys[i].key = strdup(parname(skeyvalhelp));
00259 keys[i].val = strdup(parvalue(skeyvalhelp));
00260 keys[i].help = strdup(parhelp(skeyvalhelp));
00261 keys[i].count = 0;
00262 keys[i].upd = 1;
00263 keys[i].system = system;
00264
00265
00266
00267 for (j=0; j<i; j++) {
00268 if (keys[j].option == ' ') continue;
00269 if (keys[j].option == keys[i].option)
00270 Warning("Option %c duplicated (%s,%s)",
00271 keys[i].option, keys[i].key, keys[j].key);
00272 }
00273
00274 }
00275
00276
00277 string Program::get(string key) {
00278 int i = findkey(key);
00279 if (i<0) Error("%s: Unknown keyword",key);
00280 keys[i].upd = 0;
00281 return keys[i].val;
00282 }
00283
00284 int Program::count(string key) {
00285 int i = findkey(key);
00286 if (i<0) Error("Illegal key");
00287 return keys[i].count;
00288 }
00289
00290 int Program::get_debug(void) {
00291 return debug_level;
00292 }
00293
00294 void Program::set_debug(string debug_value) {
00295 debug_level = atoi(debug_value);
00296 cerr << "DEBUG level set to: " << debug_level << endl;
00297 }
00298
00299 void Program::set_error(string error_value) {
00300 error_level = atoi(error_value);
00301 if (error_level < 0) Error("%d: Cannot set error < 0",error_level);
00302 cerr << "ERROR level set to: " << error_level << endl;
00303 }
00304
00305 int Program::dec_error(void) {
00306 if (error_level == 0) return 0;
00307
00308 return error_level--;
00309 }
00310
00311
00312
00313
00314
00315 static int xstrlen(void *xspt, int nbyt)
00316 {
00317 int nval, i;
00318 int lpflg;
00319 char *cp = (char *) xspt;
00320
00321 nval = 0;
00322 do {
00323 nval++;
00324 lpflg = FALSE;
00325 for (i = 0; i < nbyt; i++)
00326 if (*cp++ != 0)
00327 lpflg = TRUE;
00328 } while (lpflg);
00329 return (nval);
00330 }
00331
00332
00333 static string parname(string arg)
00334 {
00335 static char namebuf[64];
00336 char *ap, *np;
00337
00338 ap = (char *) arg;
00339
00340 if (arg[1] == ' ' || arg[1] == ':') {
00341 ap++;
00342 ap++;
00343 }
00344
00345 #if 0
00346
00347 while (*ap == ' ')
00348 ap++;
00349 #endif
00350
00351 np = &namebuf[0];
00352 while ((*np = *ap) != 0) {
00353 #if 0
00354 if (*np == '=' || *np == ' ') {
00355 #else
00356 if (*np == '=') {
00357 #endif
00358 *np = 0;
00359 return ((string) namebuf);
00360 }
00361 np++;
00362 ap++;
00363 }
00364 #if 0
00365 namebuf[0] = 0;
00366 return ((string) namebuf);
00367 #else
00368 return NULL;
00369 #endif
00370 }
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381 static string parvalue(string arg)
00382 {
00383 #if 0
00384 permanent char *valbuf = NULL;
00385 permanent int size = 0;
00386 #else
00387 static char valbuf[256];
00388 #endif
00389
00390 char *ap;
00391
00392 ap = (char *) arg;
00393 while (*ap) {
00394 if (*ap++ == '=') {
00395 while (*ap && *ap == ' ')
00396 ap++;
00397 strncpy(valbuf,ap,255);
00398 valbuf[255] = 0;
00399 ap = valbuf;
00400 while (*ap) {
00401 if (*ap == '\n') {
00402 *ap = 0;
00403 return valbuf;
00404 }
00405 ap++;
00406 }
00407 return valbuf;
00408 }
00409 }
00410 #if 1
00411 return ((string) ap);
00412 #else
00413 return NULL;
00414 #endif
00415 }
00416
00417
00418
00419
00420
00421
00422 static string parhelp(string arg)
00423 {
00424 char *cp = (char *) arg;
00425
00426 while (*cp && *cp != '\n')
00427 cp++;
00428 if(*cp == '\n')
00429 cp++;
00430 while (*cp && (*cp == ' ' || *cp == '\t'))
00431 cp++;
00432 return cp;
00433 }
00434
00435
00436
00437
00438
00439
00440
00441 int Program::findkey(string name)
00442 {
00443 int i, j, l, count, last;
00444
00445
00446
00447 if (nkeys<=0) return -1;
00448 for (i = 0; i < nkeys; i++)
00449 if (strcmp(keys[i].key,name) == 0) return i;
00450
00451 #if defined(MINMATCH)
00452 l = strlen(name);
00453 count = 0;
00454 for (i=1; i<nkeys; i++) {
00455 if (strncmp(keys[i].key, name,l)==0) {
00456 last = i;
00457 count++;
00458 }
00459 }
00460 if (count==1) {
00461 Warning("Resolving partially matched keyword %s= into %s=",
00462 name, keys[last].key);
00463 return last;
00464 } else if (count > 1) {
00465 Dprintf(0,"### Minimum match failed, found: ");
00466 for (j=0; j<nkeys; j++)
00467 if (strncmp(keys[j].key,name,l)==0)
00468 Dprintf(0,"%s ",keys[j].key);
00469 Dprintf(0,"\n");
00470 Error("Ambiguous keyword %s=",name);
00471 }
00472 #endif
00473
00474 return -1;
00475 }
00476