libcm is a C development framework with an emphasis on audio signal processing applications.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cmPgmOpts.c 34KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337
  1. #include "cmGlobal.h"
  2. #include "cmRpt.h"
  3. #include "cmErr.h"
  4. #include "cmCtx.h"
  5. #include "cmMem.h"
  6. #include "cmMallocDebug.h"
  7. #include "cmLinkedHeap.h"
  8. #include "cmPgmOpts.h"
  9. #include "cmText.h"
  10. #include "config.h"
  11. enum {
  12. kFlagPoFl = 0x001,
  13. kBoolPoFl = 0x002, // this parameter does not take a value
  14. kCharPoFl = 0x004, // parm. value is a character
  15. kIntPoFl = 0x008, // parm. value is a decimal int
  16. kUIntPoFl = 0x010, // parm. value is a decimal unsigned int
  17. kDblPoFl = 0x040, // parm. value is a decimal double
  18. kStrPoFl = 0x080, // parm. value is a string (default)
  19. kEnumPoFl = 0x100, // parm. valus is a enum type (automatically set by a non-zero enumId)
  20. kTypeMaskPoFl = 0x1ff
  21. };
  22. cmPgmOptH_t cmPgmOptNullHandle = cmSTATIC_NULL_HANDLE;
  23. struct _cmPoArg_str;
  24. typedef union
  25. {
  26. bool b;
  27. char c;
  28. int i;
  29. unsigned u;
  30. double d;
  31. const cmChar_t* s;
  32. } _cmPoValue_t;
  33. typedef union
  34. {
  35. bool* b;
  36. char* c;
  37. int* i;
  38. unsigned* u;
  39. double* d;
  40. const cmChar_t** s;
  41. } _cmPoValPtr_t;
  42. // opt records describe the a given parameters configuration
  43. typedef struct _cmPoOpt_str
  44. {
  45. unsigned numId; //
  46. cmChar_t charId; //
  47. cmChar_t* wordId; //
  48. unsigned sflags; // state flags (type flags)
  49. unsigned cflags; // cfg flags (user settable cfg flag)
  50. unsigned enumId; // enumerated set element id (numId is the group id)
  51. 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)
  52. unsigned maxInstCnt; //
  53. _cmPoValue_t dfltVal; // default value for this parm
  54. _cmPoValPtr_t retVal; // client supplied variable which recieves the value of the last arg. parsed for this parm.
  55. cmChar_t* helpStr; //
  56. cmChar_t* mstrStr;
  57. struct _cmPoOpt_str* link; // link used by the _cmPo_t.list linked list
  58. struct _cmPoArg_str* inst; // arg's belonging to this opt record formed by _cmPoArg_t.inst links
  59. } _cmPoOpt_t;
  60. // arg records describe an instance of a given parameter.
  61. // (there may be multiple instances of a given parameter)
  62. typedef struct _cmPoArg_str
  63. {
  64. const _cmPoOpt_t* opt; // the opt record associated with this arg. instance
  65. struct _cmPoArg_str* link; // link used by the _cmPo_t.args list
  66. struct _cmPoArg_str* inst; // link used by the _cmPoOpt_t* inst list
  67. const cmChar_t* valStr; // string value for this arg.
  68. _cmPoValue_t u; // parsed value for this arg.
  69. } _cmPoArg_t;
  70. typedef struct
  71. {
  72. cmErr_t err;
  73. cmLHeapH_t lH;
  74. cmChar_t* helpBegStr;
  75. cmChar_t* helpEndStr;
  76. _cmPoOpt_t* list; // list of control records formed by _cmPoOpt_t.link links
  77. _cmPoArg_t* args; // list of arg. records formed by _cmPoArg_t.link links
  78. bool execFl; // set to false in cmPgmOptParse() if only built-in options were selected
  79. } _cmPo_t;
  80. typedef struct
  81. {
  82. unsigned id;
  83. const cmChar_t* label;
  84. } _cmPoMap_t;
  85. _cmPoMap_t _cmPoTypeMap[] =
  86. {
  87. { kFlagPoFl, "" },
  88. { kBoolPoFl, "" },
  89. { kCharPoFl, "<char>" },
  90. { kIntPoFl, "<int>" },
  91. { kUIntPoFl, "<uint>" },
  92. { kDblPoFl, "<real>" },
  93. { kStrPoFl, "<text>" },
  94. { kEnumPoFl, "<enum>" },
  95. { 0, "<unknown>"}
  96. };
  97. const cmChar_t* _cmPoTypeFlagToLabel( unsigned flag, unsigned cflags )
  98. {
  99. if( cmIsFlag(cflags,kHexPoFl) )
  100. return "<hex>";
  101. const _cmPoMap_t* m = _cmPoTypeMap;
  102. for(; m->id != 0; ++m)
  103. if( m->id == flag )
  104. break;
  105. return m->label;
  106. }
  107. bool _cmPoOptUsesValue( const _cmPoOpt_t* r )
  108. {
  109. return
  110. cmIsNotFlag(r->sflags,kEnumPoFl) &&
  111. cmIsNotFlag(r->sflags,kBoolPoFl) &&
  112. cmIsNotFlag(r->sflags,kFlagPoFl);
  113. }
  114. _cmPo_t* _cmPoHandleToPtr( cmPgmOptH_t h )
  115. {
  116. _cmPo_t* p = (_cmPo_t*)h.h;
  117. assert(p != NULL );
  118. return p;
  119. }
  120. cmPoRC_t _cmPgmOptFinalize( _cmPo_t* p )
  121. {
  122. cmPoRC_t rc = kOkPoRC;
  123. cmLHeapDestroy(&p->lH);
  124. cmMemPtrFree(&p);
  125. return rc;
  126. }
  127. bool cmPgmOptIsValid( cmPgmOptH_t h )
  128. { return h.h != NULL; }
  129. cmPoRC_t cmPgmOptInitialize(cmCtx_t* c, cmPgmOptH_t* hp, const cmChar_t* helpBegStr, const cmChar_t* helpEndStr )
  130. {
  131. cmPoRC_t rc;
  132. if((rc = cmPgmOptFinalize(hp)) != kOkPoRC )
  133. return rc;
  134. _cmPo_t* p = cmMemAllocZ(_cmPo_t,1);
  135. cmErrSetup(&p->err,&c->rpt,"Program Options");
  136. p->lH = cmLHeapCreate(2048,c);
  137. p->helpBegStr = helpBegStr==NULL ? NULL : cmLhAllocStr( p->lH, helpBegStr );
  138. p->helpEndStr = helpEndStr==NULL ? NULL : cmLhAllocStr( p->lH, helpEndStr );
  139. hp->h = p;
  140. return cmErrLastRC(&p->err);
  141. }
  142. cmPoRC_t cmPgmOptFinalize( cmPgmOptH_t* hp )
  143. {
  144. cmPoRC_t rc = kOkPoRC;
  145. if( hp == NULL || cmPgmOptIsValid(*hp) == false )
  146. return kOkPoRC;
  147. _cmPo_t* p = _cmPoHandleToPtr(*hp);
  148. if((rc = _cmPgmOptFinalize(p)) != kOkPoRC )
  149. return rc;
  150. hp->h = NULL;
  151. return rc;
  152. }
  153. _cmPoOpt_t* _cmPgmOptNumIdToOptRecd( _cmPo_t* p, unsigned numId )
  154. {
  155. _cmPoOpt_t* r = p->list;
  156. while( r != NULL )
  157. {
  158. if( r->numId == numId )
  159. {
  160. if( cmIsFlag(r->sflags,kEnumPoFl) && r->enumPtr!=NULL )
  161. r = r->enumPtr;
  162. return r;
  163. }
  164. r = r->link;
  165. }
  166. return NULL;
  167. }
  168. _cmPoOpt_t* _cmPgmOptEnumIdToOptRecd( _cmPo_t* p, unsigned numId, unsigned enumId )
  169. {
  170. _cmPoOpt_t* r = p->list;
  171. while( r != NULL )
  172. {
  173. if( r->numId == numId && r->enumId == enumId )
  174. return r;
  175. r = r->link;
  176. }
  177. return NULL;
  178. }
  179. _cmPoOpt_t* _cmPgmOptCharIdToOptRecd( _cmPo_t* p, cmChar_t charId )
  180. {
  181. _cmPoOpt_t* r = p->list;
  182. while( r != NULL )
  183. {
  184. if( r->charId == charId )
  185. return r;
  186. r = r->link;
  187. }
  188. return NULL;
  189. }
  190. _cmPoOpt_t* _cmPgmOptWordIdToOptRecd( _cmPo_t* p, const cmChar_t* wordId )
  191. {
  192. _cmPoOpt_t* r = p->list;
  193. while( r != NULL )
  194. {
  195. if( strcmp(wordId,r->wordId) == 0 )
  196. return r;
  197. r = r->link;
  198. }
  199. return NULL;
  200. }
  201. 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 )
  202. {
  203. // validate the num. id
  204. if( cmIsNotFlag(sflags,kEnumPoFl) && _cmPgmOptNumIdToOptRecd(p,numId) != NULL )
  205. return cmErrMsg(&p->err,kDuplicateIdPoRC,"The numeric id '%i' was already used by another parameter.",numId);
  206. // validate the char. id
  207. if(_cmPgmOptCharIdToOptRecd(p,charId) != NULL )
  208. return cmErrMsg(&p->err,kDuplicateIdPoRC,"The character id -'%c' was already used by another parameter.",charId);
  209. // validate the word. id
  210. if( _cmPgmOptWordIdToOptRecd(p,wordId) != NULL )
  211. return cmErrMsg(&p->err,kDuplicateIdPoRC,"The word id --'%s' was already used by another parameter.",wordId);
  212. // clear the kHexPoFl if this is not an int or uint.
  213. if( cmIsNotFlag(sflags,kFlagPoFl) && cmIsNotFlag(sflags,kIntPoFl) && cmIsNotFlag(sflags,kUIntPoFl) )
  214. cflags = cmClrFlag(cflags,kHexPoFl);
  215. // allocate the new parm recd
  216. _cmPoOpt_t* r = cmLhAllocZ( p->lH, _cmPoOpt_t, 1 );
  217. // if this is an enum type.
  218. if( cmIsFlag(sflags,kEnumPoFl) )
  219. {
  220. sflags = cmClrFlag(sflags,kTypeMaskPoFl) | kEnumPoFl;
  221. // set the master recd for this enum ptr
  222. _cmPoOpt_t* erp;
  223. if((erp = _cmPgmOptNumIdToOptRecd(p,numId)) != NULL )
  224. {
  225. r->enumPtr = erp->enumPtr==NULL ? erp : erp->enumPtr;
  226. // if this child enum has it's required flags set
  227. if( cmIsFlag(cflags,kReqPoFl) )
  228. {
  229. // then set the required flag in the parent and clear it in the child
  230. // (this way both the parent and child will not be required (which would be impossible for an enum))
  231. r->enumPtr->cflags = cmSetFlag(r->enumPtr->cflags,kReqPoFl);
  232. cflags = cmClrFlag(cflags,kReqPoFl);
  233. }
  234. }
  235. }
  236. r->cflags = cflags;
  237. r->sflags = sflags;
  238. r->numId = numId;
  239. r->charId = charId;
  240. r->wordId = cmLhAllocStr( p->lH, wordId );
  241. r->enumId = enumId;
  242. r->maxInstCnt = cnt;
  243. r->helpStr = helpStr==NULL ? NULL : cmLhAllocStr( p->lH, helpStr );
  244. _cmPoOpt_t* rp = p->list;
  245. while( rp != NULL && rp->link != NULL )
  246. rp = rp->link;
  247. if( rp == NULL )
  248. p->list = r;
  249. else
  250. rp->link = r;
  251. //r->link = p->list;
  252. //p->list = r;
  253. *rpp = r;
  254. return kOkPoRC;
  255. }
  256. 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 )
  257. {
  258. cmPoRC_t rc;
  259. _cmPoOpt_t* r = NULL;
  260. _cmPo_t* p = _cmPoHandleToPtr(h);
  261. if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kCharPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
  262. return rc;
  263. r->dfltVal.c = dfltVal;
  264. if( retValPtr != NULL )
  265. {
  266. r->retVal.c = retValPtr;
  267. *r->retVal.c = dfltVal;
  268. }
  269. return rc;
  270. }
  271. 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 )
  272. {
  273. cmPoRC_t rc;
  274. _cmPoOpt_t* r = NULL;
  275. _cmPo_t* p = _cmPoHandleToPtr(h);
  276. if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kBoolPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
  277. return rc;
  278. r->dfltVal.b = dfltVal;
  279. if( retValPtr != NULL )
  280. {
  281. r->retVal.b = retValPtr;
  282. *r->retVal.b = dfltVal;
  283. }
  284. return rc;
  285. }
  286. 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 )
  287. {
  288. cmPoRC_t rc;
  289. _cmPoOpt_t* r = NULL;
  290. _cmPo_t* p = _cmPoHandleToPtr(h);
  291. if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kIntPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
  292. return rc;
  293. r->dfltVal.i = dfltVal;
  294. if( retValPtr != NULL )
  295. {
  296. r->retVal.i = retValPtr;
  297. *r->retVal.i = dfltVal;
  298. }
  299. return rc;
  300. }
  301. 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 )
  302. {
  303. cmPoRC_t rc;
  304. _cmPoOpt_t* r = NULL;
  305. _cmPo_t* p = _cmPoHandleToPtr(h);
  306. if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kUIntPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
  307. return rc;
  308. r->dfltVal.u = dfltVal;
  309. if( retValPtr != NULL )
  310. {
  311. r->retVal.u = retValPtr;
  312. *r->retVal.u = dfltVal;
  313. }
  314. return rc;
  315. }
  316. 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 )
  317. {
  318. cmPoRC_t rc;
  319. _cmPoOpt_t* r = NULL;
  320. _cmPo_t* p = _cmPoHandleToPtr(h);
  321. if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kDblPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
  322. return rc;
  323. r->dfltVal.d = dfltVal;
  324. if( retValPtr != NULL )
  325. {
  326. r->retVal.d = retValPtr;
  327. *r->retVal.d = dfltVal;
  328. }
  329. return rc;
  330. }
  331. 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 )
  332. {
  333. cmPoRC_t rc;
  334. _cmPoOpt_t* r = NULL;
  335. _cmPo_t* p = _cmPoHandleToPtr(h);
  336. if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kStrPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
  337. return rc;
  338. r->dfltVal.s = dfltVal;
  339. if( retValPtr != NULL )
  340. {
  341. r->retVal.s = retValPtr;
  342. *r->retVal.s = dfltVal;
  343. }
  344. return rc;
  345. }
  346. 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 )
  347. {
  348. cmPoRC_t rc;
  349. _cmPoOpt_t* r = NULL;
  350. _cmPo_t* p = _cmPoHandleToPtr(h);
  351. if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kEnumPoFl, enumId, cnt, helpStr, &r )) != kOkPoRC )
  352. return rc;
  353. r->dfltVal.u = dfltVal;
  354. if( retValPtr != NULL )
  355. {
  356. r->retVal.u = retValPtr;
  357. *r->retVal.u = dfltVal;
  358. }
  359. if( mstrHelpStr != NULL )
  360. {
  361. _cmPoOpt_t* rp = r->enumPtr == NULL ? r : r->enumPtr;
  362. rp->mstrStr = cmLhAllocStr(p->lH,mstrHelpStr);
  363. }
  364. return rc;
  365. }
  366. 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 )
  367. {
  368. cmPoRC_t rc;
  369. _cmPoOpt_t* r = NULL;
  370. _cmPo_t* p = _cmPoHandleToPtr(h);
  371. if((rc= _cmPgmOptInstall(p, numId, charId, wordId, flags, kFlagPoFl, 0, cnt, helpStr, &r )) != kOkPoRC )
  372. return rc;
  373. r->dfltVal.u = dfltVal;
  374. if( retValPtr != NULL )
  375. {
  376. r->retVal.u = retValPtr;
  377. // Unlike other parameters we don't set the initial value of flag parameter
  378. // because we don't want to destroy any default flag that may be set there
  379. }
  380. return rc;
  381. }
  382. _cmPoArg_t* _cmPgmOptInsertArg( _cmPo_t* p, _cmPoOpt_t* r )
  383. {
  384. _cmPoArg_t* a = cmLhAllocZ(p->lH, _cmPoArg_t, 1);
  385. // if this is an enumerated type then switch to the master enum recd
  386. unsigned enumId = r->enumId;
  387. _cmPoOpt_t* e = r;
  388. if( r->enumPtr != NULL )
  389. r = r->enumPtr;
  390. a->opt = r;
  391. a->valStr = NULL;
  392. // link onto the end of the master arg list
  393. _cmPoArg_t* ap = p->args;
  394. while( ap!=NULL && ap->link != NULL )
  395. ap=ap->link;
  396. if( ap == NULL )
  397. p->args = a;
  398. else
  399. ap->link = a;
  400. // link onto the end of the opt recd list
  401. ap = r->inst;
  402. while( ap!=NULL && ap->inst!=NULL)
  403. ap=ap->inst;
  404. if( ap==NULL)
  405. r->inst = a;
  406. else
  407. ap->inst = a;
  408. // if no parm. type flag was given then the arg is implicitely a bool and the value is true.
  409. //if( (r->flags & kTypeMaskPoFl) == 0 )
  410. // a->u.b = true;
  411. // if this is an enumerated type
  412. if( cmIsFlag(r->sflags,kEnumPoFl) )
  413. {
  414. a->u.u = enumId;
  415. if( r->retVal.u != NULL )
  416. *r->retVal.u = enumId;
  417. if( e->retVal.u != NULL )
  418. *e->retVal.u = enumId;
  419. }
  420. // if this is a flag type
  421. if( cmIsFlag(r->sflags,kFlagPoFl) )
  422. {
  423. a->u.u = r->dfltVal.u;
  424. if( r->retVal.u != NULL )
  425. *r->retVal.u |= a->u.u;
  426. }
  427. return a;
  428. }
  429. cmPoRC_t _cmPgmOptParseBool(_cmPo_t* p, const cmChar_t* valStr, bool* retValPtr )
  430. {
  431. cmPoRC_t rc = kOkPoRC;
  432. unsigned n = strlen("false");
  433. char val[n+1];
  434. int i;
  435. for(i=0; i<n && valStr[i]; ++i)
  436. val[i] = tolower(valStr[i]);
  437. val[i] = 0;
  438. if( !strcmp(val,"0") || !strcmp(val,"false") || !strcmp(val,"f") )
  439. *retValPtr = false;
  440. else
  441. if( !strcmp(val,"1") || !strcmp(val,"true") || !strcmp(val,"t") )
  442. *retValPtr = true;
  443. else
  444. 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);
  445. return rc;
  446. }
  447. cmPoRC_t _cmPgmOptParseValue( _cmPo_t* p, _cmPoOpt_t* r, _cmPoArg_t* a, const cmChar_t* valStr )
  448. {
  449. cmPoRC_t rc = kOkPoRC;
  450. assert(a != NULL && valStr != NULL);
  451. a->valStr = valStr;
  452. errno = 0;
  453. switch( r->sflags & kTypeMaskPoFl )
  454. {
  455. // case kFlagPoFl:
  456. // enum values get set in _cmPgmOptInsertArg()
  457. case kBoolPoFl:
  458. //rc = _cmPgmOptParseBool(p,valStr,&a->u.b);
  459. a->u.b = true;
  460. if( r->retVal.b != NULL )
  461. *r->retVal.b = a->u.b;
  462. break;
  463. case kCharPoFl:
  464. a->u.c = valStr[0];
  465. if( r->retVal.c != NULL )
  466. *r->retVal.c = a->u.c;
  467. break;
  468. case kIntPoFl:
  469. a->u.i = strtol(valStr,NULL, cmIsFlag(r->cflags,kHexPoFl) ? 16 : 10);
  470. if( r->retVal.i != NULL )
  471. *r->retVal.i = a->u.i;
  472. break;
  473. case kUIntPoFl:
  474. a->u.u = strtol(valStr,NULL, cmIsFlag(r->cflags,kHexPoFl) ? 16 : 10);
  475. if( r->retVal.u != NULL )
  476. *r->retVal.u = a->u.u;
  477. break;
  478. // case kEnumPoFl:
  479. // enum values get set in _cmPgmOptInsertArg()
  480. case kDblPoFl:
  481. a->u.d = strtod(valStr,NULL);
  482. if( r->retVal.d != NULL )
  483. *r->retVal.d = a->u.d;
  484. break;
  485. case kStrPoFl:
  486. a->u.s = valStr;
  487. if( r->retVal.s != NULL )
  488. *r->retVal.s = a->u.s;
  489. break;
  490. default:
  491. { assert(0); }
  492. }
  493. if( errno != 0 )
  494. rc = cmErrMsg(&p->err,kParseFailPoRC,"The value '%s' for option '%s' could not be parsed.",valStr,r->wordId);
  495. return rc;
  496. }
  497. unsigned _cmPgmOptInstCount( const _cmPoOpt_t* r )
  498. {
  499. const _cmPoArg_t* a = r->inst;
  500. unsigned n = 0;
  501. while( a != NULL )
  502. {
  503. ++n;
  504. a = a->inst;
  505. }
  506. return n;
  507. }
  508. // check if any non-built-in options were provided
  509. // If only built in options were selected then no execution is assumed
  510. // and required arg's are not checked.
  511. bool _cmPgmOptCheckNoExec( _cmPo_t* p )
  512. {
  513. _cmPoArg_t* a = p->args;
  514. while( a != NULL )
  515. {
  516. if( a->opt->numId >= kBasePoId )
  517. return true;
  518. a = a->link;
  519. }
  520. return false;
  521. }
  522. cmPoRC_t _cmPgmOptMissingEnumError( _cmPo_t* p, _cmPoOpt_t* r )
  523. {
  524. _cmPoOpt_t* mstr = r->enumPtr==NULL ? r : r->enumPtr;
  525. _cmPoOpt_t* rp = p->list;
  526. cmChar_t* msg = cmTsPrintfP(NULL,"No argument was supplied for the required enumerated parameter containing the following set of possible flags: { ");
  527. for(; rp!=NULL; rp=rp->link)
  528. if( cmIsFlag(rp->sflags,kEnumPoFl) && (rp==mstr || rp->enumPtr==mstr) )
  529. {
  530. msg = cmTextAppendSS(msg,rp->wordId);
  531. msg = cmTextAppendSS(msg," ");
  532. }
  533. msg = cmTextAppendSS(msg,"}");
  534. cmPoRC_t rc = cmErrMsg(&p->err,kNoReqArgPoRC,msg);
  535. cmMemFree(msg);
  536. return rc;
  537. }
  538. // check that all required arg.s were actually given and that the actual
  539. // number of instances does not exceed the defined limit
  540. cmPoRC_t _cmPgmOptCheckReqArgs( _cmPo_t* p )
  541. {
  542. cmPoRC_t rc = kOkPoRC;
  543. _cmPoOpt_t* r = p->list;
  544. while( r != NULL )
  545. {
  546. if( cmIsFlag(r->cflags, kReqPoFl ) )
  547. {
  548. _cmPoArg_t* a = p->args;
  549. while( a != NULL )
  550. {
  551. if( a->opt == r )
  552. break;
  553. a = a->link;
  554. }
  555. if( a == NULL )
  556. {
  557. if( cmIsFlag(r->sflags, kEnumPoFl ) )
  558. rc = _cmPgmOptMissingEnumError(p,r);
  559. else
  560. rc = cmErrMsg(&p->err,kNoReqArgPoRC,"No argument was supplied for the required parameter '%s'.",r->wordId);
  561. }
  562. }
  563. unsigned cnt;
  564. if( r->maxInstCnt > 0 && r->maxInstCnt < (cnt=_cmPgmOptInstCount(r)) )
  565. rc = cmErrMsg(&p->err,kArgCntErrPoRC,"The parameter '%s' has %i instances which exceeds the defined limit of %i instances.",r->wordId,cnt,r->maxInstCnt);
  566. r = r->link;
  567. }
  568. return rc;
  569. }
  570. cmPoRC_t cmPgmOptParse( cmPgmOptH_t h, unsigned argCnt, char* argArray[] )
  571. {
  572. enum { kDash, kCharId, kWordId, kArgVal };
  573. cmPoRC_t rc = kOkPoRC;
  574. _cmPo_t* p = _cmPoHandleToPtr(h);
  575. unsigned state = kDash;
  576. _cmPoOpt_t* r = NULL;
  577. _cmPoArg_t* a = NULL;
  578. int i = 1; // arg index
  579. int j = 0; // arg label character index
  580. if( _cmPgmOptNumIdToOptRecd(p,kPrintHelpPoId) == NULL )
  581. cmPgmOptInstallBool(h, kPrintHelpPoId, 'h', "help", 0, false, NULL,0,"Print this usage information." );
  582. if( _cmPgmOptNumIdToOptRecd(p,kVersionPoId) == NULL )
  583. cmPgmOptInstallBool(h, kVersionPoId, 'v', "version", 0, false, NULL,0,"Print version information." );
  584. if( _cmPgmOptNumIdToOptRecd(p,kPrintParmsPoId) == NULL )
  585. cmPgmOptInstallBool(h, kPrintParmsPoId,'p', "parms", 0, false, NULL,0,"Print the arguments.");
  586. if((rc = cmErrLastRC(&p->err)) != kOkPoRC )
  587. return rc;
  588. while(i<argCnt)
  589. {
  590. const cmChar_t* valStr = NULL;
  591. switch(state)
  592. {
  593. case kDash:
  594. // this token must begin with a '-' character
  595. if( argArray[i][0] != '-')
  596. return cmErrMsg(&p->err,kSyntaxErrPoRC,"Syntax error. Expecting a '-'.");
  597. // if the second char. is also a '-' then this is a wordId
  598. if( argArray[i][1] == '-' )
  599. {
  600. state = kWordId;
  601. j = 2; // word id's always begin on the third token char
  602. }
  603. else // otherwise it is a charId
  604. {
  605. state = kCharId;
  606. j = 1; // char id's always begin on the second token char
  607. }
  608. r = NULL;
  609. break;
  610. case kCharId:
  611. // we complete our parsing of charId's only when we encounter a '\0'
  612. if( argArray[i][j] == '\0' )
  613. {
  614. ++i;
  615. state = kDash;
  616. r = NULL;
  617. a = NULL;
  618. }
  619. else
  620. {
  621. // get the opt recd assoc'd with the jth character in this charId
  622. if((r = _cmPgmOptCharIdToOptRecd(p,argArray[i][j])) == NULL )
  623. return cmErrMsg(&p->err,kSyntaxErrPoRC,"The program option selector char '%c' is not valid.",argArray[i][j]);
  624. // if this charId is not a flag,bool or enum then it must be followed by a value.
  625. if( _cmPoOptUsesValue(r) )
  626. ++i;
  627. else // otherwise process the next char id in this charId token
  628. ++j;
  629. }
  630. break;
  631. case kWordId:
  632. // get the wordId
  633. if((r = _cmPgmOptWordIdToOptRecd(p,argArray[i]+j)) == NULL )
  634. return cmErrMsg(&p->err,kSyntaxErrPoRC,"The program option selector word '%s' is not valid.",cmStringNullGuard(argArray[i]+j));
  635. ++i; // advance to the next token
  636. break;
  637. case kArgVal:
  638. assert(r != NULL );
  639. valStr = argArray[i];
  640. ++i;
  641. break;
  642. }
  643. // if a valid opt recd has been selected
  644. if( r != NULL )
  645. {
  646. // if the cur token reprsents a value ...
  647. if( state == kArgVal )
  648. {
  649. // ... then parse the value string
  650. if((rc = _cmPgmOptParseValue(p,r,a,valStr)) != kOkPoRC )
  651. goto errLabel;
  652. r = NULL;
  653. a = NULL;
  654. state = kDash; // value strings are always followed by char or word id's
  655. }
  656. else
  657. {
  658. // create an arg record for the cur char or word id.
  659. a = _cmPgmOptInsertArg(p, r );
  660. // and the value type is not 'flag','bool' or 'enum'
  661. if( _cmPoOptUsesValue(r) )
  662. state = kArgVal;
  663. switch(state)
  664. {
  665. case kDash: assert(i==argCnt); break;
  666. case kCharId: break;
  667. case kWordId: state = kDash; break;
  668. case kArgVal: break;
  669. default: assert(0); break;
  670. }
  671. }
  672. }
  673. }
  674. errLabel:
  675. // if no errors have occurred then check for missing parameters.
  676. if( rc == kOkPoRC )
  677. {
  678. if((p->execFl = _cmPgmOptCheckNoExec(p)) == true )
  679. rc = _cmPgmOptCheckReqArgs(p);
  680. }
  681. return rc;
  682. }
  683. unsigned cmPgmOptArgCount( cmPgmOptH_t h)
  684. {
  685. _cmPo_t* p = _cmPoHandleToPtr(h);
  686. const _cmPoArg_t* a = p->args;
  687. unsigned n = 0;
  688. while( a != NULL )
  689. {
  690. ++n;
  691. a = a->link;
  692. }
  693. return n;
  694. }
  695. cmPoRC_t _cmPgmOptIndexToPtr( _cmPo_t* p, unsigned idx, const _cmPoArg_t** app )
  696. {
  697. unsigned n = 0;
  698. const _cmPoArg_t* a = p->args;
  699. assert(app != NULL );
  700. *app = NULL;
  701. while( a != NULL && n < idx )
  702. {
  703. ++n;
  704. a = a->link;
  705. }
  706. if( n!=idx || a==NULL)
  707. return cmErrMsg(&p->err,kInvalidIdxPoRC,"The option index '%i' is not valid.",idx);
  708. *app = a;
  709. return kOkPoRC;
  710. }
  711. unsigned cmPgmOptNumId( cmPgmOptH_t h, unsigned argIdx )
  712. {
  713. const _cmPoArg_t* a = NULL;
  714. cmPoRC_t rc;
  715. if((rc = _cmPgmOptIndexToPtr(_cmPoHandleToPtr(h),argIdx,&a)) != kOkPoRC )
  716. return cmInvalidId;
  717. assert( a != NULL );
  718. return a->opt->numId;
  719. }
  720. unsigned cmPgmOptCharId( cmPgmOptH_t h, unsigned argIdx )
  721. {
  722. const _cmPoArg_t* a = NULL;
  723. cmPoRC_t rc;
  724. if((rc = _cmPgmOptIndexToPtr(_cmPoHandleToPtr(h),argIdx,&a)) != kOkPoRC )
  725. return cmInvalidId;
  726. assert(a != NULL );
  727. return a->opt->charId;
  728. }
  729. const cmChar_t* cmPgmOptWordId( cmPgmOptH_t h, unsigned argIdx )
  730. {
  731. const _cmPoArg_t* a = NULL;
  732. cmPoRC_t rc;
  733. if((rc = _cmPgmOptIndexToPtr(_cmPoHandleToPtr(h),argIdx,&a)) != kOkPoRC )
  734. return NULL;
  735. assert(a!=NULL);
  736. return a->opt->wordId;
  737. }
  738. cmPoRC_t _cmPgmOptArgPtr( _cmPo_t* p, unsigned argIdx, const _cmPoArg_t** app )
  739. {
  740. cmPoRC_t rc;
  741. if((rc = _cmPgmOptIndexToPtr(p,argIdx,app)) != kOkPoRC )
  742. {
  743. if( (*app)->valStr == NULL )
  744. return cmErrMsg(&p->err,kParseFailPoRC,"The parameter at index '%i' is not a value.",argIdx);
  745. }
  746. return rc;
  747. }
  748. char cmPgmOptParseArgChar( cmPgmOptH_t h, unsigned argIdx )
  749. {
  750. cmPoRC_t rc;
  751. const _cmPoArg_t* a;
  752. _cmPo_t* p = _cmPoHandleToPtr(h);
  753. if((rc = _cmPgmOptArgPtr(p,argIdx,&a)) != kOkPoRC )
  754. return 0;
  755. return a->valStr==NULL ? 0 : a->valStr[0];
  756. }
  757. bool cmPgmOptParseArgBool( cmPgmOptH_t h, unsigned argIdx )
  758. {
  759. cmPoRC_t rc;
  760. const _cmPoArg_t* a;
  761. _cmPo_t* p = _cmPoHandleToPtr(h);
  762. bool val = false;
  763. if((rc = _cmPgmOptArgPtr(p,argIdx,&a)) != kOkPoRC )
  764. return false;
  765. if( a->valStr != NULL )
  766. _cmPgmOptParseBool(p,a->valStr,&val);
  767. return val;
  768. }
  769. int cmPgmOptParseArgInt( cmPgmOptH_t h, unsigned argIdx )
  770. {
  771. cmPoRC_t rc;
  772. const _cmPoArg_t* a;
  773. _cmPo_t* p = _cmPoHandleToPtr(h);
  774. if((rc = _cmPgmOptArgPtr(p,argIdx,&a)) != kOkPoRC )
  775. return rc;
  776. errno = 0;
  777. int v = strtol(a->valStr,NULL,10);
  778. if( errno != 0 )
  779. cmErrMsg(&p->err,kParseFailPoRC,"The parameter '%s' could not be converted to an 'int'.",a->valStr);
  780. return v;
  781. }
  782. unsigned cmPgmOptParseArgUInt( cmPgmOptH_t h, unsigned argIdx )
  783. {
  784. cmPoRC_t rc;
  785. const _cmPoArg_t* a;
  786. _cmPo_t* p = _cmPoHandleToPtr(h);
  787. if((rc = _cmPgmOptArgPtr(p,argIdx,&a)) != kOkPoRC )
  788. return rc;
  789. errno = 0;
  790. unsigned v = strtol(a->valStr,NULL,10);
  791. if( errno != 0 )
  792. cmErrMsg(&p->err,kParseFailPoRC,"The parameter '%s' could not be converted to an 'unsigned int'.",a->valStr);
  793. return v;
  794. }
  795. double cmPgmOptParseArgDbl( cmPgmOptH_t h, unsigned argIdx )
  796. {
  797. cmPoRC_t rc;
  798. const _cmPoArg_t* a;
  799. _cmPo_t* p = _cmPoHandleToPtr(h);
  800. if((rc = _cmPgmOptArgPtr(p,argIdx,&a)) != kOkPoRC )
  801. return rc;
  802. errno = 0;
  803. double v = strtod(a->valStr,NULL);
  804. if( errno != 0 )
  805. cmErrMsg(&p->err,kParseFailPoRC,"The parameter '%s' could not be converted to a 'double'.",a->valStr);
  806. return v;
  807. }
  808. const char* cmPgmOptParseArgStr( cmPgmOptH_t h, unsigned argIdx )
  809. {
  810. cmPoRC_t rc;
  811. const _cmPoArg_t* a;
  812. _cmPo_t* p = _cmPoHandleToPtr(h);
  813. if((rc = _cmPgmOptArgPtr(p,argIdx,&a)) != kOkPoRC )
  814. return NULL;
  815. return a->valStr;
  816. }
  817. unsigned cmPgmOptParmArgCount( cmPgmOptH_t h, unsigned numId )
  818. {
  819. const _cmPoOpt_t* r;
  820. _cmPo_t* p = _cmPoHandleToPtr(h);
  821. unsigned n = 0;
  822. if((r = _cmPgmOptNumIdToOptRecd(p,numId)) == NULL )
  823. cmErrMsg(&p->err,kParmNotFoundPoRC,"No parameter definition was found for numeric id %i.",numId);
  824. else
  825. n = _cmPgmOptInstCount(r);
  826. return n;
  827. }
  828. cmPoRC_t _cmPgmOptInstPtr( _cmPo_t* p, unsigned numId, unsigned instIdx, const _cmPoOpt_t** rpp, const _cmPoValue_t** vpp )
  829. {
  830. *rpp = NULL;
  831. *vpp = NULL;
  832. // locate the opt recd
  833. if((*rpp = _cmPgmOptNumIdToOptRecd(p,numId)) == NULL )
  834. return cmErrMsg(&p->err,kParmNotFoundPoRC,"No parameter definition was found for the numeric id %i.",numId);
  835. const _cmPoArg_t* a = (*rpp)->inst;
  836. unsigned i;
  837. // locate the instance recd
  838. for(i=0; i<instIdx && a != NULL; ++i)
  839. a = a->inst;
  840. // if the instance recd was not found
  841. if( i != instIdx || a == NULL )
  842. {
  843. // if the instance index is 0 then and no instance recd exists then
  844. // we will return the default value.
  845. if( instIdx == 0 )
  846. {
  847. *vpp = &((*rpp)->dfltVal);
  848. return kOkPoRC;
  849. }
  850. // otherwise signal an error
  851. return cmErrMsg(&p->err,kInstNotFoundPoRC,"The instance index %i is not valid for parameter %s instance count %i.",instIdx,(*rpp)->wordId,i);
  852. }
  853. *vpp = &a->u;
  854. return kOkPoRC;
  855. }
  856. char cmPgmOptArgChar( cmPgmOptH_t h, unsigned numId, unsigned instIdx )
  857. {
  858. const _cmPoOpt_t* rp = NULL;
  859. const _cmPoValue_t* vp = NULL;
  860. _cmPo_t* p = _cmPoHandleToPtr(h);
  861. if(_cmPgmOptInstPtr(p,numId,instIdx,&rp,&vp) != kOkPoRC )
  862. return 0;
  863. if( cmIsFlag(rp->sflags,kCharPoFl) )
  864. {
  865. cmErrMsg(&p->err,kTypeErrPoRC,"The parameter '%s' is not a 'char'.",rp->wordId);
  866. return 0;
  867. }
  868. return vp->c;
  869. }
  870. bool cmPgmOptArgBool( cmPgmOptH_t h, unsigned numId, unsigned instIdx )
  871. {
  872. const _cmPoOpt_t* rp = NULL;
  873. const _cmPoValue_t* vp = NULL;
  874. _cmPo_t* p = _cmPoHandleToPtr(h);
  875. if(_cmPgmOptInstPtr(p,numId,instIdx,&rp,&vp) != kOkPoRC )
  876. return 0;
  877. // all types have a meaning in terms of bool
  878. return vp->b;
  879. }
  880. int cmPgmOptArgInt( cmPgmOptH_t h, unsigned numId, unsigned instIdx )
  881. {
  882. cmPoRC_t rc;
  883. const _cmPoOpt_t* rp = NULL;
  884. const _cmPoValue_t* vp = NULL;
  885. _cmPo_t* p = _cmPoHandleToPtr(h);
  886. int v = 0;
  887. if((rc = _cmPgmOptInstPtr(p,numId,instIdx,&rp,&vp)) != kOkPoRC )
  888. return rc;
  889. switch( rp->sflags & kTypeMaskPoFl )
  890. {
  891. case kFlagPoFl: v = vp->u; break;
  892. case kBoolPoFl: v = vp->b; break;
  893. case kCharPoFl: v = vp->c; break;
  894. case kIntPoFl:
  895. case kEnumPoFl: v = vp->i; break;
  896. case kUIntPoFl:
  897. case kDblPoFl: v = roundl(vp->d); break;
  898. case kStrPoFl:
  899. cmErrMsg(&p->err,kTypeErrPoRC,"The string parameter '%s' cannot be converted to an integer.",rp->wordId);
  900. break;
  901. default:
  902. assert(0);
  903. break;
  904. }
  905. return v;
  906. }
  907. unsigned cmPgmOptArgUInt( cmPgmOptH_t h, unsigned numId, unsigned instIdx )
  908. { return cmPgmOptArgInt(h,numId,instIdx); }
  909. double cmPgmOptArgDbl( cmPgmOptH_t h, unsigned numId, unsigned instIdx )
  910. {
  911. cmPoRC_t rc;
  912. const _cmPoOpt_t* rp = NULL;
  913. const _cmPoValue_t* vp = NULL;
  914. _cmPo_t* p = _cmPoHandleToPtr(h);
  915. double v = 0;
  916. if((rc = _cmPgmOptInstPtr(p,numId,instIdx,&rp,&vp)) != kOkPoRC )
  917. return rc;
  918. switch( rp->sflags & kTypeMaskPoFl )
  919. {
  920. case kFlagPoFl: v = vp->u; break;
  921. case kBoolPoFl: v = vp->b; break;
  922. case kCharPoFl: v = vp->c; break;
  923. case kEnumPoFl:
  924. case kIntPoFl: v = vp->i; break;
  925. case kUIntPoFl: v = vp->u; break;
  926. case kDblPoFl: v = vp->d; break;
  927. case kStrPoFl:
  928. cmErrMsg(&p->err,kTypeErrPoRC,"The string parameter '%s' cannot be converted to a double.",rp->wordId);
  929. break;
  930. default:
  931. assert(0);
  932. break;
  933. }
  934. return v;
  935. }
  936. const char* cmPgmOptArgStr( cmPgmOptH_t h, unsigned numId, unsigned instIdx )
  937. {
  938. cmPoRC_t rc;
  939. const _cmPoOpt_t* rp = NULL;
  940. const _cmPoValue_t* vp = NULL;
  941. _cmPo_t* p = _cmPoHandleToPtr(h);
  942. if((rc = _cmPgmOptInstPtr(p,numId,instIdx,&rp,&vp)) != kOkPoRC )
  943. return NULL;
  944. // if the requested param is a defined as a string
  945. if( cmIsFlag(rp->sflags,kStrPoFl) )
  946. return vp->s;
  947. // otherwise the requested param is not defined as a string - so try to return the instance string value
  948. const _cmPoArg_t* a = rp->inst;
  949. unsigned i;
  950. for(i=0; i<instIdx && a != NULL; ++i)
  951. a = a->inst;
  952. // if the index is not valid
  953. if( i != instIdx )
  954. {
  955. cmErrMsg(&p->err,kInstNotFoundPoRC,"The instance index %i is not valid for parameter %s instance count %i.",instIdx,rp->wordId,i);
  956. return NULL;
  957. }
  958. // otherwise return the instance string
  959. return a->valStr;
  960. }
  961. cmPoRC_t cmPgmOptRC( cmPgmOptH_t h, cmPoRC_t rc )
  962. {
  963. _cmPo_t* p = _cmPoHandleToPtr(h);
  964. return cmErrSetRC(&p->err,rc);
  965. }
  966. bool cmPgmOptHandleBuiltInActions( cmPgmOptH_t h, cmRpt_t* rpt )
  967. {
  968. _cmPo_t* p = _cmPoHandleToPtr(h);
  969. _cmPoArg_t* a = p->args;
  970. while( a != NULL )
  971. {
  972. switch( a->opt->numId )
  973. {
  974. case kPrintHelpPoId:
  975. cmPgmOptPrintHelp(h,rpt);
  976. break;
  977. case kVersionPoId:
  978. cmPgmOptPrintVersion(h,rpt);
  979. break;
  980. case kPrintParmsPoId:
  981. cmPgmOptPrintParms(h,rpt);
  982. break;
  983. }
  984. a = a->link;
  985. }
  986. return p->execFl;
  987. }
  988. void cmPgmOptPrintHelp( cmPgmOptH_t h, cmRpt_t* rpt )
  989. {
  990. _cmPo_t* p = _cmPoHandleToPtr(h);
  991. const _cmPoOpt_t* r = p->list;
  992. if( p->helpBegStr != NULL )
  993. cmRptPrintf(rpt,"%s\n",p->helpBegStr);
  994. for(; r != NULL; r=r->link )
  995. {
  996. const cmChar_t* reqStr = "(required)";
  997. const cmChar_t* valueTypeLabel = "";
  998. const cmChar_t* reqLabel = "";
  999. const cmChar_t* indentStr = "";
  1000. const _cmPoOpt_t* mstr = NULL;
  1001. if( cmIsFlag(r->sflags,kEnumPoFl) )
  1002. {
  1003. if( r->enumPtr == NULL )
  1004. mstr = r;
  1005. indentStr = " ";
  1006. }
  1007. if( _cmPoOptUsesValue(r) )
  1008. valueTypeLabel = _cmPoTypeFlagToLabel(r->sflags & kTypeMaskPoFl,r->cflags);
  1009. if( cmIsNotFlag(r->sflags,kEnumPoFl) && cmIsFlag(r->cflags,kReqPoFl) )
  1010. reqLabel = reqStr;
  1011. if( mstr != NULL )
  1012. cmRptPrintf(rpt,"Enumerated group: %s %s\n",mstr->mstrStr==NULL ? "" : mstr->mstrStr, cmIsFlag(mstr->cflags,kReqPoFl) ? reqStr : "" );
  1013. cmRptPrintf(rpt,"%s-%c --%s %s %s",indentStr,r->charId,r->wordId,valueTypeLabel,reqLabel);
  1014. if( r->helpStr != NULL )
  1015. cmRptPrintf(rpt," %s\n",r->helpStr);
  1016. }
  1017. if( p->helpEndStr != NULL )
  1018. cmRptPrintf(rpt,"\n%s\n",p->helpEndStr);
  1019. }
  1020. void cmPgmOptPrintVersion( cmPgmOptH_t h, cmRpt_t* rpt )
  1021. {
  1022. cmRptPrintf(rpt,"%s\n",PACKAGE_STRING); // PACKAGE_STRING is defined in config.h
  1023. }
  1024. bool _cmPgmOptPrint( _cmPo_t* p, cmRpt_t* rpt, const _cmPoOpt_t* r, const _cmPoValue_t* v, const cmChar_t* valStr )
  1025. {
  1026. const _cmPoOpt_t* e = r;
  1027. if( cmIsFlag(r->sflags,kEnumPoFl) )
  1028. {
  1029. if( r->enumPtr != NULL )
  1030. return false;
  1031. if((e = _cmPgmOptEnumIdToOptRecd(p,r->numId,v->u)) == NULL )
  1032. {
  1033. cmErrMsg(&p->err,kParmNotFoundPoRC,"The parm. defn. could not be found for numId=%i enumId=%i.",r->numId,v->u);
  1034. return false;
  1035. }
  1036. }
  1037. cmRptPrintf(rpt,"-%c --%-20s %i ",e->charId,e->wordId, _cmPgmOptInstCount(r));
  1038. switch(r->sflags & kTypeMaskPoFl)
  1039. {
  1040. case kFlagPoFl: cmRptPrintf(rpt,r->cflags & kHexPoFl ? "0x%x ": "%u ",v->u ); break;
  1041. case kBoolPoFl: cmRptPrintf(rpt,"%c ", v->b ? 'T' : 'F'); break;
  1042. case kCharPoFl: cmRptPrintf(rpt,"%c ", v->c); break;
  1043. case kIntPoFl: cmRptPrintf(rpt,r->cflags & kHexPoFl ? "0x%x ": "%i ", v->i); break;
  1044. case kUIntPoFl: cmRptPrintf(rpt,r->cflags & kHexPoFl ? "0x%x ": "%u ", v->u); break;
  1045. case kDblPoFl: cmRptPrintf(rpt,"%f ", v->d); break;
  1046. case kStrPoFl: cmRptPrintf(rpt,"%s ", v->s); break;
  1047. case kEnumPoFl: cmRptPrintf(rpt,"%i ", v->u); break;
  1048. default:
  1049. cmRptPrintf(rpt,"%s ",cmStringNullGuard(valStr)); break;
  1050. }
  1051. return true;
  1052. }
  1053. void cmPgmOptPrintParms( cmPgmOptH_t h, cmRpt_t* rpt )
  1054. {
  1055. _cmPo_t* p = _cmPoHandleToPtr(h);
  1056. _cmPoArg_t* a = p->args;
  1057. // print the given arguments
  1058. while( a != NULL )
  1059. {
  1060. if(_cmPgmOptPrint(p, rpt, a->opt,&a->u,a->valStr))
  1061. cmRptPrintf(rpt,"\n");
  1062. a = a->link;
  1063. }
  1064. // print the default values
  1065. _cmPoOpt_t* r = p->list;
  1066. while( r != NULL )
  1067. {
  1068. if( r->inst == NULL )
  1069. {
  1070. if(_cmPgmOptPrint(p,rpt,r,&r->dfltVal,NULL))
  1071. cmRptPrintf(rpt,"\n");
  1072. }
  1073. r = r->link;
  1074. }
  1075. }