ogetoptv.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. /*====================================================================*
  2. *
  3. * ogetoptv.cpp - ogetoptv class definition;
  4. *
  5. * this is a posix compliant getoptv() function that supports absolutely
  6. * no extensions; visit the posix webpage that specifies this function
  7. * to learn more;
  8. *
  9. * <http://www.opengroup.org/onlinepubs/007904975/functions/getoptv.html>
  10. *
  11. * we implemented this function to make console programs for windows and
  12. * debian linux act the same; microsoft c++ would not compile the debian
  13. * version of getoptv and after trying to fix it we decided to start over;
  14. *
  15. * this function conforms to posix standard in that it does not support
  16. * gnu style extensions such as "--option" for arguments or "ab::c" for
  17. * options strings; if you don't know what that means then you probably
  18. * won't care either; you should not implement these extentions, anyway;
  19. *
  20. * the posix standard says that command line options and their operands
  21. * must precede all other arguments; we find this restrictive and allow
  22. * option arguments to appear anywhere; this implementation re-arranges
  23. * a non-compliant argv[] to be posix compliant on completion;
  24. *
  25. * we have defined characters, instead of coding them, so that microsoft
  26. * folks can change '-' to '/' but preserve the posix behaviour;
  27. *
  28. * this implementation calls no functions and so there should not be any
  29. * problem with external declarations; a posix compliant unistd.h should
  30. * be enough; or use our getoptv.h as an alternative; or you can add the
  31. * following declarations in a header file, somwhere:
  32. *
  33. * extern char *optarg;
  34. * extern int optopt;
  35. * extern int optind;
  36. * extern int opterr;
  37. *
  38. * this implementation resets when you call it with optind=0 or optind=1;
  39. * the 0 is gnu/debian compliant and the 1 is posix compliant; after that
  40. * it runs to completion, unless you reset optind;
  41. *
  42. * the posix site does an excellent job of defining function behaviour and
  43. * illustrating its use; if you have questions, see them; you can also cut
  44. * and paste this c language code segment to get you started;
  45. *
  46. * static char const *optv [] =
  47. * {
  48. * ":ab:c"
  49. * "command line argument description",
  50. * "ogetoptv object demonstration program",
  51. * "a\toption needing no operand",
  52. * "b s\toption needing an operand (s)",
  53. * "c\toption needing no operand",
  54. * (char const *) (0)
  55. * };
  56. * ogetoptv options;
  57. * signed c;
  58. * options.optind(1).opterr(1);
  59. * while ((c = options.getoptv(argc, argv, optv)) != -1)
  60. * {
  61. * switch(c)
  62. * {
  63. * case 'a': // optopt is 'a'
  64. * case 'b': // optopt is 'b'; optarg is string;
  65. * case ':': // optopt is legal but no operand so optarg is null;
  66. * case '?': // optopt is illegal and optarg is null;
  67. * default: // valid options having no 'case' code;
  68. * }
  69. * }
  70. *
  71. * while (options.optind < argc)
  72. * {
  73. * // do stuff to argv[options.optind++].
  74. * }
  75. *
  76. * Motley Tools by Charles Maier <cmaier@cmassoc.net>;
  77. * Copyright 2001-2006 by Charles Maier Associates;
  78. * Licensed under the Internet Software Consortium License;
  79. *
  80. *--------------------------------------------------------------------*/
  81. #ifndef oGETOPTV_SOURCE
  82. #define oGETOPTV_SOURCE
  83. /*====================================================================*
  84. * custom header files;
  85. *--------------------------------------------------------------------*/
  86. #include <iostream>
  87. #include <cstring>
  88. #include <cstdlib>
  89. /*====================================================================*
  90. * custom source files;
  91. *--------------------------------------------------------------------*/
  92. #include "../classes/ogetoptv.hpp"
  93. #include "../classes/oputoptv.hpp"
  94. #include "../classes/oversion.hpp"
  95. /*====================================================================*
  96. * application variables;
  97. *--------------------------------------------------------------------*/
  98. char const * program_name = "unamed program";
  99. /*====================================================================*
  100. *
  101. * signed opterr() const;
  102. *
  103. * return the error message flag state;
  104. *
  105. *--------------------------------------------------------------------*/
  106. signed ogetoptv::opterr () const
  107. {
  108. return (this->mopterr);
  109. }
  110. /*====================================================================*
  111. *
  112. * ogetoptv & opterr(signed opterr);
  113. *
  114. * set the error message flag state;
  115. *
  116. *--------------------------------------------------------------------*/
  117. ogetoptv & ogetoptv::opterr (signed opterr)
  118. {
  119. this->mopterr = opterr;
  120. return (*this);
  121. }
  122. /*====================================================================*
  123. *
  124. * signed optmin () const;
  125. *
  126. * return the minimum argument flag state;
  127. *
  128. *--------------------------------------------------------------------*/
  129. signed ogetoptv::optmin () const
  130. {
  131. return (this->moptmin);
  132. }
  133. /*====================================================================*
  134. *
  135. * ogetoptv & optmin (signed optmin);
  136. *
  137. * set the minimum argument flag state;
  138. *
  139. *--------------------------------------------------------------------*/
  140. ogetoptv & ogetoptv::optmin (signed optmin)
  141. {
  142. this->moptmin = optmin;
  143. return (*this);
  144. }
  145. /*====================================================================*
  146. *
  147. * signed optind() const;
  148. *
  149. * return the index of the next argv[] string; this index defines the
  150. * start address for the remainder of argument vector argv[];
  151. *
  152. *--------------------------------------------------------------------*/
  153. signed ogetoptv::optind () const
  154. {
  155. return (this->moptind);
  156. }
  157. /*====================================================================*
  158. *
  159. * ogetoptv & optind(signed optind);
  160. *
  161. * set the index of the next argv[] string;
  162. *
  163. *--------------------------------------------------------------------*/
  164. ogetoptv & ogetoptv::optind (signed optind)
  165. {
  166. this->moptind = optind;
  167. return (*this);
  168. }
  169. /*====================================================================*
  170. *
  171. * signed optopt() const;
  172. *
  173. * return the value of the option character;
  174. *
  175. *--------------------------------------------------------------------*/
  176. signed ogetoptv::optopt () const
  177. {
  178. return (this->moptopt);
  179. }
  180. /*====================================================================*
  181. *
  182. * char const * optarg() const;
  183. *
  184. * return a pointer to the option string;
  185. *
  186. *--------------------------------------------------------------------*/
  187. char const *ogetoptv::optarg () const
  188. {
  189. return (this->moptarg);
  190. }
  191. /*====================================================================*
  192. *
  193. * signed argc () const;
  194. *
  195. * return the number of arguments left in argv; it is computed by
  196. * subtracting member mpotind from member margc; it can eliminate
  197. * the need for the customary "argc-=optind" statement;
  198. *
  199. *--------------------------------------------------------------------*/
  200. signed ogetoptv::argc () const
  201. {
  202. return (this->margc - this->moptind);
  203. }
  204. /*====================================================================*
  205. *
  206. * char const ** argv () const;
  207. *
  208. * return the start address of the unprocessed portions of argv [];
  209. *
  210. *--------------------------------------------------------------------*/
  211. char const ** ogetoptv::argv () const
  212. {
  213. return (this->margv + this->moptind);
  214. }
  215. /*====================================================================*
  216. *
  217. * char const * args () const;
  218. *
  219. * return option argument string address;
  220. *
  221. *--------------------------------------------------------------------*/
  222. char const * ogetoptv::args ()
  223. {
  224. return (this->moptarg);
  225. }
  226. /*====================================================================*
  227. *
  228. * signed operator++ (signed);
  229. *
  230. * return the value of member moptind and increment optind if less
  231. * than margc; this is not a posix feature; it is an extension;
  232. *
  233. *--------------------------------------------------------------------*/
  234. signed ogetoptv::operator++ (signed)
  235. {
  236. return (this->moptind < this->margc? this->moptind++: this->moptind);
  237. }
  238. /*====================================================================*
  239. *
  240. * signed getoptv (int argc, char const * argv[], char const * optv []);
  241. *
  242. *--------------------------------------------------------------------*/
  243. signed ogetoptv::getoptv (int argc, char const * argv [], char const * optv [])
  244. {
  245. extern char const * program_name;
  246. if ((this->moptind == 0) || (this->moptind == 1))
  247. {
  248. this->margc = argc;
  249. this->margv = argv;
  250. for (program_name = this->mstring = *this->margv; *this->mstring; this->mstring++)
  251. {
  252. if ((*this->mstring == '/') || (*this->mstring == '\\'))
  253. {
  254. program_name = this->mstring + 1;
  255. }
  256. }
  257. this->mstring = (char *) (0);
  258. if (this->margc == this->moptmin)
  259. {
  260. oputoptv::print (optv);
  261. std::exit (0);
  262. }
  263. this->mcount = this->moptind = 1;
  264. }
  265. while ((this->mcount < this->margc) || (this->mstring))
  266. {
  267. if (this->mstring)
  268. {
  269. if (*this->mstring)
  270. {
  271. this->moptopt = *this->mstring++;
  272. this->moptarg = (char *)(0);
  273. for (char const *option = optv [oPUTOPTV_I_OPTIONS]; *option != (char) (0); option++)
  274. {
  275. if (this->moptopt == oGETOPTV_C_OPERAND)
  276. {
  277. continue;
  278. }
  279. if (*option == oGETOPTV_C_OPERAND)
  280. {
  281. continue;
  282. }
  283. if (*option == this->moptopt)
  284. {
  285. if (*++option != oGETOPTV_C_OPERAND)
  286. {
  287. return (this->moptopt);
  288. }
  289. if (*this->mstring)
  290. {
  291. this->moptarg = this->mstring;
  292. this->mstring = (char *) (0);
  293. return (this->moptopt);
  294. }
  295. if (this->mcount < this->margc)
  296. {
  297. this->moptarg = argv [this->mcount];
  298. for (this->mindex = this->mcount++; this->mindex > this->moptind; --this->mindex)
  299. {
  300. argv [this->mindex] = argv [this->mindex - 1];
  301. }
  302. argv [this->moptind++] = this->moptarg;
  303. return (this->moptopt);
  304. }
  305. if (this->mopterr)
  306. {
  307. std::cerr << program_name << ": option '" << (char) (this->moptopt) << "' has no operand" << std::endl;
  308. std::exit (this->mopterr);
  309. }
  310. if (*optv [oPUTOPTV_I_OPTIONS] == oGETOPTV_C_OPERAND)
  311. {
  312. return (oGETOPTV_C_OPERAND);
  313. }
  314. return (oGETOPTV_C_ILLEGAL);
  315. }
  316. }
  317. if (this->mopterr)
  318. {
  319. std::cerr << program_name << ": option '" << (char) (this->moptopt) << "' has no meaning" << std::endl;
  320. std::exit (this->mopterr);
  321. }
  322. return (oGETOPTV_C_ILLEGAL);
  323. }
  324. this->mstring = (char *) (0);
  325. }
  326. if (this->mcount < this->margc)
  327. {
  328. this->mstring = this->margv [this->mcount];
  329. if (*this->mstring == oGETOPTV_C_OPTIONS)
  330. {
  331. for (this->mindex = this->mcount; this->mindex > this->moptind; --this->mindex)
  332. {
  333. this->margv [this->mindex] = this->margv [this->mindex - 1];
  334. }
  335. this->margv [this->moptind++] = this->mstring++;
  336. if (*this->mstring == oGETOPTV_C_OPTIONS)
  337. {
  338. this->mstring++;
  339. if (std::strcmp (this->mstring, "version") == 0)
  340. {
  341. oversion::print ();
  342. std::exit (0);
  343. }
  344. if (std::strcmp (this->mstring, "help") == 0)
  345. {
  346. oputoptv::print (optv);
  347. std::exit (0);
  348. }
  349. if (*this->mstring)
  350. {
  351. this->moptarg = (char *) (0);
  352. this->moptopt = (char) (0);
  353. return (-1);
  354. }
  355. this->mstring = (char *) (0);
  356. continue;
  357. }
  358. if (*this->mstring == oGETOPTV_C_VERSION)
  359. {
  360. oversion::print ();
  361. std::exit (0);
  362. }
  363. if (*this->mstring == oGETOPTV_C_SUMMARY)
  364. {
  365. oputoptv::print (optv);
  366. std::exit (0);
  367. }
  368. }
  369. else
  370. {
  371. this->mstring = (char *) (0);
  372. }
  373. this->mcount++;
  374. }
  375. }
  376. this->moptarg = (char *) (0);
  377. this->moptopt = (char) (0);
  378. return (-1);
  379. }
  380. /*====================================================================*
  381. *
  382. * ogetoptv ();
  383. *
  384. *--------------------------------------------------------------------*/
  385. ogetoptv::ogetoptv ()
  386. {
  387. this->margs = new char [1];
  388. this->margs [0] = (char) (0);
  389. this->moptarg = (char *) (0);
  390. this->moptopt = (char) (0);
  391. this->mopterr = 1;
  392. this->moptind = 1;
  393. this->moptmin = 0;
  394. return;
  395. }
  396. /*====================================================================*
  397. *
  398. * ~ogetoptv ();
  399. *
  400. *--------------------------------------------------------------------*/
  401. ogetoptv::~ogetoptv ()
  402. {
  403. delete [] this->margs;
  404. this->moptarg = (char *) (0);
  405. this->moptopt = (char) (0);
  406. return;
  407. }
  408. /*====================================================================*
  409. * end definition;
  410. *--------------------------------------------------------------------*/
  411. #endif