5bf653dc5e
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.
1316 lines
34 KiB
C
1316 lines
34 KiB
C
#include "cmGlobal.h"
|
|
#include "cmRpt.h"
|
|
#include "cmErr.h"
|
|
#include "cmCtx.h"
|
|
#include "cmMem.h"
|
|
#include "cmMallocDebug.h"
|
|
#include "cmLinkedHeap.h"
|
|
#include "cmPgmOpts.h"
|
|
#include "cmText.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;
|
|
|
|
struct _cmPoArg_str;
|
|
|
|
typedef union
|
|
{
|
|
bool b;
|
|
char c;
|
|
int i;
|
|
unsigned u;
|
|
double d;
|
|
const cmChar_t* s;
|
|
} _cmPoValue_t;
|
|
|
|
typedef union
|
|
{
|
|
bool* b;
|
|
char* c;
|
|
int* i;
|
|
unsigned* u;
|
|
double* d;
|
|
const cmChar_t** s;
|
|
} _cmPoValPtr_t;
|
|
|
|
|
|
// opt records describe the a given parameters configuration
|
|
typedef struct _cmPoOpt_str
|
|
{
|
|
unsigned numId; //
|
|
cmChar_t charId; //
|
|
cmChar_t* wordId; //
|
|
unsigned sflags; // state flags (type flags)
|
|
unsigned cflags; // cfg flags (user settable cfg flag)
|
|
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; //
|
|
_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.
|
|
cmChar_t* helpStr; //
|
|
cmChar_t* mstrStr;
|
|
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
|
|
} _cmPoOpt_t;
|
|
|
|
|
|
// arg records describe an instance of a given parameter.
|
|
// (there may be multiple instances of a given parameter)
|
|
typedef struct _cmPoArg_str
|
|
{
|
|
const _cmPoOpt_t* opt; // the opt record associated with this arg. instance
|
|
struct _cmPoArg_str* link; // link used by the _cmPo_t.args list
|
|
struct _cmPoArg_str* inst; // link used by the _cmPoOpt_t* inst list
|
|
const cmChar_t* valStr; // string value for this arg.
|
|
_cmPoValue_t u; // parsed value for this arg.
|
|
} _cmPoArg_t;
|
|
|
|
typedef struct
|
|
{
|
|
cmErr_t err;
|
|
cmLHeapH_t lH;
|
|
cmChar_t* helpBegStr;
|
|
cmChar_t* helpEndStr;
|
|
_cmPoOpt_t* list; // list of control records formed by _cmPoOpt_t.link links
|
|
_cmPoArg_t* args; // list of arg. records formed by _cmPoArg_t.link links
|
|
bool execFl; // set to false in cmPgmOptParse() if only built-in options were selected
|
|
} _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* p = (_cmPo_t*)h.h;
|
|
assert(p != NULL );
|
|
return p;
|
|
}
|
|
|
|
cmPoRC_t _cmPgmOptFinalize( _cmPo_t* p )
|
|
{
|
|
cmPoRC_t rc = kOkPoRC;
|
|
cmLHeapDestroy(&p->lH);
|
|
cmMemPtrFree(&p);
|
|
return rc;
|
|
}
|
|
|
|
bool cmPgmOptIsValid( cmPgmOptH_t h )
|
|
{ return h.h != NULL; }
|
|
|
|
cmPoRC_t cmPgmOptInitialize(cmCtx_t* c, cmPgmOptH_t* hp, const cmChar_t* helpBegStr, const cmChar_t* helpEndStr )
|
|
{
|
|
cmPoRC_t rc;
|
|
if((rc = cmPgmOptFinalize(hp)) != kOkPoRC )
|
|
return rc;
|
|
|
|
_cmPo_t* p = cmMemAllocZ(_cmPo_t,1);
|
|
|
|
cmErrSetup(&p->err,&c->rpt,"Program Options");
|
|
|
|
p->lH = cmLHeapCreate(2048,c);
|
|
p->helpBegStr = helpBegStr==NULL ? NULL : cmLhAllocStr( p->lH, helpBegStr );
|
|
p->helpEndStr = helpEndStr==NULL ? NULL : cmLhAllocStr( p->lH, helpEndStr );
|
|
|
|
hp->h = p;
|
|
|
|
return cmErrLastRC(&p->err);
|
|
}
|
|
|
|
cmPoRC_t cmPgmOptFinalize( cmPgmOptH_t* hp )
|
|
{
|
|
cmPoRC_t rc = kOkPoRC;
|
|
|
|
if( hp == NULL || cmPgmOptIsValid(*hp) == false )
|
|
return kOkPoRC;
|
|
|
|
_cmPo_t* p = _cmPoHandleToPtr(*hp);
|
|
|
|
if((rc = _cmPgmOptFinalize(p)) != kOkPoRC )
|
|
return rc;
|
|
|
|
hp->h = NULL;
|
|
return rc;
|
|
}
|
|
|
|
_cmPoOpt_t* _cmPgmOptNumIdToOptRecd( _cmPo_t* p, unsigned numId )
|
|
{
|
|
_cmPoOpt_t* r = p->list;
|
|
while( r != NULL )
|
|
{
|
|
if( r->numId == numId )
|
|
{
|
|
|
|
if( cmIsFlag(r->sflags,kEnumPoFl) && r->enumPtr!=NULL )
|
|
r = r->enumPtr;
|
|
|
|
return r;
|
|
}
|
|
|
|
r = r->link;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
_cmPoOpt_t* _cmPgmOptEnumIdToOptRecd( _cmPo_t* p, unsigned numId, unsigned enumId )
|
|
{
|
|
_cmPoOpt_t* r = p->list;
|
|
while( r != NULL )
|
|
{
|
|
if( r->numId == numId && r->enumId == enumId )
|
|
return r;
|
|
|
|
r = r->link;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
_cmPoOpt_t* _cmPgmOptCharIdToOptRecd( _cmPo_t* p, cmChar_t charId )
|
|
{
|
|
_cmPoOpt_t* r = p->list;
|
|
while( r != NULL )
|
|
{
|
|
if( r->charId == charId )
|
|
return r;
|
|
|
|
r = r->link;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
_cmPoOpt_t* _cmPgmOptWordIdToOptRecd( _cmPo_t* p, const cmChar_t* wordId )
|
|
{
|
|
_cmPoOpt_t* r = p->list;
|
|
while( r != NULL )
|
|
{
|
|
if( strcmp(wordId,r->wordId) == 0 )
|
|
return r;
|
|
|
|
r = r->link;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
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
|
|
if( cmIsNotFlag(sflags,kEnumPoFl) && _cmPgmOptNumIdToOptRecd(p,numId) != NULL )
|
|
return cmErrMsg(&p->err,kDuplicateIdPoRC,"The numeric id '%i' was already used by another parameter.",numId);
|
|
|
|
// validate the char. id
|
|
if( _cmPgmOptCharIdToOptRecd(p,charId) != NULL )
|
|
return cmErrMsg(&p->err,kDuplicateIdPoRC,"The character id -'%c' was already used by another parameter.",charId);
|
|
|
|
// validate the word. id
|
|
if( _cmPgmOptWordIdToOptRecd(p,wordId) != NULL )
|
|
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
|
|
_cmPoOpt_t* r = cmLhAllocZ( p->lH, _cmPoOpt_t, 1 );
|
|
|
|
|
|
// if this is an enum type.
|
|
if( cmIsFlag(sflags,kEnumPoFl) )
|
|
{
|
|
sflags = cmClrFlag(sflags,kTypeMaskPoFl) | kEnumPoFl;
|
|
|
|
// set the master recd for this enum ptr
|
|
_cmPoOpt_t* erp;
|
|
if((erp = _cmPgmOptNumIdToOptRecd(p,numId)) != NULL )
|
|
{
|
|
r->enumPtr = erp->enumPtr==NULL ? erp : erp->enumPtr;
|
|
|
|
// if this child enum has it's required flags set
|
|
if( cmIsFlag(cflags,kReqPoFl) )
|
|
{
|
|
// 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))
|
|
r->enumPtr->cflags = cmSetFlag(r->enumPtr->cflags,kReqPoFl);
|
|
cflags = cmClrFlag(cflags,kReqPoFl);
|
|
}
|
|
}
|
|
}
|
|
|
|
r->cflags = cflags;
|
|
r->sflags = sflags;
|
|
r->numId = numId;
|
|
r->charId = charId;
|
|
r->wordId = cmLhAllocStr( p->lH, wordId );
|
|
r->enumId = enumId;
|
|
r->maxInstCnt = cnt;
|
|
r->helpStr = helpStr==NULL ? NULL : cmLhAllocStr( p->lH, helpStr );
|
|
|
|
|
|
_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;
|
|
|
|
return kOkPoRC;
|
|
}
|
|
|
|
cmPoRC_t cmPgmOptInstallChar(cmPgmOptH_t h, unsigned numId, cmChar_t charId, const cmChar_t* wordId, unsigned flags, cmChar_t dfltVal, cmChar_t* 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, kCharPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
|
|
return rc;
|
|
|
|
r->dfltVal.c = dfltVal;
|
|
if( retValPtr != NULL )
|
|
{
|
|
r->retVal.c = retValPtr;
|
|
*r->retVal.c = dfltVal;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
cmPoRC_t cmPgmOptInstallBool(cmPgmOptH_t h, unsigned numId, cmChar_t charId, const cmChar_t* wordId, unsigned flags, bool dfltVal, bool* 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, kBoolPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
|
|
return rc;
|
|
|
|
r->dfltVal.b = dfltVal;
|
|
if( retValPtr != NULL )
|
|
{
|
|
r->retVal.b = retValPtr;
|
|
*r->retVal.b = dfltVal;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
cmPoRC_t cmPgmOptInstallInt( cmPgmOptH_t h, unsigned numId, cmChar_t charId, const cmChar_t* wordId, unsigned flags, int dfltVal, int* 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, kIntPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
|
|
return rc;
|
|
|
|
r->dfltVal.i = dfltVal;
|
|
if( retValPtr != NULL )
|
|
{
|
|
r->retVal.i = retValPtr;
|
|
*r->retVal.i = dfltVal;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
cmPoRC_t cmPgmOptInstallUInt(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, kUIntPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
|
|
return rc;
|
|
|
|
r->dfltVal.u = dfltVal;
|
|
if( retValPtr != NULL )
|
|
{
|
|
r->retVal.u = retValPtr;
|
|
*r->retVal.u = dfltVal;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
cmPoRC_t cmPgmOptInstallDbl( cmPgmOptH_t h, unsigned numId, cmChar_t charId, const cmChar_t* wordId, unsigned flags, double dfltVal, double* 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, kDblPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
|
|
return rc;
|
|
|
|
r->dfltVal.d = dfltVal;
|
|
if( retValPtr != NULL )
|
|
{
|
|
r->retVal.d = retValPtr;
|
|
*r->retVal.d = dfltVal;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
cmPoRC_t cmPgmOptInstallStr( cmPgmOptH_t h, unsigned numId, cmChar_t charId, const cmChar_t* wordId, unsigned flags, const cmChar_t* dfltVal, const cmChar_t** 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, kStrPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
|
|
return rc;
|
|
|
|
r->dfltVal.s = dfltVal;
|
|
if( retValPtr != NULL )
|
|
{
|
|
r->retVal.s = retValPtr;
|
|
*r->retVal.s = dfltVal;
|
|
}
|
|
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, const cmChar_t* mstrHelpStr )
|
|
{
|
|
cmPoRC_t rc;
|
|
_cmPoOpt_t* r = NULL;
|
|
_cmPo_t* p = _cmPoHandleToPtr(h);
|
|
|
|
if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kEnumPoFl, enumId, cnt, helpStr, &r )) != kOkPoRC )
|
|
return rc;
|
|
|
|
r->dfltVal.u = dfltVal;
|
|
if( retValPtr != NULL )
|
|
{
|
|
r->retVal.u = retValPtr;
|
|
*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;
|
|
}
|
|
|
|
|
|
_cmPoArg_t* _cmPgmOptInsertArg( _cmPo_t* p, _cmPoOpt_t* r )
|
|
{
|
|
_cmPoArg_t* a = cmLhAllocZ(p->lH, _cmPoArg_t, 1);
|
|
|
|
// if this is an enumerated type then switch to the master enum recd
|
|
unsigned enumId = r->enumId;
|
|
_cmPoOpt_t* e = r;
|
|
if( r->enumPtr != NULL )
|
|
r = r->enumPtr;
|
|
|
|
a->opt = r;
|
|
a->valStr = NULL;
|
|
|
|
a->link = p->args; // link into master arg list
|
|
p->args = a;
|
|
|
|
a->inst = r->inst; // link into opt recd list
|
|
r->inst = a;
|
|
|
|
// if no parm. type flag was given then the arg is implicitely a bool and the value is true.
|
|
//if( (r->flags & kTypeMaskPoFl) == 0 )
|
|
// a->u.b = true;
|
|
|
|
// if this is an enumerated type
|
|
if( cmIsFlag(r->sflags,kEnumPoFl) )
|
|
{
|
|
a->u.u = enumId;
|
|
|
|
if( r->retVal.u != NULL )
|
|
*r->retVal.u = enumId;
|
|
|
|
if( e->retVal.u != NULL )
|
|
*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;
|
|
}
|
|
|
|
cmPoRC_t _cmPgmOptParseBool(_cmPo_t* p, const cmChar_t* valStr, bool* retValPtr )
|
|
{
|
|
cmPoRC_t rc = kOkPoRC;
|
|
unsigned n = strlen("false");
|
|
char val[n+1];
|
|
int i;
|
|
for(i=0; i<n && valStr[i]; ++i)
|
|
val[i] = tolower(valStr[i]);
|
|
val[i] = 0;
|
|
|
|
if( !strcmp(val,"0") || !strcmp(val,"false") || !strcmp(val,"f") )
|
|
*retValPtr = false;
|
|
else
|
|
if( !strcmp(val,"1") || !strcmp(val,"true") || !strcmp(val,"t") )
|
|
*retValPtr = true;
|
|
else
|
|
rc = cmErrMsg(&p->err,kParseFailPoRC,"The argument '%s' could not be parsed into a bool. Legal bool values are 0,F,FALSE,1,T,TRUE (case insensitive).",valStr);
|
|
|
|
return rc;
|
|
}
|
|
|
|
cmPoRC_t _cmPgmOptParseValue( _cmPo_t* p, _cmPoOpt_t* r, _cmPoArg_t* a, const cmChar_t* valStr )
|
|
{
|
|
cmPoRC_t rc = kOkPoRC;
|
|
|
|
assert(a != NULL && valStr != NULL);
|
|
a->valStr = valStr;
|
|
|
|
errno = 0;
|
|
switch( r->sflags & kTypeMaskPoFl )
|
|
{
|
|
// case kFlagPoFl:
|
|
// enum values get set in _cmPgmOptInsertArg()
|
|
|
|
|
|
case kBoolPoFl:
|
|
//rc = _cmPgmOptParseBool(p,valStr,&a->u.b);
|
|
a->u.b = true;
|
|
if( r->retVal.b != NULL )
|
|
*r->retVal.b = a->u.b;
|
|
break;
|
|
|
|
case kCharPoFl:
|
|
a->u.c = valStr[0];
|
|
if( r->retVal.c != NULL )
|
|
*r->retVal.c = a->u.c;
|
|
break;
|
|
|
|
case kIntPoFl:
|
|
a->u.i = strtol(valStr,NULL, cmIsFlag(r->cflags,kHexPoFl) ? 16 : 10);
|
|
if( r->retVal.i != NULL )
|
|
*r->retVal.i = a->u.i;
|
|
break;
|
|
|
|
case kUIntPoFl:
|
|
a->u.u = strtol(valStr,NULL, cmIsFlag(r->cflags,kHexPoFl) ? 16 : 10);
|
|
if( r->retVal.u != NULL )
|
|
*r->retVal.u = a->u.u;
|
|
break;
|
|
|
|
// case kEnumPoFl:
|
|
// enum values get set in _cmPgmOptInsertArg()
|
|
|
|
case kDblPoFl:
|
|
a->u.d = strtod(valStr,NULL);
|
|
if( r->retVal.d != NULL )
|
|
*r->retVal.d = a->u.d;
|
|
break;
|
|
|
|
case kStrPoFl:
|
|
a->u.s = valStr;
|
|
if( r->retVal.s != NULL )
|
|
*r->retVal.s = a->u.s;
|
|
break;
|
|
|
|
default:
|
|
{ assert(0); }
|
|
}
|
|
|
|
|
|
if( errno != 0 )
|
|
rc = cmErrMsg(&p->err,kParseFailPoRC,"The value '%s' for option '%s' could not be parsed.",valStr,r->wordId);
|
|
|
|
return rc;
|
|
}
|
|
|
|
unsigned _cmPgmOptInstCount( const _cmPoOpt_t* r )
|
|
{
|
|
const _cmPoArg_t* a = r->inst;
|
|
unsigned n = 0;
|
|
|
|
while( a != NULL )
|
|
{
|
|
++n;
|
|
a = a->inst;
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
|
|
// check if any non-built-in options were provided
|
|
// If only built in options were selected then no execution is assumed
|
|
// and required arg's are not checked.
|
|
bool _cmPgmOptCheckNoExec( _cmPo_t* p )
|
|
{
|
|
_cmPoArg_t* a = p->args;
|
|
while( a != NULL )
|
|
{
|
|
if( a->opt->numId >= kBasePoId )
|
|
return true;
|
|
|
|
a = a->link;
|
|
}
|
|
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
|
|
// number of instances does not exceed the defined limit
|
|
cmPoRC_t _cmPgmOptCheckReqArgs( _cmPo_t* p )
|
|
{
|
|
cmPoRC_t rc = kOkPoRC;
|
|
|
|
_cmPoOpt_t* r = p->list;
|
|
while( r != NULL )
|
|
{
|
|
if( cmIsFlag(r->cflags, kReqPoFl ) )
|
|
{
|
|
_cmPoArg_t* a = p->args;
|
|
while( a != NULL )
|
|
{
|
|
if( a->opt == r )
|
|
break;
|
|
a = a->link;
|
|
}
|
|
|
|
if( a == NULL )
|
|
{
|
|
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);
|
|
}
|
|
|
|
}
|
|
|
|
unsigned cnt;
|
|
if( r->maxInstCnt > 0 && r->maxInstCnt < (cnt=_cmPgmOptInstCount(r)) )
|
|
rc = cmErrMsg(&p->err,kArgCntErrPoRC,"The parameter '%s' has %i instances which exceeds the defined limit of %i instances.",r->wordId,cnt,r->maxInstCnt);
|
|
|
|
r = r->link;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
cmPoRC_t cmPgmOptParse( cmPgmOptH_t h, unsigned argCnt, char* argArray[] )
|
|
{
|
|
enum { kDash, kCharId, kWordId, kArgVal };
|
|
cmPoRC_t rc = kOkPoRC;
|
|
_cmPo_t* p = _cmPoHandleToPtr(h);
|
|
unsigned state = kDash;
|
|
_cmPoOpt_t* r = NULL;
|
|
_cmPoArg_t* a = NULL;
|
|
int i = 0; // arg 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)
|
|
{
|
|
const cmChar_t* valStr = NULL;
|
|
|
|
switch(state)
|
|
{
|
|
|
|
case kDash:
|
|
// this token must begin with a '-' character
|
|
if( argArray[i][0] != '-')
|
|
return cmErrMsg(&p->err,kSyntaxErrPoRC,"Syntax error. Expecting a '-'.");
|
|
|
|
// if the second char. is also a '-' then this is a wordId
|
|
if( argArray[i][1] == '-' )
|
|
{
|
|
state = kWordId;
|
|
j = 2; // word id's always begin on the third token char
|
|
}
|
|
else // otherwise it is a charId
|
|
{
|
|
state = kCharId;
|
|
j = 1; // char id's always begin on the second token char
|
|
}
|
|
|
|
r = NULL;
|
|
break;
|
|
|
|
case kCharId:
|
|
// we complete our parsing of charId's only when we encounter a '\0'
|
|
if( argArray[i][j] == '\0' )
|
|
{
|
|
++i;
|
|
state = kDash;
|
|
r = NULL;
|
|
a = NULL;
|
|
}
|
|
else
|
|
{
|
|
// get the opt recd assoc'd with the jth character in this charId
|
|
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]);
|
|
|
|
// if this charId is not a flag,bool or enum then it must be followed by a value.
|
|
if( _cmPoOptUsesValue(r) )
|
|
++i;
|
|
else // otherwise process the next char id in this charId token
|
|
++j;
|
|
}
|
|
break;
|
|
|
|
case kWordId:
|
|
// get the wordId
|
|
if((r = _cmPgmOptWordIdToOptRecd(p,argArray[i]+j)) == NULL )
|
|
return cmErrMsg(&p->err,kSyntaxErrPoRC,"The program option selector word '%s' is not valid.",cmStringNullGuard(argArray[i]+j));
|
|
++i; // advance to the next token
|
|
break;
|
|
|
|
case kArgVal:
|
|
assert(r != NULL );
|
|
valStr = argArray[i];
|
|
++i;
|
|
break;
|
|
}
|
|
|
|
// if a valid opt recd has been selected
|
|
if( r != NULL )
|
|
{
|
|
// if the cur token reprsents a value ...
|
|
if( state == kArgVal )
|
|
{
|
|
// ... then parse the value string
|
|
if((rc = _cmPgmOptParseValue(p,r,a,valStr)) != kOkPoRC )
|
|
goto errLabel;
|
|
|
|
r = NULL;
|
|
a = NULL;
|
|
state = kDash; // value strings are always followed by char or word id's
|
|
}
|
|
else
|
|
{
|
|
// create an arg record for the cur char or word id.
|
|
a = _cmPgmOptInsertArg(p, r );
|
|
|
|
// and the value type is not 'flag','bool' or 'enum'
|
|
if( _cmPoOptUsesValue(r) )
|
|
state = kArgVal;
|
|
|
|
switch(state)
|
|
{
|
|
case kDash: assert(i==argCnt); break;
|
|
case kCharId: break;
|
|
case kWordId: state = kDash; break;
|
|
case kArgVal: break;
|
|
default: assert(0); break;
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
errLabel:
|
|
|
|
// if no errors have occurred then check for missing parameters.
|
|
if( rc == kOkPoRC )
|
|
{
|
|
if((p->execFl = _cmPgmOptCheckNoExec(p)) == true )
|
|
rc = _cmPgmOptCheckReqArgs(p);
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
unsigned cmPgmOptArgCount( cmPgmOptH_t h)
|
|
{
|
|
_cmPo_t* p = _cmPoHandleToPtr(h);
|
|
const _cmPoArg_t* a = p->args;
|
|
unsigned n = 0;
|
|
|
|
while( a != NULL )
|
|
{
|
|
++n;
|
|
a = a->link;
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
cmPoRC_t _cmPgmOptIndexToPtr( _cmPo_t* p, unsigned idx, const _cmPoArg_t** app )
|
|
{
|
|
unsigned n = 0;
|
|
const _cmPoArg_t* a = p->args;
|
|
|
|
while( a != NULL && n < idx )
|
|
{
|
|
++n;
|
|
a = a->link;
|
|
}
|
|
|
|
if( n!=idx || a==NULL)
|
|
return cmErrMsg(&p->err,kInvalidIdxPoRC,"The option index '%i' is not valid.",idx);
|
|
|
|
*app = a;
|
|
|
|
return kOkPoRC;
|
|
}
|
|
|
|
unsigned cmPgmOptNumId( 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->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 rc;
|
|
|
|
if((rc = _cmPgmOptIndexToPtr(p,argIdx,app)) != kOkPoRC )
|
|
{
|
|
if( (*app)->valStr == NULL )
|
|
return cmErrMsg(&p->err,kParseFailPoRC,"The parameter at index '%i' is not a value.",argIdx);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
char cmPgmOptParseArgChar( cmPgmOptH_t h, unsigned argIdx )
|
|
{
|
|
cmPoRC_t rc;
|
|
const _cmPoArg_t* a;
|
|
_cmPo_t* p = _cmPoHandleToPtr(h);
|
|
|
|
if((rc = _cmPgmOptArgPtr(p,argIdx,&a)) != kOkPoRC )
|
|
return 0;
|
|
|
|
return a->valStr==NULL ? 0 : a->valStr[0];
|
|
}
|
|
|
|
bool cmPgmOptParseArgBool( cmPgmOptH_t h, unsigned argIdx )
|
|
{
|
|
cmPoRC_t rc;
|
|
const _cmPoArg_t* a;
|
|
_cmPo_t* p = _cmPoHandleToPtr(h);
|
|
bool val = false;
|
|
|
|
if((rc = _cmPgmOptArgPtr(p,argIdx,&a)) != kOkPoRC )
|
|
return false;
|
|
|
|
if( a->valStr != NULL )
|
|
_cmPgmOptParseBool(p,a->valStr,&val);
|
|
|
|
return val;
|
|
}
|
|
|
|
int cmPgmOptParseArgInt( cmPgmOptH_t h, unsigned argIdx )
|
|
{
|
|
cmPoRC_t rc;
|
|
const _cmPoArg_t* a;
|
|
_cmPo_t* p = _cmPoHandleToPtr(h);
|
|
|
|
if((rc = _cmPgmOptArgPtr(p,argIdx,&a)) != kOkPoRC )
|
|
return rc;
|
|
|
|
errno = 0;
|
|
int v = strtol(a->valStr,NULL,10);
|
|
if( errno != 0 )
|
|
cmErrMsg(&p->err,kParseFailPoRC,"The parameter '%s' could not be converted to an 'int'.",a->valStr);
|
|
|
|
return v;
|
|
}
|
|
|
|
unsigned cmPgmOptParseArgUInt( cmPgmOptH_t h, unsigned argIdx )
|
|
{
|
|
cmPoRC_t rc;
|
|
const _cmPoArg_t* a;
|
|
_cmPo_t* p = _cmPoHandleToPtr(h);
|
|
|
|
if((rc = _cmPgmOptArgPtr(p,argIdx,&a)) != kOkPoRC )
|
|
return rc;
|
|
|
|
errno = 0;
|
|
unsigned v = strtol(a->valStr,NULL,10);
|
|
if( errno != 0 )
|
|
cmErrMsg(&p->err,kParseFailPoRC,"The parameter '%s' could not be converted to an 'unsigned int'.",a->valStr);
|
|
|
|
return v;
|
|
}
|
|
|
|
double cmPgmOptParseArgDbl( cmPgmOptH_t h, unsigned argIdx )
|
|
{
|
|
cmPoRC_t rc;
|
|
const _cmPoArg_t* a;
|
|
_cmPo_t* p = _cmPoHandleToPtr(h);
|
|
|
|
if((rc = _cmPgmOptArgPtr(p,argIdx,&a)) != kOkPoRC )
|
|
return rc;
|
|
|
|
errno = 0;
|
|
double v = strtod(a->valStr,NULL);
|
|
if( errno != 0 )
|
|
cmErrMsg(&p->err,kParseFailPoRC,"The parameter '%s' could not be converted to a 'double'.",a->valStr);
|
|
|
|
return v;
|
|
}
|
|
|
|
const char* cmPgmOptParseArgStr( cmPgmOptH_t h, unsigned argIdx )
|
|
{
|
|
cmPoRC_t rc;
|
|
const _cmPoArg_t* a;
|
|
_cmPo_t* p = _cmPoHandleToPtr(h);
|
|
|
|
if((rc = _cmPgmOptArgPtr(p,argIdx,&a)) != kOkPoRC )
|
|
return NULL;
|
|
return a->valStr;
|
|
}
|
|
|
|
unsigned cmPgmOptParmArgCount( cmPgmOptH_t h, unsigned numId )
|
|
{
|
|
const _cmPoOpt_t* r;
|
|
_cmPo_t* p = _cmPoHandleToPtr(h);
|
|
unsigned n = 0;
|
|
|
|
if((r = _cmPgmOptNumIdToOptRecd(p,numId)) == NULL )
|
|
cmErrMsg(&p->err,kParmNotFoundPoRC,"No parameter definition was found for numeric id %i.",numId);
|
|
else
|
|
n = _cmPgmOptInstCount(r);
|
|
|
|
return n;
|
|
}
|
|
|
|
cmPoRC_t _cmPgmOptInstPtr( _cmPo_t* p, unsigned numId, unsigned instIdx, const _cmPoOpt_t** rpp, const _cmPoValue_t** vpp )
|
|
{
|
|
*rpp = NULL;
|
|
*vpp = NULL;
|
|
|
|
// locate the opt recd
|
|
if((*rpp = _cmPgmOptNumIdToOptRecd(p,numId)) == NULL )
|
|
return cmErrMsg(&p->err,kParmNotFoundPoRC,"No parameter definition was found for the numeric id %i.",numId);
|
|
|
|
const _cmPoArg_t* a = (*rpp)->inst;
|
|
unsigned i;
|
|
|
|
// locate the instance recd
|
|
for(i=0; i<instIdx && a != NULL; ++i)
|
|
a = a->inst;
|
|
|
|
// if the instance recd was not found
|
|
if( i != instIdx || a == NULL )
|
|
{
|
|
// if the instance index is 0 then and no instance recd exists then
|
|
// we will return the default value.
|
|
if( instIdx == 0 )
|
|
{
|
|
*vpp = &((*rpp)->dfltVal);
|
|
return kOkPoRC;
|
|
}
|
|
|
|
// otherwise signal an error
|
|
return cmErrMsg(&p->err,kInstNotFoundPoRC,"The instance index %i is not valid for parameter %s instance count %i.",instIdx,(*rpp)->wordId,i);
|
|
}
|
|
|
|
*vpp = &a->u;
|
|
|
|
return kOkPoRC;
|
|
}
|
|
|
|
char cmPgmOptArgChar( cmPgmOptH_t h, unsigned numId, unsigned instIdx )
|
|
{
|
|
const _cmPoOpt_t* rp = NULL;
|
|
const _cmPoValue_t* vp = NULL;
|
|
_cmPo_t* p = _cmPoHandleToPtr(h);
|
|
|
|
if(_cmPgmOptInstPtr(p,numId,instIdx,&rp,&vp) != kOkPoRC )
|
|
return 0;
|
|
|
|
if( cmIsFlag(rp->sflags,kCharPoFl) )
|
|
{
|
|
cmErrMsg(&p->err,kTypeErrPoRC,"The parameter '%s' is not a 'char'.",rp->wordId);
|
|
return 0;
|
|
}
|
|
|
|
return vp->c;
|
|
}
|
|
|
|
|
|
bool cmPgmOptArgBool( cmPgmOptH_t h, unsigned numId, unsigned instIdx )
|
|
{
|
|
const _cmPoOpt_t* rp = NULL;
|
|
const _cmPoValue_t* vp = NULL;
|
|
_cmPo_t* p = _cmPoHandleToPtr(h);
|
|
|
|
|
|
if(_cmPgmOptInstPtr(p,numId,instIdx,&rp,&vp) != kOkPoRC )
|
|
return 0;
|
|
|
|
// all types have a meaning in terms of bool
|
|
return vp->b;
|
|
}
|
|
|
|
int cmPgmOptArgInt( cmPgmOptH_t h, unsigned numId, unsigned instIdx )
|
|
{
|
|
cmPoRC_t rc;
|
|
const _cmPoOpt_t* rp = NULL;
|
|
const _cmPoValue_t* vp = NULL;
|
|
_cmPo_t* p = _cmPoHandleToPtr(h);
|
|
int v = 0;
|
|
|
|
if((rc = _cmPgmOptInstPtr(p,numId,instIdx,&rp,&vp)) != kOkPoRC )
|
|
return rc;
|
|
|
|
switch( rp->sflags & kTypeMaskPoFl )
|
|
{
|
|
case kFlagPoFl: v = vp->u; break;
|
|
case kBoolPoFl: v = vp->b; break;
|
|
case kCharPoFl: v = vp->c; break;
|
|
case kIntPoFl:
|
|
case kEnumPoFl: v = vp->i; break;
|
|
case kUIntPoFl:
|
|
case kDblPoFl: v = roundl(vp->d); break;
|
|
case kStrPoFl:
|
|
cmErrMsg(&p->err,kTypeErrPoRC,"The string parameter '%s' cannot be converted to an integer.",rp->wordId);
|
|
break;
|
|
default:
|
|
assert(0);
|
|
break;
|
|
}
|
|
|
|
return v;
|
|
}
|
|
|
|
unsigned cmPgmOptArgUInt( cmPgmOptH_t h, unsigned numId, unsigned instIdx )
|
|
{ return cmPgmOptArgInt(h,numId,instIdx); }
|
|
|
|
double cmPgmOptArgDbl( cmPgmOptH_t h, unsigned numId, unsigned instIdx )
|
|
{
|
|
cmPoRC_t rc;
|
|
const _cmPoOpt_t* rp = NULL;
|
|
const _cmPoValue_t* vp = NULL;
|
|
_cmPo_t* p = _cmPoHandleToPtr(h);
|
|
double v = 0;
|
|
|
|
if((rc = _cmPgmOptInstPtr(p,numId,instIdx,&rp,&vp)) != kOkPoRC )
|
|
return rc;
|
|
|
|
switch( rp->sflags & kTypeMaskPoFl )
|
|
{
|
|
case kFlagPoFl: v = vp->u; break;
|
|
case kBoolPoFl: v = vp->b; break;
|
|
case kCharPoFl: v = vp->c; break;
|
|
case kEnumPoFl:
|
|
case kIntPoFl: v = vp->i; break;
|
|
case kUIntPoFl: v = vp->u; break;
|
|
case kDblPoFl: v = vp->d; break;
|
|
case kStrPoFl:
|
|
cmErrMsg(&p->err,kTypeErrPoRC,"The string parameter '%s' cannot be converted to a double.",rp->wordId);
|
|
break;
|
|
default:
|
|
assert(0);
|
|
break;
|
|
}
|
|
|
|
return v;
|
|
}
|
|
|
|
const char* cmPgmOptArgStr( cmPgmOptH_t h, unsigned numId, unsigned instIdx )
|
|
{
|
|
cmPoRC_t rc;
|
|
const _cmPoOpt_t* rp = NULL;
|
|
const _cmPoValue_t* vp = NULL;
|
|
_cmPo_t* p = _cmPoHandleToPtr(h);
|
|
|
|
if((rc = _cmPgmOptInstPtr(p,numId,instIdx,&rp,&vp)) != kOkPoRC )
|
|
return NULL;
|
|
|
|
// if the requested param is a defined as a string
|
|
if( cmIsFlag(rp->sflags,kStrPoFl) )
|
|
return vp->s;
|
|
|
|
// otherwise the requested param is not defined as a string - so try to return the instance string value
|
|
const _cmPoArg_t* a = rp->inst;
|
|
unsigned i;
|
|
for(i=0; i<instIdx && a != NULL; ++i)
|
|
a = a->inst;
|
|
|
|
// if the index is not valid
|
|
if( i != instIdx )
|
|
{
|
|
cmErrMsg(&p->err,kInstNotFoundPoRC,"The instance index %i is not valid for parameter %s instance count %i.",instIdx,rp->wordId,i);
|
|
return NULL;
|
|
}
|
|
|
|
// otherwise return the instance string
|
|
return a->valStr;
|
|
}
|
|
|
|
cmPoRC_t cmPgmOptRC( cmPgmOptH_t h, cmPoRC_t rc )
|
|
{
|
|
_cmPo_t* p = _cmPoHandleToPtr(h);
|
|
return cmErrSetRC(&p->err,rc);
|
|
}
|
|
|
|
bool cmPgmOptHandleBuiltInActions( cmPgmOptH_t h, cmRpt_t* rpt )
|
|
{
|
|
_cmPo_t* p = _cmPoHandleToPtr(h);
|
|
_cmPoArg_t* a = p->args;
|
|
while( a != NULL )
|
|
{
|
|
|
|
switch( a->opt->numId )
|
|
{
|
|
case kPrintHelpPoId:
|
|
cmPgmOptPrintHelp(h,rpt);
|
|
break;
|
|
|
|
case kVersionPoId:
|
|
cmPgmOptPrintVersion(h,rpt);
|
|
break;
|
|
|
|
case kPrintParmsPoId:
|
|
cmPgmOptPrintParms(h,rpt);
|
|
break;
|
|
}
|
|
|
|
a = a->link;
|
|
}
|
|
|
|
return p->execFl;
|
|
}
|
|
|
|
void cmPgmOptPrintHelp( cmPgmOptH_t h, cmRpt_t* rpt )
|
|
{
|
|
_cmPo_t* p = _cmPoHandleToPtr(h);
|
|
const _cmPoOpt_t* r = p->list;
|
|
|
|
if( p->helpBegStr != NULL )
|
|
cmRptPrintf(rpt,"%s\n",p->helpBegStr);
|
|
|
|
for(; r != NULL; r=r->link )
|
|
{
|
|
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 )
|
|
cmRptPrintf(rpt," %s\n",r->helpStr);
|
|
|
|
}
|
|
|
|
|
|
if( p->helpEndStr != NULL )
|
|
cmRptPrintf(rpt,"\n%s\n",p->helpEndStr);
|
|
|
|
}
|
|
|
|
void cmPgmOptPrintVersion( cmPgmOptH_t h, cmRpt_t* rpt )
|
|
{
|
|
cmRptPrintf(rpt,"%s\n",PACKAGE_STRING); // PACKAGE_STRING is defined in config.h
|
|
}
|
|
|
|
|
|
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;
|
|
if( cmIsFlag(r->sflags,kEnumPoFl) )
|
|
{
|
|
if( r->enumPtr != NULL )
|
|
return false;
|
|
|
|
if((e = _cmPgmOptEnumIdToOptRecd(p,r->numId,v->u)) == NULL )
|
|
{
|
|
cmErrMsg(&p->err,kParmNotFoundPoRC,"The parm. defn. could not be found for numId=%i enumId=%i.",r->numId,v->u);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
cmRptPrintf(rpt,"-%c --%-20s %i ",e->charId,e->wordId, _cmPgmOptInstCount(r));
|
|
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 kCharPoFl: cmRptPrintf(rpt,"%c ", v->c); break;
|
|
case kIntPoFl: cmRptPrintf(rpt,r->cflags & kHexPoFl ? "0x%x ": "%i ", v->i); break;
|
|
case kUIntPoFl: cmRptPrintf(rpt,r->cflags & kHexPoFl ? "0x%x ": "%u ", v->u); break;
|
|
case kDblPoFl: cmRptPrintf(rpt,"%f ", v->d); break;
|
|
case kStrPoFl: cmRptPrintf(rpt,"%s ", v->s); break;
|
|
case kEnumPoFl: cmRptPrintf(rpt,"%i ", v->u); break;
|
|
default:
|
|
cmRptPrintf(rpt,"%s ",cmStringNullGuard(valStr)); break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void cmPgmOptPrintParms( cmPgmOptH_t h, cmRpt_t* rpt )
|
|
{
|
|
_cmPo_t* p = _cmPoHandleToPtr(h);
|
|
_cmPoArg_t* a = p->args;
|
|
|
|
// print the given arguments
|
|
while( a != NULL )
|
|
{
|
|
if(_cmPgmOptPrint(p, rpt, a->opt,&a->u,a->valStr))
|
|
cmRptPrintf(rpt,"\n");
|
|
|
|
a = a->link;
|
|
}
|
|
|
|
// print the default values
|
|
_cmPoOpt_t* r = p->list;
|
|
while( r != NULL )
|
|
{
|
|
if( r->inst == NULL )
|
|
{
|
|
if(_cmPgmOptPrint(p,rpt,r,&r->dfltVal,NULL))
|
|
cmRptPrintf(rpt,"\n");
|
|
}
|
|
r = r->link;
|
|
}
|
|
|
|
}
|