libcm is a C development framework with an emphasis on audio signal processing applications.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

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. }