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 35KB

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