libcm is a C development framework with an emphasis on audio signal processing applications.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

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