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.
This commit is contained in:
kevin 2013-02-15 16:07:17 -08:00
parent bfcbe9f1fd
commit 5bf653dc5e
2 changed files with 289 additions and 98 deletions

View File

@ -6,8 +6,22 @@
#include "cmMallocDebug.h" #include "cmMallocDebug.h"
#include "cmLinkedHeap.h" #include "cmLinkedHeap.h"
#include "cmPgmOpts.h" #include "cmPgmOpts.h"
#include "cmText.h"
#include "config.h" #include "config.h"
enum {
kFlagPoFl = 0x001,
kBoolPoFl = 0x002, // this parameter does not take a value
kCharPoFl = 0x004, // parm. value is a character
kIntPoFl = 0x008, // parm. value is a decimal int
kUIntPoFl = 0x010, // parm. value is a decimal unsigned int
kDblPoFl = 0x040, // parm. value is a decimal double
kStrPoFl = 0x080, // parm. value is a string (default)
kEnumPoFl = 0x100, // parm. valus is a enum type (automatically set by a non-zero enumId)
kTypeMaskPoFl = 0x1ff
};
cmPgmOptH_t cmPgmOptNullHandle = cmSTATIC_NULL_HANDLE; cmPgmOptH_t cmPgmOptNullHandle = cmSTATIC_NULL_HANDLE;
struct _cmPoArg_str; struct _cmPoArg_str;
@ -39,13 +53,15 @@ typedef struct _cmPoOpt_str
unsigned numId; // unsigned numId; //
cmChar_t charId; // cmChar_t charId; //
cmChar_t* wordId; // cmChar_t* wordId; //
unsigned flags; // unsigned sflags; // state flags (type flags)
unsigned enumId; // unsigned cflags; // cfg flags (user settable cfg flag)
struct _cmPoOpt_str* enumPtr; // pointer to mast enum recd unsigned enumId; // enumerated set element id (numId is the group id)
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)
unsigned maxInstCnt; // unsigned maxInstCnt; //
_cmPoValue_t dfltVal; // default value for this parm _cmPoValue_t dfltVal; // default value for this parm
_cmPoValPtr_t retVal; // client supplied variable which recieves the value of the last arg. parsed for this parm. _cmPoValPtr_t retVal; // client supplied variable which recieves the value of the last arg. parsed for this parm.
cmChar_t* helpStr; // cmChar_t* helpStr; //
cmChar_t* mstrStr;
struct _cmPoOpt_str* link; // link used by the _cmPo_t.list linked list struct _cmPoOpt_str* link; // link used by the _cmPo_t.list linked list
struct _cmPoArg_str* inst; // arg's belonging to this opt record formed by _cmPoArg_t.inst links struct _cmPoArg_str* inst; // arg's belonging to this opt record formed by _cmPoArg_t.inst links
} _cmPoOpt_t; } _cmPoOpt_t;
@ -73,6 +89,45 @@ typedef struct
bool execFl; // set to false in cmPgmOptParse() if only built-in options were selected bool execFl; // set to false in cmPgmOptParse() if only built-in options were selected
} _cmPo_t; } _cmPo_t;
typedef struct
{
unsigned id;
const cmChar_t* label;
} _cmPoMap_t;
_cmPoMap_t _cmPoTypeMap[] =
{
{ kFlagPoFl, "" },
{ kBoolPoFl, "" },
{ kCharPoFl, "<char>" },
{ kIntPoFl, "<int>" },
{ kUIntPoFl, "<uint>" },
{ kDblPoFl, "<real>" },
{ kStrPoFl, "<text>" },
{ kEnumPoFl, "<enum>" },
{ 0, "<unknown>"}
};
const cmChar_t* _cmPoTypeFlagToLabel( unsigned flag, unsigned cflags )
{
if( cmIsFlag(cflags,kHexPoFl) )
return "<hex>";
const _cmPoMap_t* m = _cmPoTypeMap;
for(; m->id != 0; ++m)
if( m->id == flag )
break;
return m->label;
}
bool _cmPoOptUsesValue( const _cmPoOpt_t* r )
{
return
cmIsNotFlag(r->sflags,kEnumPoFl) &&
cmIsNotFlag(r->sflags,kBoolPoFl) &&
cmIsNotFlag(r->sflags,kFlagPoFl);
}
_cmPo_t* _cmPoHandleToPtr( cmPgmOptH_t h ) _cmPo_t* _cmPoHandleToPtr( cmPgmOptH_t h )
{ {
_cmPo_t* p = (_cmPo_t*)h.h; _cmPo_t* p = (_cmPo_t*)h.h;
@ -107,10 +162,6 @@ cmPoRC_t cmPgmOptInitialize(cmCtx_t* c, cmPgmOptH_t* hp, const cmChar_t* helpBeg
hp->h = p; hp->h = p;
cmPgmOptInstallBool(*hp, kPrintHelpPoId, 'h', "help", 0, false, NULL,0,"Print this usage information." );
cmPgmOptInstallBool(*hp, kVersionPoId, 'v', "version", 0, false, NULL,0,"Print version information." );
cmPgmOptInstallBool(*hp, kPrintParmsPoId,'p', "parms", 0, false, NULL,0,"Print the parameter information.");
return cmErrLastRC(&p->err); return cmErrLastRC(&p->err);
} }
@ -138,7 +189,7 @@ _cmPoOpt_t* _cmPgmOptNumIdToOptRecd( _cmPo_t* p, unsigned numId )
if( r->numId == numId ) if( r->numId == numId )
{ {
if( cmIsFlag(r->flags,kEnumPoFl) && r->enumPtr!=NULL ) if( cmIsFlag(r->sflags,kEnumPoFl) && r->enumPtr!=NULL )
r = r->enumPtr; r = r->enumPtr;
return r; return r;
@ -190,10 +241,10 @@ _cmPoOpt_t* _cmPgmOptWordIdToOptRecd( _cmPo_t* p, const cmChar_t* wordId )
} }
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 ) 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 )
{ {
// validate the num. id // validate the num. id
if( enumId==0 && _cmPgmOptNumIdToOptRecd(p,numId) != NULL ) if( cmIsNotFlag(sflags,kEnumPoFl) && _cmPgmOptNumIdToOptRecd(p,numId) != NULL )
return cmErrMsg(&p->err,kDuplicateIdPoRC,"The numeric id '%i' was already used by another parameter.",numId); return cmErrMsg(&p->err,kDuplicateIdPoRC,"The numeric id '%i' was already used by another parameter.",numId);
// validate the char. id // validate the char. id
@ -204,15 +255,18 @@ cmPoRC_t _cmPgmOptInstall( _cmPo_t* p, unsigned numId, const cmChar_t charId, co
if( _cmPgmOptWordIdToOptRecd(p,wordId) != NULL ) if( _cmPgmOptWordIdToOptRecd(p,wordId) != NULL )
return cmErrMsg(&p->err,kDuplicateIdPoRC,"The word id --'%s' was already used by another parameter.",wordId); return cmErrMsg(&p->err,kDuplicateIdPoRC,"The word id --'%s' was already used by another parameter.",wordId);
// clear the kHexPoFl if this is not an int or uint.
if( cmIsNotFlag(sflags,kFlagPoFl) && cmIsNotFlag(sflags,kIntPoFl) && cmIsNotFlag(sflags,kUIntPoFl) )
cflags = cmClrFlag(cflags,kHexPoFl);
// allocate the new parm recd // allocate the new parm recd
_cmPoOpt_t* r = cmLhAllocZ( p->lH, _cmPoOpt_t, 1 ); _cmPoOpt_t* r = cmLhAllocZ( p->lH, _cmPoOpt_t, 1 );
// if enumId != 0 then this is automatically an enum type. // if this is an enum type.
if( enumId != 0 ) if( cmIsFlag(sflags,kEnumPoFl) )
{ {
flags = cmClrFlag(flags,kTypeMaskPoFl) | kEnumPoFl; sflags = cmClrFlag(sflags,kTypeMaskPoFl) | kEnumPoFl;
// set the master recd for this enum ptr // set the master recd for this enum ptr
_cmPoOpt_t* erp; _cmPoOpt_t* erp;
@ -221,25 +275,37 @@ cmPoRC_t _cmPgmOptInstall( _cmPo_t* p, unsigned numId, const cmChar_t charId, co
r->enumPtr = erp->enumPtr==NULL ? erp : erp->enumPtr; r->enumPtr = erp->enumPtr==NULL ? erp : erp->enumPtr;
// if this child enum has it's required flags set // if this child enum has it's required flags set
if( cmIsFlag(flags,kReqPoFl) ) if( cmIsFlag(cflags,kReqPoFl) )
{ {
// then set the required flag in the parent and clear it in the child // then set the required flag in the parent and clear it in the child
// (this way both the parent and child will not be required (which would be impossible for an enum)) // (this way both the parent and child will not be required (which would be impossible for an enum))
r->enumPtr->flags = cmSetFlag(r->enumPtr->flags,kReqPoFl); r->enumPtr->cflags = cmSetFlag(r->enumPtr->cflags,kReqPoFl);
flags = cmClrFlag(flags,kReqPoFl); cflags = cmClrFlag(cflags,kReqPoFl);
} }
} }
} }
r->flags = flags; r->cflags = cflags;
r->sflags = sflags;
r->numId = numId; r->numId = numId;
r->charId = charId; r->charId = charId;
r->wordId = cmLhAllocStr( p->lH, wordId ); r->wordId = cmLhAllocStr( p->lH, wordId );
r->enumId = enumId; r->enumId = enumId;
r->maxInstCnt = cnt; r->maxInstCnt = cnt;
r->helpStr = helpStr==NULL ? NULL : cmLhAllocStr( p->lH, helpStr ); r->helpStr = helpStr==NULL ? NULL : cmLhAllocStr( p->lH, helpStr );
r->link = p->list;
p->list = r;
_cmPoOpt_t* rp = p->list;
while( rp != NULL && rp->link != NULL )
rp = rp->link;
if( rp == NULL )
p->list = r;
else
rp->link = r;
//r->link = p->list;
//p->list = r;
*rpp = r; *rpp = r;
@ -252,9 +318,7 @@ cmPoRC_t cmPgmOptInstallChar(cmPgmOptH_t h, unsigned numId, cmChar_t charId, con
_cmPoOpt_t* r = NULL; _cmPoOpt_t* r = NULL;
_cmPo_t* p = _cmPoHandleToPtr(h); _cmPo_t* p = _cmPoHandleToPtr(h);
flags = cmClrFlag(flags,kTypeMaskPoFl) | kCharPoFl; if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kCharPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, 0, cnt, helpStr, &r )) != kOkPoRC )
return rc; return rc;
r->dfltVal.c = dfltVal; r->dfltVal.c = dfltVal;
@ -272,9 +336,7 @@ cmPoRC_t cmPgmOptInstallBool(cmPgmOptH_t h, unsigned numId, cmChar_t charId, con
_cmPoOpt_t* r = NULL; _cmPoOpt_t* r = NULL;
_cmPo_t* p = _cmPoHandleToPtr(h); _cmPo_t* p = _cmPoHandleToPtr(h);
flags = cmClrFlag(flags,kTypeMaskPoFl) | kBoolPoFl; if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kBoolPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, 0, cnt, helpStr, &r )) != kOkPoRC )
return rc; return rc;
r->dfltVal.b = dfltVal; r->dfltVal.b = dfltVal;
@ -292,9 +354,7 @@ cmPoRC_t cmPgmOptInstallInt( cmPgmOptH_t h, unsigned numId, cmChar_t charId, con
_cmPoOpt_t* r = NULL; _cmPoOpt_t* r = NULL;
_cmPo_t* p = _cmPoHandleToPtr(h); _cmPo_t* p = _cmPoHandleToPtr(h);
flags = cmClrFlag(flags,kTypeMaskPoFl) | kIntPoFl; if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kIntPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, 0, cnt, helpStr, &r )) != kOkPoRC )
return rc; return rc;
r->dfltVal.i = dfltVal; r->dfltVal.i = dfltVal;
@ -312,9 +372,7 @@ cmPoRC_t cmPgmOptInstallUInt(cmPgmOptH_t h, unsigned numId, cmChar_t charId, con
_cmPoOpt_t* r = NULL; _cmPoOpt_t* r = NULL;
_cmPo_t* p = _cmPoHandleToPtr(h); _cmPo_t* p = _cmPoHandleToPtr(h);
flags = cmClrFlag(flags,kTypeMaskPoFl) | kUIntPoFl; if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kUIntPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, 0, cnt, helpStr, &r )) != kOkPoRC )
return rc; return rc;
r->dfltVal.u = dfltVal; r->dfltVal.u = dfltVal;
@ -332,9 +390,7 @@ cmPoRC_t cmPgmOptInstallDbl( cmPgmOptH_t h, unsigned numId, cmChar_t charId, con
_cmPoOpt_t* r = NULL; _cmPoOpt_t* r = NULL;
_cmPo_t* p = _cmPoHandleToPtr(h); _cmPo_t* p = _cmPoHandleToPtr(h);
flags = cmClrFlag(flags,kTypeMaskPoFl) | kDblPoFl; if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kDblPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, 0, cnt, helpStr, &r )) != kOkPoRC )
return rc; return rc;
r->dfltVal.d = dfltVal; r->dfltVal.d = dfltVal;
@ -352,9 +408,8 @@ cmPoRC_t cmPgmOptInstallStr( cmPgmOptH_t h, unsigned numId, cmChar_t charId, con
_cmPoOpt_t* r = NULL; _cmPoOpt_t* r = NULL;
_cmPo_t* p = _cmPoHandleToPtr(h); _cmPo_t* p = _cmPoHandleToPtr(h);
flags = cmClrFlag(flags,kTypeMaskPoFl) | kStrPoFl;
if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, 0, cnt, helpStr, &r )) != kOkPoRC ) if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kStrPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
return rc; return rc;
r->dfltVal.s = dfltVal; r->dfltVal.s = dfltVal;
@ -366,15 +421,13 @@ cmPoRC_t cmPgmOptInstallStr( cmPgmOptH_t h, unsigned numId, cmChar_t charId, con
return rc; return rc;
} }
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 ) 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 )
{ {
cmPoRC_t rc; cmPoRC_t rc;
_cmPoOpt_t* r = NULL; _cmPoOpt_t* r = NULL;
_cmPo_t* p = _cmPoHandleToPtr(h); _cmPo_t* p = _cmPoHandleToPtr(h);
flags = cmClrFlag(flags,kTypeMaskPoFl) | kEnumPoFl; if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kEnumPoFl, enumId, cnt, helpStr, &r )) != kOkPoRC )
if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, enumId, cnt, helpStr, &r )) != kOkPoRC )
return rc; return rc;
r->dfltVal.u = dfltVal; r->dfltVal.u = dfltVal;
@ -383,6 +436,32 @@ cmPoRC_t cmPgmOptInstallEnum(cmPgmOptH_t h, unsigned numId, cmChar_t charId, con
r->retVal.u = retValPtr; r->retVal.u = retValPtr;
*r->retVal.u = dfltVal; *r->retVal.u = dfltVal;
} }
if( mstrHelpStr != NULL )
{
_cmPoOpt_t* rp = r->enumPtr == NULL ? r : r->enumPtr;
rp->mstrStr = cmLhAllocStr(p->lH,mstrHelpStr);
}
return rc;
}
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 )
{
cmPoRC_t rc;
_cmPoOpt_t* r = NULL;
_cmPo_t* p = _cmPoHandleToPtr(h);
if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kFlagPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
return rc;
r->dfltVal.u = dfltVal;
if( retValPtr != NULL )
{
r->retVal.u = retValPtr;
// Unlike other parameters we don't set the initial value of flag parameter
// because we don't want to destroy any default flag that may be set there
}
return rc; return rc;
} }
@ -411,7 +490,7 @@ _cmPoArg_t* _cmPgmOptInsertArg( _cmPo_t* p, _cmPoOpt_t* r )
// a->u.b = true; // a->u.b = true;
// if this is an enumerated type // if this is an enumerated type
if( cmIsFlag(r->flags,kEnumPoFl) ) if( cmIsFlag(r->sflags,kEnumPoFl) )
{ {
a->u.u = enumId; a->u.u = enumId;
@ -421,6 +500,14 @@ _cmPoArg_t* _cmPgmOptInsertArg( _cmPo_t* p, _cmPoOpt_t* r )
if( e->retVal.u != NULL ) if( e->retVal.u != NULL )
*e->retVal.u = enumId; *e->retVal.u = enumId;
} }
// if this is a flag type
if( cmIsFlag(r->sflags,kFlagPoFl) )
{
a->u.u = r->dfltVal.u;
if( r->retVal.u != NULL )
*r->retVal.u |= a->u.u;
}
return a; return a;
} }
@ -453,8 +540,12 @@ cmPoRC_t _cmPgmOptParseValue( _cmPo_t* p, _cmPoOpt_t* r, _cmPoArg_t* a, const cm
a->valStr = valStr; a->valStr = valStr;
errno = 0; errno = 0;
switch( r->flags & kTypeMaskPoFl ) switch( r->sflags & kTypeMaskPoFl )
{ {
// case kFlagPoFl:
// enum values get set in _cmPgmOptInsertArg()
case kBoolPoFl: case kBoolPoFl:
//rc = _cmPgmOptParseBool(p,valStr,&a->u.b); //rc = _cmPgmOptParseBool(p,valStr,&a->u.b);
a->u.b = true; a->u.b = true;
@ -469,13 +560,13 @@ cmPoRC_t _cmPgmOptParseValue( _cmPo_t* p, _cmPoOpt_t* r, _cmPoArg_t* a, const cm
break; break;
case kIntPoFl: case kIntPoFl:
a->u.i = strtol(valStr,NULL,10); a->u.i = strtol(valStr,NULL, cmIsFlag(r->cflags,kHexPoFl) ? 16 : 10);
if( r->retVal.i != NULL ) if( r->retVal.i != NULL )
*r->retVal.i = a->u.i; *r->retVal.i = a->u.i;
break; break;
case kUIntPoFl: case kUIntPoFl:
a->u.u = strtol(valStr,NULL,10); a->u.u = strtol(valStr,NULL, cmIsFlag(r->cflags,kHexPoFl) ? 16 : 10);
if( r->retVal.u != NULL ) if( r->retVal.u != NULL )
*r->retVal.u = a->u.u; *r->retVal.u = a->u.u;
break; break;
@ -483,12 +574,6 @@ cmPoRC_t _cmPgmOptParseValue( _cmPo_t* p, _cmPoOpt_t* r, _cmPoArg_t* a, const cm
// case kEnumPoFl: // case kEnumPoFl:
// enum values get set in _cmPgmOptInsertArg() // enum values get set in _cmPgmOptInsertArg()
case kHexPoFl:
a->u.u = strtol(valStr,NULL,16);
if( r->retVal.u != NULL )
*r->retVal.u = a->u.u;
break;
case kDblPoFl: case kDblPoFl:
a->u.d = strtod(valStr,NULL); a->u.d = strtod(valStr,NULL);
if( r->retVal.d != NULL ) if( r->retVal.d != NULL )
@ -500,6 +585,9 @@ cmPoRC_t _cmPgmOptParseValue( _cmPo_t* p, _cmPoOpt_t* r, _cmPoArg_t* a, const cm
if( r->retVal.s != NULL ) if( r->retVal.s != NULL )
*r->retVal.s = a->u.s; *r->retVal.s = a->u.s;
break; break;
default:
{ assert(0); }
} }
@ -540,6 +628,28 @@ bool _cmPgmOptCheckNoExec( _cmPo_t* p )
return false; return false;
} }
cmPoRC_t _cmPgmOptMissingEnumError( _cmPo_t* p, _cmPoOpt_t* r )
{
_cmPoOpt_t* mstr = r->enumPtr==NULL ? r : r->enumPtr;
_cmPoOpt_t* rp = p->list;
cmChar_t* msg = cmTsPrintfP(NULL,"No argument was supplied for the required enumerated parameter containing the following set of possible flags: { ");
for(; rp!=NULL; rp=rp->link)
if( cmIsFlag(rp->sflags,kEnumPoFl) && (rp==mstr || rp->enumPtr==mstr) )
{
msg = cmTextAppendSS(msg,rp->wordId);
msg = cmTextAppendSS(msg," ");
}
msg = cmTextAppendSS(msg,"}");
cmPoRC_t rc = cmErrMsg(&p->err,kNoReqArgPoRC,msg);
cmMemFree(msg);
return rc;
}
// check that all required arg.s were actually given and that the actual // check that all required arg.s were actually given and that the actual
// number of instances does not exceed the defined limit // number of instances does not exceed the defined limit
cmPoRC_t _cmPgmOptCheckReqArgs( _cmPo_t* p ) cmPoRC_t _cmPgmOptCheckReqArgs( _cmPo_t* p )
@ -549,7 +659,7 @@ cmPoRC_t _cmPgmOptCheckReqArgs( _cmPo_t* p )
_cmPoOpt_t* r = p->list; _cmPoOpt_t* r = p->list;
while( r != NULL ) while( r != NULL )
{ {
if( cmIsFlag(r->flags, kReqPoFl ) ) if( cmIsFlag(r->cflags, kReqPoFl ) )
{ {
_cmPoArg_t* a = p->args; _cmPoArg_t* a = p->args;
while( a != NULL ) while( a != NULL )
@ -560,7 +670,12 @@ cmPoRC_t _cmPgmOptCheckReqArgs( _cmPo_t* p )
} }
if( a == NULL ) if( a == NULL )
rc = cmErrMsg(&p->err,kNoReqArgPoRC,"No argument was supplied for the required parameter '%s'.",r->wordId); {
if( cmIsFlag(r->sflags, kEnumPoFl ) )
rc = _cmPgmOptMissingEnumError(p,r);
else
rc = cmErrMsg(&p->err,kNoReqArgPoRC,"No argument was supplied for the required parameter '%s'.",r->wordId);
}
} }
@ -585,6 +700,17 @@ cmPoRC_t cmPgmOptParse( cmPgmOptH_t h, unsigned argCnt, char* argArray[] )
_cmPoArg_t* a = NULL; _cmPoArg_t* a = NULL;
int i = 0; // arg index int i = 0; // arg index
int j = 0; // arg label character index int j = 0; // arg label character index
if( _cmPgmOptNumIdToOptRecd(p,kPrintHelpPoId) == NULL )
cmPgmOptInstallBool(h, kPrintHelpPoId, 'h', "help", 0, false, NULL,0,"Print this usage information." );
if( _cmPgmOptNumIdToOptRecd(p,kVersionPoId) == NULL )
cmPgmOptInstallBool(h, kVersionPoId, 'v', "version", 0, false, NULL,0,"Print version information." );
if( _cmPgmOptNumIdToOptRecd(p,kPrintParmsPoId) == NULL )
cmPgmOptInstallBool(h, kPrintParmsPoId,'p', "parms", 0, false, NULL,0,"Print the arguments.");
while(i<argCnt) while(i<argCnt)
{ {
@ -628,8 +754,8 @@ cmPoRC_t cmPgmOptParse( cmPgmOptH_t h, unsigned argCnt, char* argArray[] )
if((r = _cmPgmOptCharIdToOptRecd(p,argArray[i][j])) == NULL ) if((r = _cmPgmOptCharIdToOptRecd(p,argArray[i][j])) == NULL )
return cmErrMsg(&p->err,kSyntaxErrPoRC,"The program option selector char '%c' is not valid.",argArray[i][j]); return cmErrMsg(&p->err,kSyntaxErrPoRC,"The program option selector char '%c' is not valid.",argArray[i][j]);
// if this charId is not a bool or enum then it must be followed by a value. // if this charId is not a flag,bool or enum then it must be followed by a value.
if( cmIsFlag(r->flags,kBoolPoFl)==false && cmIsFlag(r->flags,kEnumPoFl)==false ) if( _cmPoOptUsesValue(r) )
++i; ++i;
else // otherwise process the next char id in this charId token else // otherwise process the next char id in this charId token
++j; ++j;
@ -669,8 +795,8 @@ cmPoRC_t cmPgmOptParse( cmPgmOptH_t h, unsigned argCnt, char* argArray[] )
// create an arg record for the cur char or word id. // create an arg record for the cur char or word id.
a = _cmPgmOptInsertArg(p, r ); a = _cmPgmOptInsertArg(p, r );
// and the value type is not 'bool' or 'enum' // and the value type is not 'flag','bool' or 'enum'
if( cmIsFlag(r->flags,kBoolPoFl)== false && cmIsFlag(r->flags,kEnumPoFl)==false ) if( _cmPoOptUsesValue(r) )
state = kArgVal; state = kArgVal;
switch(state) switch(state)
@ -718,7 +844,7 @@ cmPoRC_t _cmPgmOptIndexToPtr( _cmPo_t* p, unsigned idx, const _cmPoArg_t** app
unsigned n = 0; unsigned n = 0;
const _cmPoArg_t* a = p->args; const _cmPoArg_t* a = p->args;
while( a != NULL && idx < n ) while( a != NULL && n < idx )
{ {
++n; ++n;
a = a->link; a = a->link;
@ -732,7 +858,7 @@ cmPoRC_t _cmPgmOptIndexToPtr( _cmPo_t* p, unsigned idx, const _cmPoArg_t** app
return kOkPoRC; return kOkPoRC;
} }
unsigned cmPgmOptSelId( cmPgmOptH_t h, unsigned argIdx ) unsigned cmPgmOptNumId( cmPgmOptH_t h, unsigned argIdx )
{ {
const _cmPoArg_t* a; const _cmPoArg_t* a;
cmPoRC_t rc; cmPoRC_t rc;
@ -741,6 +867,24 @@ unsigned cmPgmOptSelId( cmPgmOptH_t h, unsigned argIdx )
return a->opt->numId; return a->opt->numId;
} }
unsigned cmPgmOptCharId( cmPgmOptH_t h, unsigned argIdx )
{
const _cmPoArg_t* a;
cmPoRC_t rc;
if((rc = _cmPgmOptIndexToPtr(_cmPoHandleToPtr(h),argIdx,&a)) != kOkPoRC )
return cmInvalidId;
return a->opt->charId;
}
const cmChar_t* cmPgmOptWordId( cmPgmOptH_t h, unsigned argIdx )
{
const _cmPoArg_t* a;
cmPoRC_t rc;
if((rc = _cmPgmOptIndexToPtr(_cmPoHandleToPtr(h),argIdx,&a)) != kOkPoRC )
return NULL;
return a->opt->wordId;
}
cmPoRC_t _cmPgmOptArgPtr( _cmPo_t* p, unsigned argIdx, const _cmPoArg_t** app ) cmPoRC_t _cmPgmOptArgPtr( _cmPo_t* p, unsigned argIdx, const _cmPoArg_t** app )
{ {
cmPoRC_t rc; cmPoRC_t rc;
@ -903,7 +1047,7 @@ char cmPgmOptArgChar( cmPgmOptH_t h, unsigned numId, unsigned instIdx )
if(_cmPgmOptInstPtr(p,numId,instIdx,&rp,&vp) != kOkPoRC ) if(_cmPgmOptInstPtr(p,numId,instIdx,&rp,&vp) != kOkPoRC )
return 0; return 0;
if( cmIsFlag(rp->flags,kCharPoFl) ) if( cmIsFlag(rp->sflags,kCharPoFl) )
{ {
cmErrMsg(&p->err,kTypeErrPoRC,"The parameter '%s' is not a 'char'.",rp->wordId); cmErrMsg(&p->err,kTypeErrPoRC,"The parameter '%s' is not a 'char'.",rp->wordId);
return 0; return 0;
@ -938,14 +1082,14 @@ int cmPgmOptArgInt( cmPgmOptH_t h, unsigned numId, unsigned instIdx )
if((rc = _cmPgmOptInstPtr(p,numId,instIdx,&rp,&vp)) != kOkPoRC ) if((rc = _cmPgmOptInstPtr(p,numId,instIdx,&rp,&vp)) != kOkPoRC )
return rc; return rc;
switch( rp->flags & kTypeMaskPoFl ) switch( rp->sflags & kTypeMaskPoFl )
{ {
case kFlagPoFl: v = vp->u; break;
case kBoolPoFl: v = vp->b; break; case kBoolPoFl: v = vp->b; break;
case kCharPoFl: v = vp->c; break; case kCharPoFl: v = vp->c; break;
case kIntPoFl: case kIntPoFl:
case kEnumPoFl: v = vp->i; break; case kEnumPoFl: v = vp->i; break;
case kUIntPoFl: case kUIntPoFl:
case kHexPoFl: v = vp->u; break;
case kDblPoFl: v = roundl(vp->d); break; case kDblPoFl: v = roundl(vp->d); break;
case kStrPoFl: case kStrPoFl:
cmErrMsg(&p->err,kTypeErrPoRC,"The string parameter '%s' cannot be converted to an integer.",rp->wordId); 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 )
if((rc = _cmPgmOptInstPtr(p,numId,instIdx,&rp,&vp)) != kOkPoRC ) if((rc = _cmPgmOptInstPtr(p,numId,instIdx,&rp,&vp)) != kOkPoRC )
return rc; return rc;
switch( rp->flags & kTypeMaskPoFl ) switch( rp->sflags & kTypeMaskPoFl )
{ {
case kFlagPoFl: v = vp->u; break;
case kBoolPoFl: v = vp->b; break; case kBoolPoFl: v = vp->b; break;
case kCharPoFl: v = vp->c; break; case kCharPoFl: v = vp->c; break;
case kEnumPoFl: case kEnumPoFl:
case kIntPoFl: v = vp->i; break; case kIntPoFl: v = vp->i; break;
case kHexPoFl:
case kUIntPoFl: v = vp->u; break; case kUIntPoFl: v = vp->u; break;
case kDblPoFl: v = vp->d; break; case kDblPoFl: v = vp->d; break;
case kStrPoFl: case kStrPoFl:
@ -1003,7 +1147,7 @@ const char* cmPgmOptArgStr( cmPgmOptH_t h, unsigned numId, unsigned instIdx )
return NULL; return NULL;
// if the requested param is a defined as a string // if the requested param is a defined as a string
if( cmIsFlag(rp->flags,kStrPoFl) ) if( cmIsFlag(rp->sflags,kStrPoFl) )
return vp->s; return vp->s;
// otherwise the requested param is not defined as a string - so try to return the instance string value // 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 )
if( p->helpBegStr != NULL ) if( p->helpBegStr != NULL )
cmRptPrintf(rpt,"%s\n",p->helpBegStr); cmRptPrintf(rpt,"%s\n",p->helpBegStr);
while( r != NULL ) for(; r != NULL; r=r->link )
{ {
cmRptPrintf(rpt,"-%c --%-20s ",r->charId,r->wordId); const cmChar_t* reqStr = "(required)";
const cmChar_t* valueTypeLabel = "";
const cmChar_t* reqLabel = "";
const cmChar_t* indentStr = "";
const _cmPoOpt_t* mstr = NULL;
if( cmIsFlag(r->sflags,kEnumPoFl) )
{
if( r->enumPtr == NULL )
mstr = r;
indentStr = " ";
}
if( _cmPoOptUsesValue(r) )
valueTypeLabel = _cmPoTypeFlagToLabel(r->sflags & kTypeMaskPoFl,r->cflags);
if( cmIsNotFlag(r->sflags,kEnumPoFl) && cmIsFlag(r->sflags,kReqPoFl) )
reqLabel = reqStr;
if( mstr != NULL )
cmRptPrintf(rpt,"Enumerated group: %s %s",mstr->mstrStr==NULL ? "" : mstr->mstrStr, cmIsFlag(mstr->cflags,kReqPoFl) ? reqStr : "" );
cmRptPrintf(rpt,"%s-%c --%s %s %s",indentStr,r->charId,r->wordId,valueTypeLabel,reqLabel);
if( r->helpStr != NULL ) if( r->helpStr != NULL )
cmRptPrintf(rpt," %s\n",r->helpStr); cmRptPrintf(rpt," %s\n",r->helpStr);
r = r->link;
} }
@ -1090,7 +1256,7 @@ void cmPgmOptPrintVersion( cmPgmOptH_t h, cmRpt_t* rpt )
bool _cmPgmOptPrint( _cmPo_t* p, cmRpt_t* rpt, const _cmPoOpt_t* r, const _cmPoValue_t* v, const cmChar_t* valStr ) bool _cmPgmOptPrint( _cmPo_t* p, cmRpt_t* rpt, const _cmPoOpt_t* r, const _cmPoValue_t* v, const cmChar_t* valStr )
{ {
const _cmPoOpt_t* e = r; const _cmPoOpt_t* e = r;
if( cmIsFlag(r->flags,kEnumPoFl) ) if( cmIsFlag(r->sflags,kEnumPoFl) )
{ {
if( r->enumPtr != NULL ) if( r->enumPtr != NULL )
return false; return false;
@ -1103,13 +1269,13 @@ bool _cmPgmOptPrint( _cmPo_t* p, cmRpt_t* rpt, const _cmPoOpt_t* r, const _cmPoV
} }
cmRptPrintf(rpt,"-%c --%-20s %i ",e->charId,e->wordId, _cmPgmOptInstCount(r)); cmRptPrintf(rpt,"-%c --%-20s %i ",e->charId,e->wordId, _cmPgmOptInstCount(r));
switch(r->flags & kTypeMaskPoFl) switch(r->sflags & kTypeMaskPoFl)
{ {
case kFlagPoFl: cmRptPrintf(rpt,r->cflags & kHexPoFl ? "0x%x ": "%u ",v->u ); break;
case kBoolPoFl: cmRptPrintf(rpt,"%c ", v->b ? 'T' : 'F'); break; case kBoolPoFl: cmRptPrintf(rpt,"%c ", v->b ? 'T' : 'F'); break;
case kCharPoFl: cmRptPrintf(rpt,"%c ", v->c); break; case kCharPoFl: cmRptPrintf(rpt,"%c ", v->c); break;
case kIntPoFl: cmRptPrintf(rpt,"%i ", v->i); break; case kIntPoFl: cmRptPrintf(rpt,r->cflags & kHexPoFl ? "0x%x ": "%i ", v->i); break;
case kUIntPoFl: cmRptPrintf(rpt,"%u ", v->u); break; case kUIntPoFl: cmRptPrintf(rpt,r->cflags & kHexPoFl ? "0x%x ": "%u ", v->u); break;
case kHexPoFl: cmRptPrintf(rpt,"0x%x ",v->u); break;
case kDblPoFl: cmRptPrintf(rpt,"%f ", v->d); break; case kDblPoFl: cmRptPrintf(rpt,"%f ", v->d); break;
case kStrPoFl: cmRptPrintf(rpt,"%s ", v->s); break; case kStrPoFl: cmRptPrintf(rpt,"%s ", v->s); break;
case kEnumPoFl: cmRptPrintf(rpt,"%i ", v->u); break; case kEnumPoFl: cmRptPrintf(rpt,"%i ", v->u); break;

View File

@ -72,58 +72,77 @@ extern "C" {
// Flag used by the 'flags' arg. to cmPgmOptInstall(). // Flag used by the 'flags' arg. to cmPgmOptInstall().
enum { enum {
kNoPoFlags = 0x000, kReqPoFl = 0x01, // this is a required parameter
kReqPoFl = 0x001, // this is a required parameter kHexPoFl = 0x02 // this integer must be given in hexidecimal or output an integer in hex.
kBoolPoFl = 0x002, // this parameter takes a value
kCharPoFl = 0x004, // parm. value is a character
kIntPoFl = 0x008, // parm. value is a decimal int
kUIntPoFl = 0x010, // parm. value is a decimal unsigned int
kHexPoFl = 0x020, // parm. value is a hex. unsigned int
kDblPoFl = 0x040, // parm. value is a decimal double
kStrPoFl = 0x080, // parm. value is a string (default)
kEnumPoFl = 0x100, // parm. valus is a enum type (automatically set by a non-zero enumId)
kTypeMaskPoFl = 0x1f6
}; };
// Define a parameter. // Define a parameter.
// //
// unsigned numId, - numeric id used to identify this parameter // unsigned numId, - Numeric id used to identify this parameter. The min. numId should be kPoBaseId.
// const cmChar_t charId, - a character used to identify this parameter // const cmChar_t charId, - A character used to identify this parameter.
// const cmChar_t* wordId, - a label used to identify this parameter // const cmChar_t* wordId, - A label used to identify this parameter.
// unsigned flags, - kNoPoFlags | kReqPoFl (the type flags are automatically assigned) // unsigned flags, - kNoPoFlags | kReqPoFl (the type flags are automatically assigned)
// unsigned enumId, - non-zero value used to group enumerated parameter values (ignored for non-enum types) // unsigned enumId, - non-zero value used to group enumerated parameter values (ignored for non-enum types)
// dfltVal - The default value for this parameter.
// retValPtr- Optional pointer to a variable to receive the argument value for this parameter.
// unsigned cnt, - count of times this parameter may repeated or 0 for an unlimited repetitions // unsigned cnt, - count of times this parameter may repeated or 0 for an unlimited repetitions
// const cmChar_t* helpStr - a textual description of this parameter // const cmChar_t* helpStr - a textual description of this parameter
// //
// Notes // Notes
// 1) 'numId','charId', and 'wordId' must all be unique among all parameter definitions. // 1) 'numId','charId', and 'wordId' must all be unique among all parameter definitions.
// 2) If no parameter value type flag is given then the type is assumed to be of type bool. // An error will be generated if they are not.
// 3) For all parameter value types except the string type arguments are automatically parsed to the // 2) For all parameter value types except the string type arguments are automatically parsed to the
// defined type. To avoid automatic parsing simply define the type as a string (using cmPgmOptInstallStr()). // defined type. To avoid automatic parsing simply define the type as a string (using cmPgmOptInstallStr()).
// 4) All expected parameters must be defined prior to calling cmPgmOptParse(). // 3) All expected parameters must be defined prior to calling cmPgmOptParse().
// 5) One call to cmPgmOPtInstallEnum() is made for each possible enumeration value - where the 'enumId' gives the value. // 4) One call to cmPgmOptInstallEnum() is made for each possible enumeration value - where the 'enumId' gives the value.
// A given set of associated enum values is grouped by giving a common 'numId'. // A given set of associated enum values is grouped by giving a common 'numId'.
// Include a master help string in one of the enumerated elements to give documentation
// text for the entire set of values.
// Example: // Example:
// cmPgmOptInstallEnum(h,colorId,...,redId,...); // cmPgmOptInstallEnum(h,colorId,...,redId,...,"Red","Select a color");
// cmPgmOptInstallEnum(h,colorId,...,greenId,...); // cmPgmOptInstallEnum(h,colorId,...,greenId,..."Green",NULL);
// cmPgmOptInstallEnum(h,colorId,...,blueId,...); // cmPgmOptInstallEnum(h,colorId,...,blueId,...,"Blue",NULL);
// //
// 6) The following id's are used for built-in actions and are therefore restricted from use by the client: // 5) The following id's are used for built-in actions and are therefore restricted from use by the client:
// a. -h --help Print the program usage information. // a. -h --help Print the program usage information.
// b. -v --version Print the program version informatoin. // b. -v --version Print the program version informatoin.
// c. -p --parms Print the program parameter values. // c. -p --parms Print the program parameter values.
// //
// 6) If a retValPtr is specified then *retValPtr it is assigned 'dfltVal' as part of the
// call to cmPgmOptInstXXX().
//
// 7) The default value of 'Flag' type parameters is always zero.
// If the 'char' or 'word' id of the Flag parameter appears in the
// actual argument list then the value of the argument is 'onValue'.
// Unlike other parameters Flag parameters do not initialize *regValPtr.
// If the retValPtr is given and the flag is set in the arg. list then
// the retValPtr is set by bitwise assignment (i.e. *retValPtr |= dfltFlagValue).
// This allows multiple Flag parameters to use the same retValPtr and
// set independent bit fields in it.
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 ); 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 );
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 ); 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 );
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 ); 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 );
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 ); 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 );
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 ); 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 );
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 ); 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 );
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 ); 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 );
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 );
// Parse a set of command line arguments. // Parse a set of command line arguments.
//
// 1) If only built-in parameters were specified then the NO check is done
// to verify that required arguments were provided. However, if any non-built-in
// arguments are provided then a check is performed to be sure that any
// parameters specified with the kPoReqFl have associated argument values.
//
// 2) If a parameter was specified with a 'retValPtr' then *retValPtr is
// set to the value of the last argument associated with the given parameter.
// This means that 'retValPtr' is generally only useful when the
// parameter instance count limit (the 'cnt' param to cmPgmOptInstallXXX())
// was set to 1.
//
//
cmPoRC_t cmPgmOptParse( cmPgmOptH_t h, unsigned argCnt, char* argArray[] ); cmPoRC_t cmPgmOptParse( cmPgmOptH_t h, unsigned argCnt, char* argArray[] );
// Get the total count of arguments passed to cmPgmOptParse(). // Get the total count of arguments passed to cmPgmOptParse().
@ -132,6 +151,12 @@ extern "C" {
// Get the numeric id associated with each argument. // Get the numeric id associated with each argument.
unsigned cmPgmOptNumId( cmPgmOptH_t h, unsigned argIdx ); unsigned cmPgmOptNumId( cmPgmOptH_t h, unsigned argIdx );
// Get the character id associated with this argument.
unsigned cmPgmOptCharId( cmPgmOptH_t h, unsigned argIdx );
// Get the word id associated with this argument.
const cmChar_t* cmPgmOptWordId( cmPgmOptH_t h, unsigned argIdx );
// Manually convert each argument string into the specified type. // Manually convert each argument string into the specified type.
// These functions are useful if all of the parameters were defined using cmPgmOptInstallStr(). // These functions are useful if all of the parameters were defined using cmPgmOptInstallStr().
// Use cmPgmOptRC() to check for errors. // Use cmPgmOptRC() to check for errors.