Переглянути джерело

cmPgmOpts.h/c: Many changes and additions

Parameter type flags (cmBoolPoFl, ...) are now private.
Added 'Flag' parameter type.
Added Enum master help string.
Improved built-in help text content and formatting.
cmHexPoFl is now a parameter configuration flag rather than a type.
master
kevin 11 роки тому
джерело
коміт
5bf653dc5e
2 змінених файлів з 289 додано та 98 видалено
  1. 238
    72
      cmPgmOpts.c
  2. 51
    26
      cmPgmOpts.h

+ 238
- 72
cmPgmOpts.c Переглянути файл

@@ -6,8 +6,22 @@
6 6
 #include "cmMallocDebug.h"
7 7
 #include "cmLinkedHeap.h"
8 8
 #include "cmPgmOpts.h"
9
+#include "cmText.h"
9 10
 #include "config.h"
10 11
 
12
+enum { 
13
+  kFlagPoFl  = 0x001,
14
+  kBoolPoFl  = 0x002,  // this parameter does not take a value
15
+  kCharPoFl  = 0x004,  // parm. value is a character
16
+  kIntPoFl   = 0x008,  // parm. value is a decimal int
17
+  kUIntPoFl  = 0x010,  // parm. value is a decimal unsigned int
18
+  kDblPoFl   = 0x040,  // parm. value is a decimal double
19
+  kStrPoFl   = 0x080,  // parm. value is a string (default)
20
+  kEnumPoFl  = 0x100,  // parm. valus is a enum type (automatically set by a non-zero enumId)
21
+
22
+  kTypeMaskPoFl = 0x1ff
23
+};
24
+
11 25
 cmPgmOptH_t cmPgmOptNullHandle = cmSTATIC_NULL_HANDLE;
12 26
 
13 27
 struct _cmPoArg_str;
@@ -39,13 +53,15 @@ typedef struct _cmPoOpt_str
39 53
   unsigned              numId;      // 
40 54
   cmChar_t              charId;     // 
41 55
   cmChar_t*             wordId;     //
42
-  unsigned              flags;      // 
43
-  unsigned              enumId;     //
44
-  struct _cmPoOpt_str*  enumPtr;    // pointer to mast enum recd
56
+  unsigned              sflags;     // state flags (type flags)
57
+  unsigned              cflags;     // cfg flags (user settable cfg flag)
58
+  unsigned              enumId;     // enumerated set element id (numId is the group id)
59
+  struct _cmPoOpt_str*  enumPtr;    // pointer to mast enum recd (the master is the first param. rcvd for a given enum set - so this field is NULL for the master record)
45 60
   unsigned              maxInstCnt; //
46 61
   _cmPoValue_t          dfltVal;    // default value for this parm 
47 62
   _cmPoValPtr_t         retVal;     // client supplied variable which recieves the value of the last arg. parsed for this parm.
48 63
   cmChar_t*             helpStr;    //
64
+  cmChar_t*             mstrStr;
49 65
   struct _cmPoOpt_str*  link;       // link used by the _cmPo_t.list linked list
50 66
   struct _cmPoArg_str*  inst;       // arg's belonging to this opt record formed by _cmPoArg_t.inst links
51 67
 } _cmPoOpt_t;
@@ -73,6 +89,45 @@ typedef struct
73 89
   bool        execFl;       // set to false in cmPgmOptParse() if only built-in options were selected
74 90
 } _cmPo_t;
75 91
 
92
+typedef struct
93
+{
94
+  unsigned        id;
95
+  const cmChar_t* label;
96
+} _cmPoMap_t;
97
+
98
+_cmPoMap_t _cmPoTypeMap[] = 
99
+{
100
+  { kFlagPoFl, "" },
101
+  { kBoolPoFl, "" },
102
+  { kCharPoFl, "<char>" },
103
+  { kIntPoFl,  "<int>" },
104
+  { kUIntPoFl, "<uint>" },
105
+  { kDblPoFl,  "<real>" },
106
+  { kStrPoFl,  "<text>" },
107
+  { kEnumPoFl, "<enum>" },
108
+  { 0,         "<unknown>"}
109
+};
110
+
111
+const cmChar_t* _cmPoTypeFlagToLabel( unsigned flag, unsigned cflags )
112
+{
113
+  if( cmIsFlag(cflags,kHexPoFl) )
114
+    return "<hex>";
115
+
116
+  const _cmPoMap_t* m = _cmPoTypeMap;
117
+  for(; m->id != 0; ++m)
118
+    if( m->id == flag )
119
+      break;
120
+  return m->label;
121
+}
122
+
123
+bool _cmPoOptUsesValue( const _cmPoOpt_t* r )
124
+{ 
125
+  return 
126
+    cmIsNotFlag(r->sflags,kEnumPoFl) && 
127
+    cmIsNotFlag(r->sflags,kBoolPoFl) && 
128
+    cmIsNotFlag(r->sflags,kFlagPoFl);
129
+}
130
+
76 131
 _cmPo_t* _cmPoHandleToPtr( cmPgmOptH_t h )
77 132
 {
78 133
   _cmPo_t* p = (_cmPo_t*)h.h;
@@ -107,10 +162,6 @@ cmPoRC_t cmPgmOptInitialize(cmCtx_t* c, cmPgmOptH_t* hp, const cmChar_t* helpBeg
107 162
 
108 163
   hp->h = p;
109 164
 
110
-  cmPgmOptInstallBool(*hp, kPrintHelpPoId, 'h', "help",    0, false, NULL,0,"Print this usage information." );
111
-  cmPgmOptInstallBool(*hp, kVersionPoId,   'v', "version", 0, false, NULL,0,"Print version information." );
112
-  cmPgmOptInstallBool(*hp, kPrintParmsPoId,'p', "parms",   0, false, NULL,0,"Print the parameter information."); 
113
-
114 165
   return cmErrLastRC(&p->err);
115 166
 }
116 167
 
@@ -138,7 +189,7 @@ _cmPoOpt_t* _cmPgmOptNumIdToOptRecd( _cmPo_t* p, unsigned numId )
138 189
     if( r->numId == numId )
139 190
     {
140 191
 
141
-      if( cmIsFlag(r->flags,kEnumPoFl) && r->enumPtr!=NULL )
192
+      if( cmIsFlag(r->sflags,kEnumPoFl) && r->enumPtr!=NULL )
142 193
         r = r->enumPtr;
143 194
 
144 195
       return r;
@@ -190,10 +241,10 @@ _cmPoOpt_t* _cmPgmOptWordIdToOptRecd( _cmPo_t* p, const cmChar_t* wordId )
190 241
 }
191 242
 
192 243
 
193
-cmPoRC_t _cmPgmOptInstall( _cmPo_t* p, unsigned numId, const cmChar_t charId, const cmChar_t* wordId, unsigned flags, unsigned enumId, unsigned cnt, const cmChar_t* helpStr, _cmPoOpt_t** rpp )
244
+cmPoRC_t _cmPgmOptInstall( _cmPo_t* p, unsigned numId, const cmChar_t charId, const cmChar_t* wordId, unsigned cflags, unsigned sflags, unsigned enumId, unsigned cnt, const cmChar_t* helpStr, _cmPoOpt_t** rpp )
194 245
 {
195 246
   // validate the num. id
196
-  if( enumId==0 && _cmPgmOptNumIdToOptRecd(p,numId) != NULL )
247
+  if( cmIsNotFlag(sflags,kEnumPoFl) && _cmPgmOptNumIdToOptRecd(p,numId) != NULL )
197 248
     return cmErrMsg(&p->err,kDuplicateIdPoRC,"The numeric id '%i' was already used by another parameter.",numId);
198 249
 
199 250
   // validate the char. id
@@ -204,15 +255,18 @@ cmPoRC_t _cmPgmOptInstall( _cmPo_t* p, unsigned numId, const cmChar_t charId, co
204 255
   if( _cmPgmOptWordIdToOptRecd(p,wordId) != NULL )
205 256
     return cmErrMsg(&p->err,kDuplicateIdPoRC,"The word id --'%s' was already used by another parameter.",wordId);
206 257
 
258
+  // clear the kHexPoFl if this is not an int or uint.
259
+  if( cmIsNotFlag(sflags,kFlagPoFl) && cmIsNotFlag(sflags,kIntPoFl) && cmIsNotFlag(sflags,kUIntPoFl) )
260
+    cflags = cmClrFlag(cflags,kHexPoFl);
207 261
 
208 262
   // allocate the new parm recd
209 263
   _cmPoOpt_t* r = cmLhAllocZ( p->lH, _cmPoOpt_t, 1 );
210 264
 
211 265
 
212
-  // if enumId != 0 then this is automatically an enum type.
213
-  if( enumId != 0 )
266
+  // if this is an enum type.
267
+  if( cmIsFlag(sflags,kEnumPoFl) )
214 268
   {
215
-    flags = cmClrFlag(flags,kTypeMaskPoFl) | kEnumPoFl;
269
+    sflags = cmClrFlag(sflags,kTypeMaskPoFl) | kEnumPoFl;
216 270
 
217 271
     // set the master recd for this enum ptr
218 272
     _cmPoOpt_t* erp;
@@ -221,25 +275,37 @@ cmPoRC_t _cmPgmOptInstall( _cmPo_t* p, unsigned numId, const cmChar_t charId, co
221 275
       r->enumPtr = erp->enumPtr==NULL ? erp : erp->enumPtr;  
222 276
 
223 277
       // if this child enum has it's required flags set 
224
-      if( cmIsFlag(flags,kReqPoFl) )
278
+      if( cmIsFlag(cflags,kReqPoFl) )
225 279
       {
226 280
         // then set the required flag in the parent and clear it in the child
227 281
         // (this way both the parent and child will not be required (which would be impossible for an enum))
228
-        r->enumPtr->flags = cmSetFlag(r->enumPtr->flags,kReqPoFl);
229
-        flags = cmClrFlag(flags,kReqPoFl);
282
+        r->enumPtr->cflags = cmSetFlag(r->enumPtr->cflags,kReqPoFl);
283
+        cflags = cmClrFlag(cflags,kReqPoFl);
230 284
       }
231 285
     }
232 286
   }
233 287
 
234
-  r->flags      = flags; 
288
+  r->cflags     = cflags; 
289
+  r->sflags     = sflags;
235 290
   r->numId      = numId;
236 291
   r->charId     = charId;
237 292
   r->wordId     = cmLhAllocStr( p->lH, wordId );
238 293
   r->enumId     = enumId;
239 294
   r->maxInstCnt = cnt;
240 295
   r->helpStr    = helpStr==NULL ? NULL : cmLhAllocStr( p->lH, helpStr );
241
-  r->link       = p->list;
242
-  p->list       = r;
296
+
297
+
298
+  _cmPoOpt_t* rp = p->list;
299
+  while( rp != NULL && rp->link != NULL )
300
+    rp = rp->link;
301
+
302
+  if( rp == NULL )
303
+    p->list = r;
304
+  else
305
+    rp->link = r;
306
+
307
+  //r->link       = p->list;
308
+  //p->list       = r;
243 309
 
244 310
   *rpp = r;
245 311
 
@@ -252,9 +318,7 @@ cmPoRC_t cmPgmOptInstallChar(cmPgmOptH_t h, unsigned numId, cmChar_t charId, con
252 318
   _cmPoOpt_t* r     = NULL;
253 319
   _cmPo_t*    p     = _cmPoHandleToPtr(h);
254 320
 
255
-  flags = cmClrFlag(flags,kTypeMaskPoFl) | kCharPoFl;
256
-
257
-  if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, 0, cnt, helpStr, &r )) != kOkPoRC )
321
+  if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kCharPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
258 322
     return rc;
259 323
 
260 324
   r->dfltVal.c = dfltVal;
@@ -272,9 +336,7 @@ cmPoRC_t cmPgmOptInstallBool(cmPgmOptH_t h, unsigned numId, cmChar_t charId, con
272 336
   _cmPoOpt_t* r     = NULL;
273 337
   _cmPo_t*    p     = _cmPoHandleToPtr(h);
274 338
 
275
-  flags = cmClrFlag(flags,kTypeMaskPoFl) | kBoolPoFl;
276
-
277
-  if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, 0, cnt, helpStr, &r )) != kOkPoRC )
339
+  if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kBoolPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
278 340
     return rc;
279 341
 
280 342
   r->dfltVal.b = dfltVal;
@@ -292,9 +354,7 @@ cmPoRC_t cmPgmOptInstallInt( cmPgmOptH_t h, unsigned numId, cmChar_t charId, con
292 354
   _cmPoOpt_t* r     = NULL;
293 355
   _cmPo_t*    p     = _cmPoHandleToPtr(h);
294 356
 
295
-  flags = cmClrFlag(flags,kTypeMaskPoFl) | kIntPoFl;
296
-
297
-  if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, 0, cnt, helpStr, &r )) != kOkPoRC )
357
+  if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kIntPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
298 358
     return rc;
299 359
 
300 360
   r->dfltVal.i = dfltVal;
@@ -312,9 +372,7 @@ cmPoRC_t cmPgmOptInstallUInt(cmPgmOptH_t h, unsigned numId, cmChar_t charId, con
312 372
   _cmPoOpt_t* r     = NULL;
313 373
   _cmPo_t*    p     = _cmPoHandleToPtr(h);
314 374
 
315
-  flags = cmClrFlag(flags,kTypeMaskPoFl) | kUIntPoFl;
316
-
317
-  if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, 0, cnt, helpStr, &r )) != kOkPoRC )
375
+  if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kUIntPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
318 376
     return rc;
319 377
 
320 378
   r->dfltVal.u = dfltVal;
@@ -332,9 +390,7 @@ cmPoRC_t cmPgmOptInstallDbl( cmPgmOptH_t h, unsigned numId, cmChar_t charId, con
332 390
   _cmPoOpt_t* r     = NULL;
333 391
   _cmPo_t*    p     = _cmPoHandleToPtr(h);
334 392
 
335
-  flags = cmClrFlag(flags,kTypeMaskPoFl) | kDblPoFl;
336
-
337
-  if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, 0, cnt, helpStr, &r )) != kOkPoRC )
393
+  if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kDblPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
338 394
     return rc;
339 395
 
340 396
   r->dfltVal.d = dfltVal;
@@ -352,9 +408,8 @@ cmPoRC_t cmPgmOptInstallStr( cmPgmOptH_t h, unsigned numId, cmChar_t charId, con
352 408
   _cmPoOpt_t* r     = NULL;
353 409
   _cmPo_t*    p     = _cmPoHandleToPtr(h);
354 410
 
355
-  flags = cmClrFlag(flags,kTypeMaskPoFl) | kStrPoFl;
356 411
 
357
-  if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, 0, cnt, helpStr, &r )) != kOkPoRC )
412
+  if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kStrPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
358 413
     return rc;
359 414
 
360 415
   r->dfltVal.s = dfltVal;
@@ -366,15 +421,13 @@ cmPoRC_t cmPgmOptInstallStr( cmPgmOptH_t h, unsigned numId, cmChar_t charId, con
366 421
   return rc;
367 422
 }
368 423
 
369
-cmPoRC_t cmPgmOptInstallEnum(cmPgmOptH_t h, unsigned numId, cmChar_t charId, const cmChar_t* wordId, unsigned flags, unsigned enumId, unsigned dfltVal, unsigned* retValPtr, unsigned cnt, const cmChar_t* helpStr  )
424
+cmPoRC_t cmPgmOptInstallEnum(cmPgmOptH_t h, unsigned numId, cmChar_t charId, const cmChar_t* wordId, unsigned flags, unsigned enumId, unsigned dfltVal, unsigned* retValPtr, unsigned cnt, const cmChar_t* helpStr, const cmChar_t* mstrHelpStr  )
370 425
 {
371 426
   cmPoRC_t    rc;
372 427
   _cmPoOpt_t* r     = NULL;
373 428
   _cmPo_t*    p     = _cmPoHandleToPtr(h);
374 429
 
375
-  flags = cmClrFlag(flags,kTypeMaskPoFl) | kEnumPoFl;
376
-
377
-  if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, enumId, cnt, helpStr, &r )) != kOkPoRC )
430
+  if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kEnumPoFl, enumId, cnt, helpStr, &r )) != kOkPoRC )
378 431
     return rc;
379 432
 
380 433
   r->dfltVal.u = dfltVal;
@@ -383,6 +436,32 @@ cmPoRC_t cmPgmOptInstallEnum(cmPgmOptH_t h, unsigned numId, cmChar_t charId, con
383 436
     r->retVal.u  = retValPtr;
384 437
     *r->retVal.u = dfltVal;
385 438
   }
439
+
440
+  if( mstrHelpStr != NULL )
441
+  {
442
+    _cmPoOpt_t* rp = r->enumPtr == NULL ? r : r->enumPtr;
443
+    rp->mstrStr = cmLhAllocStr(p->lH,mstrHelpStr);
444
+  }
445
+  return rc;
446
+}
447
+
448
+cmPoRC_t cmPgmOptInstallFlag(cmPgmOptH_t h, unsigned numId, cmChar_t charId, const cmChar_t* wordId, unsigned flags, unsigned         dfltVal, unsigned*       retValPtr, unsigned cnt, const cmChar_t* helpStr )
449
+{
450
+  cmPoRC_t    rc;
451
+  _cmPoOpt_t* r     = NULL;
452
+  _cmPo_t*    p     = _cmPoHandleToPtr(h);
453
+
454
+  if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kFlagPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
455
+    return rc;
456
+
457
+  r->dfltVal.u = dfltVal;
458
+  if( retValPtr != NULL )
459
+  {
460
+    r->retVal.u  = retValPtr;
461
+    // Unlike other parameters we don't set the initial value of flag parameter 
462
+    // because we don't want to destroy any default flag that may be set there
463
+  }
464
+
386 465
   return rc;
387 466
 }
388 467
 
@@ -411,7 +490,7 @@ _cmPoArg_t* _cmPgmOptInsertArg( _cmPo_t* p,  _cmPoOpt_t* r )
411 490
   //  a->u.b = true;
412 491
 
413 492
   // if this is an enumerated type
414
-  if( cmIsFlag(r->flags,kEnumPoFl) )
493
+  if( cmIsFlag(r->sflags,kEnumPoFl) )
415 494
   {
416 495
     a->u.u = enumId;
417 496
 
@@ -421,6 +500,14 @@ _cmPoArg_t* _cmPgmOptInsertArg( _cmPo_t* p,  _cmPoOpt_t* r )
421 500
     if( e->retVal.u != NULL )
422 501
       *e->retVal.u = enumId;
423 502
   }
503
+
504
+  // if this is a flag type
505
+  if( cmIsFlag(r->sflags,kFlagPoFl) )
506
+  {
507
+    a->u.u = r->dfltVal.u;
508
+    if( r->retVal.u != NULL )
509
+      *r->retVal.u |= a->u.u;
510
+  }
424 511
   return a;
425 512
 }
426 513
 
@@ -453,8 +540,12 @@ cmPoRC_t _cmPgmOptParseValue( _cmPo_t* p, _cmPoOpt_t* r, _cmPoArg_t* a, const cm
453 540
   a->valStr = valStr;
454 541
 
455 542
   errno = 0;
456
-  switch( r->flags & kTypeMaskPoFl )
543
+  switch( r->sflags & kTypeMaskPoFl )
457 544
   {
545
+    // case kFlagPoFl: 
546
+    // enum values get set in _cmPgmOptInsertArg()
547
+
548
+
458 549
     case kBoolPoFl: 
459 550
       //rc = _cmPgmOptParseBool(p,valStr,&a->u.b); 
460 551
       a->u.b = true;
@@ -469,13 +560,13 @@ cmPoRC_t _cmPgmOptParseValue( _cmPo_t* p, _cmPoOpt_t* r, _cmPoArg_t* a, const cm
469 560
       break;
470 561
 
471 562
     case kIntPoFl:  
472
-      a->u.i = strtol(valStr,NULL,10); 
563
+      a->u.i = strtol(valStr,NULL, cmIsFlag(r->cflags,kHexPoFl) ? 16 : 10); 
473 564
       if( r->retVal.i != NULL )
474 565
         *r->retVal.i = a->u.i;
475 566
       break;
476 567
 
477 568
     case kUIntPoFl: 
478
-      a->u.u = strtol(valStr,NULL,10); 
569
+      a->u.u = strtol(valStr,NULL, cmIsFlag(r->cflags,kHexPoFl) ? 16 : 10); 
479 570
       if( r->retVal.u != NULL )
480 571
         *r->retVal.u = a->u.u;
481 572
       break;
@@ -483,12 +574,6 @@ cmPoRC_t _cmPgmOptParseValue( _cmPo_t* p, _cmPoOpt_t* r, _cmPoArg_t* a, const cm
483 574
       // case kEnumPoFl: 
484 575
       // enum values get set in _cmPgmOptInsertArg()
485 576
 
486
-    case kHexPoFl:  
487
-      a->u.u = strtol(valStr,NULL,16); 
488
-      if( r->retVal.u != NULL )
489
-        *r->retVal.u = a->u.u;
490
-      break;
491
-
492 577
     case kDblPoFl:  
493 578
       a->u.d = strtod(valStr,NULL);    
494 579
       if( r->retVal.d != NULL )
@@ -500,6 +585,9 @@ cmPoRC_t _cmPgmOptParseValue( _cmPo_t* p, _cmPoOpt_t* r, _cmPoArg_t* a, const cm
500 585
       if( r->retVal.s != NULL )
501 586
         *r->retVal.s = a->u.s;
502 587
       break;
588
+
589
+    default:
590
+      { assert(0); }
503 591
   }
504 592
 
505 593
 
@@ -540,6 +628,28 @@ bool _cmPgmOptCheckNoExec( _cmPo_t* p )
540 628
   return false;
541 629
 }
542 630
 
631
+cmPoRC_t  _cmPgmOptMissingEnumError( _cmPo_t* p, _cmPoOpt_t* r )
632
+{
633
+  _cmPoOpt_t* mstr = r->enumPtr==NULL ? r : r->enumPtr;
634
+  _cmPoOpt_t* rp  = p->list;
635
+  cmChar_t*   msg = cmTsPrintfP(NULL,"No argument was supplied for the required enumerated parameter containing the following set of possible flags: { ");
636
+  
637
+  for(; rp!=NULL; rp=rp->link)
638
+    if( cmIsFlag(rp->sflags,kEnumPoFl) && (rp==mstr || rp->enumPtr==mstr) )
639
+    {
640
+      msg = cmTextAppendSS(msg,rp->wordId);
641
+      msg = cmTextAppendSS(msg," ");
642
+    }
643
+
644
+  msg = cmTextAppendSS(msg,"}");
645
+  
646
+  cmPoRC_t rc = cmErrMsg(&p->err,kNoReqArgPoRC,msg);
647
+
648
+  cmMemFree(msg);
649
+  
650
+  return rc;
651
+}
652
+
543 653
 // check that all required arg.s were actually given and that the actual
544 654
 // number of instances does not exceed the defined limit
545 655
 cmPoRC_t _cmPgmOptCheckReqArgs( _cmPo_t* p )
@@ -549,7 +659,7 @@ cmPoRC_t _cmPgmOptCheckReqArgs( _cmPo_t* p )
549 659
   _cmPoOpt_t* r = p->list;
550 660
   while( r != NULL )
551 661
   {
552
-    if( cmIsFlag(r->flags, kReqPoFl ) )
662
+    if( cmIsFlag(r->cflags, kReqPoFl ) )
553 663
     {
554 664
       _cmPoArg_t* a = p->args;
555 665
       while( a != NULL )
@@ -560,7 +670,12 @@ cmPoRC_t _cmPgmOptCheckReqArgs( _cmPo_t* p )
560 670
       }
561 671
     
562 672
       if( a == NULL )
563
-        rc = cmErrMsg(&p->err,kNoReqArgPoRC,"No argument was supplied for the required parameter '%s'.",r->wordId);
673
+      {
674
+        if( cmIsFlag(r->sflags, kEnumPoFl ) )
675
+          rc =  _cmPgmOptMissingEnumError(p,r);
676
+        else
677
+          rc = cmErrMsg(&p->err,kNoReqArgPoRC,"No argument was supplied for the required parameter '%s'.",r->wordId);
678
+      }
564 679
 
565 680
     }
566 681
 
@@ -585,6 +700,17 @@ cmPoRC_t cmPgmOptParse( cmPgmOptH_t h, unsigned argCnt,  char* argArray[] )
585 700
   _cmPoArg_t* a     = NULL;
586 701
   int         i     = 0; // arg index
587 702
   int         j     = 0; // arg label character index
703
+
704
+
705
+  if( _cmPgmOptNumIdToOptRecd(p,kPrintHelpPoId) == NULL )
706
+    cmPgmOptInstallBool(h, kPrintHelpPoId, 'h', "help",    0, false, NULL,0,"Print this usage information." );
707
+
708
+  if( _cmPgmOptNumIdToOptRecd(p,kVersionPoId) == NULL )
709
+    cmPgmOptInstallBool(h, kVersionPoId,   'v', "version", 0, false, NULL,0,"Print version information." );
710
+
711
+  if( _cmPgmOptNumIdToOptRecd(p,kPrintParmsPoId) == NULL )
712
+    cmPgmOptInstallBool(h, kPrintParmsPoId,'p', "parms",   0, false, NULL,0,"Print the arguments."); 
713
+
588 714
   
589 715
   while(i<argCnt)
590 716
   {
@@ -628,8 +754,8 @@ cmPoRC_t cmPgmOptParse( cmPgmOptH_t h, unsigned argCnt,  char* argArray[] )
628 754
           if((r = _cmPgmOptCharIdToOptRecd(p,argArray[i][j])) == NULL )
629 755
             return cmErrMsg(&p->err,kSyntaxErrPoRC,"The program option selector char '%c' is not valid.",argArray[i][j]);
630 756
 
631
-          // if this charId is not a bool or enum then it must be followed by a value.
632
-          if( cmIsFlag(r->flags,kBoolPoFl)==false && cmIsFlag(r->flags,kEnumPoFl)==false )
757
+          // if this charId is not a flag,bool or enum then it must be followed by a value.
758
+          if( _cmPoOptUsesValue(r) )
633 759
             ++i;
634 760
           else // otherwise process the next char id in this charId token            
635 761
             ++j;
@@ -669,8 +795,8 @@ cmPoRC_t cmPgmOptParse( cmPgmOptH_t h, unsigned argCnt,  char* argArray[] )
669 795
         // create an arg record for the cur char or word id.
670 796
         a = _cmPgmOptInsertArg(p, r );
671 797
 
672
-        // and the value type is not 'bool' or 'enum'
673
-        if( cmIsFlag(r->flags,kBoolPoFl)== false && cmIsFlag(r->flags,kEnumPoFl)==false )
798
+        // and the value type is not 'flag','bool' or 'enum'
799
+        if( _cmPoOptUsesValue(r) )
674 800
           state = kArgVal;
675 801
 
676 802
         switch(state)
@@ -718,7 +844,7 @@ cmPoRC_t  _cmPgmOptIndexToPtr( _cmPo_t* p, unsigned idx, const _cmPoArg_t** app
718 844
   unsigned          n = 0;
719 845
   const _cmPoArg_t* a = p->args;
720 846
 
721
-  while( a != NULL && idx < n )
847
+  while( a != NULL && n < idx )
722 848
   {
723 849
     ++n;
724 850
     a = a->link;
@@ -732,7 +858,7 @@ cmPoRC_t  _cmPgmOptIndexToPtr( _cmPo_t* p, unsigned idx, const _cmPoArg_t** app
732 858
   return kOkPoRC;
733 859
 }
734 860
   
735
-unsigned cmPgmOptSelId( cmPgmOptH_t h, unsigned argIdx )
861
+unsigned cmPgmOptNumId( cmPgmOptH_t h, unsigned argIdx )
736 862
 {
737 863
   const _cmPoArg_t* a;
738 864
   cmPoRC_t          rc;
@@ -741,6 +867,24 @@ unsigned cmPgmOptSelId( cmPgmOptH_t h, unsigned argIdx )
741 867
   return a->opt->numId;
742 868
 }
743 869
 
870
+unsigned cmPgmOptCharId( cmPgmOptH_t h, unsigned argIdx )
871
+{
872
+  const _cmPoArg_t* a;
873
+  cmPoRC_t          rc;
874
+  if((rc = _cmPgmOptIndexToPtr(_cmPoHandleToPtr(h),argIdx,&a)) != kOkPoRC )
875
+    return cmInvalidId;
876
+  return a->opt->charId;
877
+}
878
+
879
+const cmChar_t* cmPgmOptWordId( cmPgmOptH_t h, unsigned argIdx )
880
+{
881
+  const _cmPoArg_t* a;
882
+  cmPoRC_t          rc;
883
+  if((rc = _cmPgmOptIndexToPtr(_cmPoHandleToPtr(h),argIdx,&a)) != kOkPoRC )
884
+    return NULL;
885
+  return a->opt->wordId;
886
+}
887
+
744 888
 cmPoRC_t  _cmPgmOptArgPtr( _cmPo_t* p, unsigned argIdx, const _cmPoArg_t** app )
745 889
 {
746 890
   cmPoRC_t rc;
@@ -903,7 +1047,7 @@ char        cmPgmOptArgChar( cmPgmOptH_t h, unsigned numId, unsigned instIdx )
903 1047
   if(_cmPgmOptInstPtr(p,numId,instIdx,&rp,&vp) != kOkPoRC )
904 1048
     return 0;
905 1049
 
906
-  if( cmIsFlag(rp->flags,kCharPoFl) )
1050
+  if( cmIsFlag(rp->sflags,kCharPoFl) )
907 1051
   {
908 1052
     cmErrMsg(&p->err,kTypeErrPoRC,"The parameter '%s' is not a 'char'.",rp->wordId);
909 1053
     return 0;
@@ -938,14 +1082,14 @@ int         cmPgmOptArgInt(    cmPgmOptH_t h, unsigned numId, unsigned instIdx )
938 1082
   if((rc = _cmPgmOptInstPtr(p,numId,instIdx,&rp,&vp)) != kOkPoRC )
939 1083
     return rc;
940 1084
  
941
-  switch( rp->flags & kTypeMaskPoFl )
1085
+  switch( rp->sflags & kTypeMaskPoFl )
942 1086
   {
1087
+    case kFlagPoFl: v = vp->u; break;
943 1088
     case kBoolPoFl: v = vp->b; break;
944 1089
     case kCharPoFl: v = vp->c; break;
945 1090
     case kIntPoFl:
946 1091
     case kEnumPoFl: v = vp->i; break;
947 1092
     case kUIntPoFl:
948
-    case kHexPoFl:  v = vp->u; break;
949 1093
     case kDblPoFl:  v = roundl(vp->d); break;
950 1094
     case kStrPoFl:  
951 1095
       cmErrMsg(&p->err,kTypeErrPoRC,"The string parameter '%s' cannot be converted to an integer.",rp->wordId);
@@ -972,13 +1116,13 @@ double      cmPgmOptArgDbl( cmPgmOptH_t h, unsigned numId, unsigned instIdx )
972 1116
   if((rc = _cmPgmOptInstPtr(p,numId,instIdx,&rp,&vp)) != kOkPoRC )
973 1117
     return rc;
974 1118
  
975
-  switch( rp->flags & kTypeMaskPoFl )
1119
+  switch( rp->sflags & kTypeMaskPoFl )
976 1120
   {
1121
+    case kFlagPoFl: v = vp->u; break;
977 1122
     case kBoolPoFl: v = vp->b; break;
978 1123
     case kCharPoFl: v = vp->c; break;
979 1124
     case kEnumPoFl:
980 1125
     case kIntPoFl:  v = vp->i; break;
981
-    case kHexPoFl:  
982 1126
     case kUIntPoFl: v = vp->u; break;
983 1127
     case kDblPoFl:  v = vp->d; break;
984 1128
     case kStrPoFl:  
@@ -1003,7 +1147,7 @@ const char* cmPgmOptArgStr(    cmPgmOptH_t h, unsigned numId, unsigned instIdx )
1003 1147
     return NULL;
1004 1148
 
1005 1149
   // if the requested param is a defined as a string
1006
-  if( cmIsFlag(rp->flags,kStrPoFl) )
1150
+  if( cmIsFlag(rp->sflags,kStrPoFl) )
1007 1151
     return vp->s;
1008 1152
 
1009 1153
   // otherwise the requested param is not defined as a string - so try to return the instance string value
@@ -1065,14 +1209,36 @@ void cmPgmOptPrintHelp( cmPgmOptH_t h, cmRpt_t* rpt )
1065 1209
   if( p->helpBegStr != NULL )
1066 1210
     cmRptPrintf(rpt,"%s\n",p->helpBegStr);
1067 1211
 
1068
-  while( r != NULL )
1212
+  for(; r != NULL; r=r->link )
1069 1213
   {
1070
-    cmRptPrintf(rpt,"-%c --%-20s ",r->charId,r->wordId);
1214
+    const cmChar_t* reqStr = "(required)";
1215
+    const cmChar_t* valueTypeLabel = "";
1216
+    const cmChar_t* reqLabel = "";
1217
+    const cmChar_t* indentStr = "";
1218
+
1219
+    const _cmPoOpt_t* mstr = NULL;
1220
+
1221
+    if( cmIsFlag(r->sflags,kEnumPoFl) )
1222
+    {
1223
+      if( r->enumPtr == NULL )
1224
+        mstr     = r;
1225
+      indentStr = "    ";
1226
+    }
1227
+
1228
+    if( _cmPoOptUsesValue(r) ) 
1229
+      valueTypeLabel = _cmPoTypeFlagToLabel(r->sflags & kTypeMaskPoFl,r->cflags);
1230
+
1231
+    if( cmIsNotFlag(r->sflags,kEnumPoFl)  && cmIsFlag(r->sflags,kReqPoFl) )
1232
+      reqLabel = reqStr;
1233
+
1234
+    if( mstr != NULL )
1235
+      cmRptPrintf(rpt,"Enumerated group: %s %s",mstr->mstrStr==NULL ? "" : mstr->mstrStr, cmIsFlag(mstr->cflags,kReqPoFl) ? reqStr : "" );
1236
+   
1237
+    cmRptPrintf(rpt,"%s-%c --%s %s %s",indentStr,r->charId,r->wordId,valueTypeLabel,reqLabel);
1071 1238
 
1072 1239
     if( r->helpStr != NULL )
1073 1240
       cmRptPrintf(rpt,"    %s\n",r->helpStr);
1074 1241
 
1075
-    r = r->link;
1076 1242
   }
1077 1243
   
1078 1244
 
@@ -1090,7 +1256,7 @@ void cmPgmOptPrintVersion( cmPgmOptH_t h, cmRpt_t* rpt )
1090 1256
 bool _cmPgmOptPrint( _cmPo_t* p, cmRpt_t* rpt, const _cmPoOpt_t* r, const _cmPoValue_t* v, const cmChar_t* valStr )
1091 1257
 {
1092 1258
   const _cmPoOpt_t* e = r;
1093
-  if( cmIsFlag(r->flags,kEnumPoFl) )
1259
+  if( cmIsFlag(r->sflags,kEnumPoFl) )
1094 1260
   {
1095 1261
     if( r->enumPtr != NULL )
1096 1262
       return false;
@@ -1103,13 +1269,13 @@ bool _cmPgmOptPrint( _cmPo_t* p, cmRpt_t* rpt, const _cmPoOpt_t* r, const _cmPoV
1103 1269
   }
1104 1270
 
1105 1271
   cmRptPrintf(rpt,"-%c --%-20s %i ",e->charId,e->wordId, _cmPgmOptInstCount(r));
1106
-  switch(r->flags & kTypeMaskPoFl)
1272
+  switch(r->sflags & kTypeMaskPoFl)
1107 1273
   {
1274
+    case kFlagPoFl: cmRptPrintf(rpt,r->cflags & kHexPoFl ? "0x%x ": "%u ",v->u ); break;
1108 1275
     case kBoolPoFl: cmRptPrintf(rpt,"%c ",  v->b ? 'T' : 'F'); break;
1109 1276
     case kCharPoFl: cmRptPrintf(rpt,"%c ",  v->c); break;
1110
-    case kIntPoFl:  cmRptPrintf(rpt,"%i ",  v->i); break;
1111
-    case kUIntPoFl: cmRptPrintf(rpt,"%u ",  v->u); break;
1112
-    case kHexPoFl:  cmRptPrintf(rpt,"0x%x ",v->u); break;
1277
+    case kIntPoFl:  cmRptPrintf(rpt,r->cflags & kHexPoFl ? "0x%x ": "%i ",  v->i); break;
1278
+    case kUIntPoFl: cmRptPrintf(rpt,r->cflags & kHexPoFl ? "0x%x ": "%u ",  v->u); break;
1113 1279
     case kDblPoFl:  cmRptPrintf(rpt,"%f ",  v->d); break;
1114 1280
     case kStrPoFl:  cmRptPrintf(rpt,"%s ",  v->s); break;
1115 1281
     case kEnumPoFl: cmRptPrintf(rpt,"%i ",  v->u); break;

+ 51
- 26
cmPgmOpts.h Переглянути файл

@@ -72,58 +72,77 @@ extern "C" {
72 72
 
73 73
   // Flag used by the 'flags' arg. to cmPgmOptInstall().
74 74
   enum { 
75
-    kNoPoFlags = 0x000, 
76
-    kReqPoFl   = 0x001,  // this is a required parameter
77
-    kBoolPoFl  = 0x002,  // this parameter takes a value
78
-    kCharPoFl  = 0x004,  // parm. value is a character
79
-    kIntPoFl   = 0x008,  // parm. value is a decimal int
80
-    kUIntPoFl  = 0x010,  // parm. value is a decimal unsigned int
81
-    kHexPoFl   = 0x020,  // parm. value is a hex. unsigned int 
82
-    kDblPoFl   = 0x040,  // parm. value is a decimal double
83
-    kStrPoFl   = 0x080,  // parm. value is a string (default)
84
-    kEnumPoFl  = 0x100,  // parm. valus is a enum type (automatically set by a non-zero enumId)
85
-
86
-    kTypeMaskPoFl = 0x1f6
75
+    kReqPoFl   = 0x01,  // this is a required parameter
76
+    kHexPoFl   = 0x02   // this integer must be given in hexidecimal or output an integer in hex.
87 77
   };
88 78
 
89 79
 
90 80
   // Define a parameter.
91 81
   //
92
-  // unsigned        numId,   - numeric id used to identify this parameter 
93
-  // const cmChar_t  charId,  - a character used to identify this parameter
94
-  // const cmChar_t* wordId,  - a label used to identify this parameter
82
+  // unsigned        numId,   - Numeric id used to identify this parameter. The min. numId should be kPoBaseId.
83
+  // const cmChar_t  charId,  - A character used to identify this parameter.
84
+  // const cmChar_t* wordId,  - A label used to identify this parameter.
95 85
   // unsigned        flags,   - kNoPoFlags | kReqPoFl (the type flags are automatically assigned)
96 86
   // unsigned        enumId,  - non-zero value used to group enumerated parameter values  (ignored for non-enum types)
87
+  //                 dfltVal  - The default value for this parameter.
88
+  //                 retValPtr- Optional pointer to a variable to receive the argument value for this parameter.
97 89
   // unsigned        cnt,     - count of times this parameter may repeated or 0 for an unlimited repetitions
98 90
   // const cmChar_t* helpStr  - a textual description of this parameter
99 91
   //
100 92
   // Notes
101
-  // 1) 'numId','charId', and 'wordId' must all be unique among all parameter definitions.
102
-  // 2) If no  parameter value type flag is given then the type is assumed to be of type bool.
103
-  // 3) For all parameter value types except the string type arguments are automatically parsed to the
93
+  // 1) 'numId','charId', and 'wordId' must all be unique among all parameter definitions.  
94
+  //    An error will be generated if they are not.
95
+  // 2) For all parameter value types except the string type arguments are automatically parsed to the
104 96
   //    defined type. To avoid automatic parsing simply define the type as a string (using cmPgmOptInstallStr()).
105
-  // 4) All expected parameters must be defined prior to calling cmPgmOptParse().
106
-  // 5) One call to cmPgmOPtInstallEnum() is made for each possible enumeration value - where the 'enumId' gives the value.
107
-  //    A given set of associated enum values is grouped by giving a common 'numId'.
97
+  // 3) All expected parameters must be defined prior to calling cmPgmOptParse().
98
+  // 4) One call to cmPgmOptInstallEnum() is made for each possible enumeration value - where the 'enumId' gives the value.
99
+  //    A given set of associated enum values is grouped by giving a common 'numId'. 
100
+  //    Include a master help string in one of the enumerated elements to give documentation 
101
+  //    text for the entire set of values.
108 102
   //    Example:
109
-  //     cmPgmOptInstallEnum(h,colorId,...,redId,...); 
110
-  //     cmPgmOptInstallEnum(h,colorId,...,greenId,...); 
111
-  //     cmPgmOptInstallEnum(h,colorId,...,blueId,...);   
103
+  //     cmPgmOptInstallEnum(h,colorId,...,redId,...,"Red","Select a color"); 
104
+  //     cmPgmOptInstallEnum(h,colorId,...,greenId,..."Green",NULL); 
105
+  //     cmPgmOptInstallEnum(h,colorId,...,blueId,...,"Blue",NULL);   
112 106
   //
113
-  // 6) The following id's are used for built-in actions and are therefore restricted from use by the client:
107
+  // 5) The following id's are used for built-in actions and are therefore restricted from use by the client:
114 108
   //    a. -h --help    Print the program usage information.
115 109
   //    b. -v --version Print the program version informatoin.
116 110
   //    c. -p --parms   Print the program parameter values.
117 111
   //
112
+  // 6) If a retValPtr is specified then *retValPtr it is assigned 'dfltVal' as part of the
113
+  //    call to cmPgmOptInstXXX().
114
+  // 
115
+  // 7) The default value of 'Flag' type parameters is always zero. 
116
+  //    If the 'char' or 'word' id of the Flag parameter appears in the
117
+  //    actual argument list then the value of the argument is 'onValue'.
118
+  //    Unlike other parameters Flag parameters do not initialize *regValPtr. 
119
+  //    If the retValPtr is given and the flag is set in the arg. list then
120
+  //    the retValPtr is set by bitwise assignment (i.e. *retValPtr |= dfltFlagValue).
121
+  //    This allows multiple Flag parameters to use the same retValPtr and
122
+  //    set independent bit fields in it.
118 123
   cmPoRC_t cmPgmOptInstallChar(cmPgmOptH_t h, unsigned numId, cmChar_t charId, const cmChar_t* worldId, unsigned flags, cmChar_t        dfltVal, cmChar_t*        retValPtr, unsigned cnt, const cmChar_t* helpStr );
119 124
   cmPoRC_t cmPgmOptInstallBool(cmPgmOptH_t h, unsigned numId, cmChar_t charId, const cmChar_t* worldId, unsigned flags, bool            dfltVal, bool*            retValPtr, unsigned cnt, const cmChar_t* helpStr );
120 125
   cmPoRC_t cmPgmOptInstallInt( cmPgmOptH_t h, unsigned numId, cmChar_t charId, const cmChar_t* worldId, unsigned flags, int             dfltVal, int*             retValPtr, unsigned cnt, const cmChar_t* helpStr );
121 126
   cmPoRC_t cmPgmOptInstallUInt(cmPgmOptH_t h, unsigned numId, cmChar_t charId, const cmChar_t* worldId, unsigned flags, unsigned        dfltVal, unsigned*        retValPtr, unsigned cnt, const cmChar_t* helpStr );
122 127
   cmPoRC_t cmPgmOptInstallDbl( cmPgmOptH_t h, unsigned numId, cmChar_t charId, const cmChar_t* worldId, unsigned flags, double          dfltVal, double*          retValPtr, unsigned cnt, const cmChar_t* helpStr );
123 128
   cmPoRC_t cmPgmOptInstallStr( cmPgmOptH_t h, unsigned numId, cmChar_t charId, const cmChar_t* worldId, unsigned flags, const cmChar_t* dfltVal, const cmChar_t** retValPtr, unsigned cnt, const cmChar_t* helpStr );
124
-  cmPoRC_t cmPgmOptInstallEnum(cmPgmOptH_t h, unsigned numId, cmChar_t charId, const cmChar_t* worldId, unsigned flags, unsigned enumId, unsigned dfltVal, unsigned* retValPtr, unsigned cnt, const cmChar_t* helpStr  );
129
+  cmPoRC_t cmPgmOptInstallEnum(cmPgmOptH_t h, unsigned numId, cmChar_t charId, const cmChar_t* worldId, unsigned flags, unsigned enumId, unsigned dfltVal, unsigned* retValPtr, unsigned cnt, const cmChar_t* helpStr, const cmChar_t* mstrHelpStr  );
130
+  cmPoRC_t cmPgmOptInstallFlag(cmPgmOptH_t h, unsigned numId, cmChar_t charId, const cmChar_t* worldId, unsigned flags, unsigned         onValue, unsigned*       retValPtr, unsigned cnt, const cmChar_t* helpStr );
125 131
 
126 132
   // Parse a set of command line arguments.
133
+  //
134
+  // 1) If only built-in parameters were specified then the NO check is done 
135
+  //    to verify that required arguments were provided.  However, if any non-built-in
136
+  //    arguments are provided then a check is performed to be sure that any 
137
+  //    parameters specified with the kPoReqFl have associated argument values.
138
+  //
139
+  // 2) If a parameter was specified with a 'retValPtr' then *retValPtr is
140
+  //    set to the value of the last argument associated with the given parameter.
141
+  //    This means that 'retValPtr' is generally only useful when the
142
+  //    parameter instance count limit (the 'cnt' param to cmPgmOptInstallXXX())
143
+  //    was set to 1.
144
+  //
145
+  //    
127 146
   cmPoRC_t cmPgmOptParse( cmPgmOptH_t h, unsigned argCnt, char* argArray[] );
128 147
   
129 148
   // Get the total count of arguments passed to cmPgmOptParse().
@@ -132,6 +151,12 @@ extern "C" {
132 151
   // Get the numeric id associated with each argument.
133 152
   unsigned cmPgmOptNumId( cmPgmOptH_t h, unsigned argIdx );
134 153
 
154
+  // Get the character id associated with this argument.
155
+  unsigned cmPgmOptCharId( cmPgmOptH_t h, unsigned argIdx );
156
+
157
+  // Get the word id associated with this argument.
158
+  const cmChar_t* cmPgmOptWordId( cmPgmOptH_t h, unsigned argIdx );
159
+
135 160
   // Manually convert each argument string into the specified type.
136 161
   // These functions are useful if all of the parameters were defined using cmPgmOptInstallStr().
137 162
   // Use cmPgmOptRC() to check for errors.

Завантаження…
Відмінити
Зберегти