programBase.cxx 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466
  1. // Filename: programBase.cxx
  2. // Created by: drose (13Feb00)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) Carnegie Mellon University. All rights reserved.
  8. //
  9. // All use of this software is subject to the terms of the revised BSD
  10. // license. You should have received a copy of this license along
  11. // with this source code in a file named "LICENSE."
  12. //
  13. ////////////////////////////////////////////////////////////////////
  14. #include "programBase.h"
  15. #include "wordWrapStream.h"
  16. #include "pnmFileTypeRegistry.h"
  17. #include "indent.h"
  18. #include "dSearchPath.h"
  19. #include "coordinateSystem.h"
  20. #include "dconfig.h"
  21. #include "config_dconfig.h"
  22. #include "string_utils.h"
  23. #include "vector_string.h"
  24. #include "configVariableInt.h"
  25. #include "configVariableBool.h"
  26. #include "panda_getopt_long.h"
  27. #include "preprocess_argv.h"
  28. #include <stdlib.h>
  29. #include <algorithm>
  30. #include <ctype.h>
  31. // This manifest is defined if we are running on a system (e.g. most
  32. // any Unix) that allows us to determine the width of the terminal
  33. // screen via an ioctl() call. It's just handy to know for formatting
  34. // output nicely for the user.
  35. #ifdef IOCTL_TERMINAL_WIDTH
  36. #include <termios.h>
  37. #ifndef TIOCGWINSZ
  38. #include <sys/ioctl.h>
  39. #elif __APPLE__
  40. #include <sys/ioctl.h>
  41. #endif // TIOCGWINSZ
  42. #endif // IOCTL_TERMINAL_WIDTH
  43. bool ProgramBase::SortOptionsByIndex::
  44. operator () (const Option *a, const Option *b) const {
  45. if (a->_index_group != b->_index_group) {
  46. return a->_index_group < b->_index_group;
  47. }
  48. return a->_sequence < b->_sequence;
  49. }
  50. // This should be called at program termination just to make sure
  51. // Notify gets properly flushed before we exit, if someone calls
  52. // exit(). It's probably not necessary, but why not be phobic about
  53. // it?
  54. static void flush_nout() {
  55. nout << flush;
  56. }
  57. static ConfigVariableInt default_terminal_width
  58. ("default-terminal-width", 72,
  59. PRC_DESC("Specify the column at which to wrap output lines "
  60. "from pandatool-based programs, if it cannot be determined "
  61. "automatically."));
  62. static ConfigVariableBool use_terminal_width
  63. ("use-terminal-width", true,
  64. PRC_DESC("True to try to determine the terminal width automatically from "
  65. "the operating system, if supported; false to use the width "
  66. "specified by default-terminal-width even if the operating system "
  67. "appears to report a valid width."));
  68. ////////////////////////////////////////////////////////////////////
  69. // Function: ProgramBase::Constructor
  70. // Access: Public
  71. // Description:
  72. ////////////////////////////////////////////////////////////////////
  73. ProgramBase::
  74. ProgramBase() {
  75. // Set up Notify to write output to our own formatted stream.
  76. Notify::ptr()->set_ostream_ptr(new WordWrapStream(this), true);
  77. // And we'll want to be sure to flush that in all normal exit cases.
  78. atexit(&flush_nout);
  79. _path_replace = new PathReplace;
  80. // If a program never adds the path store options, the default path
  81. // store is PS_absolute. This is the most robust solution for
  82. // programs that read files but do not need to write them.
  83. _path_replace->_path_store = PS_absolute;
  84. _got_path_store = false;
  85. _got_path_directory = false;
  86. _next_sequence = 0;
  87. _sorted_options = false;
  88. _last_newline = false;
  89. _got_terminal_width = false;
  90. _got_option_indent = false;
  91. add_option("h", "", 100,
  92. "Display this help page.",
  93. &ProgramBase::handle_help_option, NULL, (void *)this);
  94. // It's nice to start with a blank line.
  95. nout << "\r";
  96. }
  97. ////////////////////////////////////////////////////////////////////
  98. // Function: ProgramBase::Destructor
  99. // Access: Public, Virtual
  100. // Description:
  101. ////////////////////////////////////////////////////////////////////
  102. ProgramBase::
  103. ~ProgramBase() {
  104. // Reset Notify in case any messages get sent after our
  105. // destruction--our stream is no longer valid.
  106. Notify::ptr()->set_ostream_ptr(NULL, false);
  107. }
  108. ////////////////////////////////////////////////////////////////////
  109. // Function: ProgramBase::show_description
  110. // Access: Public
  111. // Description: Writes the program description to stderr.
  112. ////////////////////////////////////////////////////////////////////
  113. void ProgramBase::
  114. show_description() {
  115. nout << _description << "\n";
  116. }
  117. ////////////////////////////////////////////////////////////////////
  118. // Function: ProgramBase::show_usage
  119. // Access: Public
  120. // Description: Writes the usage line(s) to stderr.
  121. ////////////////////////////////////////////////////////////////////
  122. void ProgramBase::
  123. show_usage() {
  124. nout << "\rUsage:\n";
  125. Runlines::const_iterator ri;
  126. string prog = " " +_program_name.get_basename_wo_extension();
  127. for (ri = _runlines.begin(); ri != _runlines.end(); ++ri) {
  128. show_text(prog, prog.length() + 1, *ri);
  129. }
  130. nout << "\r";
  131. }
  132. ////////////////////////////////////////////////////////////////////
  133. // Function: ProgramBase::show_options
  134. // Access: Public
  135. // Description: Describes each of the available options to stderr.
  136. ////////////////////////////////////////////////////////////////////
  137. void ProgramBase::
  138. show_options() {
  139. sort_options();
  140. if (!_got_option_indent) {
  141. get_terminal_width();
  142. _option_indent = min(15, (int)(_terminal_width * 0.25));
  143. _got_option_indent = true;
  144. }
  145. nout << "Options:\n";
  146. OptionsByIndex::const_iterator oi;
  147. for (oi = _options_by_index.begin(); oi != _options_by_index.end(); ++oi) {
  148. const Option &opt = *(*oi);
  149. string prefix = " -" + opt._option + " " + opt._parm_name;
  150. show_text(prefix, _option_indent, opt._description + "\r");
  151. }
  152. }
  153. ////////////////////////////////////////////////////////////////////
  154. // Function: ProgramBase::show_text
  155. // Access: Public
  156. // Description: Formats the indicated text and its prefix for output
  157. // to stderr with the known _terminal_width.
  158. ////////////////////////////////////////////////////////////////////
  159. void ProgramBase::
  160. show_text(const string &prefix, int indent_width, string text) {
  161. get_terminal_width();
  162. // This is correct! It goes go to cerr, not to nout. Sending it to
  163. // nout would be cyclic, since nout is redefined to map back through
  164. // this function.
  165. format_text(cerr, _last_newline,
  166. prefix, indent_width, text, _terminal_width);
  167. }
  168. ////////////////////////////////////////////////////////////////////
  169. // Function: ProgramBase::parse_command_line
  170. // Access: Public, Virtual
  171. // Description: Dispatches on each of the options on the command
  172. // line, and passes the remaining parameters to
  173. // handle_args(). If an error on the command line is
  174. // detected, will automatically call show_usage() and
  175. // exit(1).
  176. ////////////////////////////////////////////////////////////////////
  177. void ProgramBase::
  178. parse_command_line(int argc, char **argv) {
  179. preprocess_argv(argc, argv);
  180. // Setting this variable to zero reinitializes the options parser
  181. // This is only necessary for processing multiple command lines in
  182. // the same program (mainly the MaxToEgg converter plugin)
  183. extern int optind;
  184. optind = 0;
  185. _program_name = Filename::from_os_specific(argv[0]);
  186. int i;
  187. for (i = 1; i < argc; i++) {
  188. _program_args.push_back(argv[i]);
  189. }
  190. // Build up the long options list and the short options string for
  191. // getopt_long_only().
  192. pvector<struct option> long_options;
  193. string short_options;
  194. // We also need to build a temporary map of int index numbers to
  195. // Option pointers. We'll pass these index numbers to GNU's
  196. // getopt_long() so we can tell one option from another.
  197. typedef pmap<int, const Option *> Options;
  198. Options options;
  199. OptionsByName::const_iterator oi;
  200. int next_index = 256;
  201. // Let's prefix the option string with "-" to tell getopt that we
  202. // want it to tell us the post-option arguments, instead of trying
  203. // to meddle with ARGC and ARGV (which we aren't using directly).
  204. short_options = "-";
  205. for (oi = _options_by_name.begin(); oi != _options_by_name.end(); ++oi) {
  206. const Option &opt = (*oi).second;
  207. int index;
  208. if (opt._option.length() == 1) {
  209. // This is a "short" option; its option string consists of only
  210. // one letter. Its index is the letter itself.
  211. index = (int)opt._option[0];
  212. short_options += opt._option;
  213. if (!opt._parm_name.empty()) {
  214. // This option takes an argument.
  215. short_options += ':';
  216. }
  217. } else {
  218. // This is a "long" option; we'll assign it the next available
  219. // index.
  220. index = ++next_index;
  221. }
  222. // Now add it to the GNU data structures.
  223. struct option gopt;
  224. gopt.name = (char *)opt._option.c_str();
  225. gopt.has_arg = (opt._parm_name.empty()) ?
  226. no_argument : required_argument;
  227. gopt.flag = (int *)NULL;
  228. // Return an index into the _options_by_index array, offset by 256
  229. // so we don't confuse it with '?'.
  230. gopt.val = index;
  231. long_options.push_back(gopt);
  232. options[index] = &opt;
  233. }
  234. // Finally, add one more structure, all zeroes, to indicate the end
  235. // of the options.
  236. struct option gopt;
  237. memset(&gopt, 0, sizeof(gopt));
  238. long_options.push_back(gopt);
  239. // We'll use this vector to save the non-option arguments.
  240. // Generally, these will all be at the end, but with the GNU
  241. // extensions, they need not be.
  242. Args remaining_args;
  243. // Now call getopt_long() to actually parse the arguments.
  244. extern char *optarg;
  245. const struct option *long_opts = &long_options[0];
  246. int flag =
  247. getopt_long_only(argc, argv, short_options.c_str(), long_opts, NULL);
  248. while (flag != EOF) {
  249. string arg;
  250. if (optarg != NULL) {
  251. arg = optarg;
  252. }
  253. switch (flag) {
  254. case '?':
  255. // Invalid option or parameter.
  256. show_usage();
  257. exit(1);
  258. case '\x1':
  259. // A special return value from getopt() indicating a non-option
  260. // argument.
  261. remaining_args.push_back(arg);
  262. break;
  263. default:
  264. {
  265. // A normal option. Figure out which one it is.
  266. Options::const_iterator ii;
  267. ii = options.find(flag);
  268. if (ii == options.end()) {
  269. nout << "Internal error! Invalid option index returned.\n";
  270. abort();
  271. }
  272. const Option &opt = *(*ii).second;
  273. bool okflag = true;
  274. if (opt._option_function != (OptionDispatchFunction)NULL) {
  275. okflag = (*opt._option_function)(opt._option, arg, opt._option_data);
  276. }
  277. if (opt._option_method != (OptionDispatchMethod)NULL) {
  278. okflag = (*opt._option_method)(this, opt._option, arg, opt._option_data);
  279. }
  280. if (opt._bool_var != (bool *)NULL) {
  281. (*opt._bool_var) = true;
  282. }
  283. if (!okflag) {
  284. show_usage();
  285. exit(1);
  286. }
  287. }
  288. }
  289. flag =
  290. getopt_long_only(argc, argv, short_options.c_str(), long_opts, NULL);
  291. }
  292. if (!handle_args(remaining_args)) {
  293. show_usage();
  294. exit(1);
  295. }
  296. if (!post_command_line()) {
  297. show_usage();
  298. exit(1);
  299. }
  300. }
  301. ////////////////////////////////////////////////////////////////////
  302. // Function: ProgramBase::get_exec_command
  303. // Access: Public
  304. // Description: Returns the command that invoked this program, as a
  305. // shell-friendly string, suitable for pasting into the
  306. // comments of output files.
  307. ////////////////////////////////////////////////////////////////////
  308. string ProgramBase::
  309. get_exec_command() const {
  310. string command;
  311. command = _program_name.get_basename_wo_extension();
  312. Args::const_iterator ai;
  313. for (ai = _program_args.begin(); ai != _program_args.end(); ++ai) {
  314. const string &arg = (*ai);
  315. // First, check to see if the string is shell-acceptable.
  316. bool legal = true;
  317. string::const_iterator si;
  318. for (si = arg.begin(); legal && si != arg.end(); ++si) {
  319. switch (*si) {
  320. case ' ':
  321. case '\n':
  322. case '\t':
  323. case '*':
  324. case '?':
  325. case '\\':
  326. case '(':
  327. case ')':
  328. case '|':
  329. case '&':
  330. case '<':
  331. case '>':
  332. case '"':
  333. case ';':
  334. case '$':
  335. legal = false;
  336. }
  337. }
  338. if (legal) {
  339. command += " " + arg;
  340. } else {
  341. command += " '" + arg + "'";
  342. }
  343. }
  344. return command;
  345. }
  346. ////////////////////////////////////////////////////////////////////
  347. // Function: ProgramBase::handle_args
  348. // Access: Protected, Virtual
  349. // Description: Does something with the additional arguments on the
  350. // command line (after all the -options have been
  351. // parsed). Returns true if the arguments are good,
  352. // false otherwise.
  353. ////////////////////////////////////////////////////////////////////
  354. bool ProgramBase::
  355. handle_args(ProgramBase::Args &args) {
  356. if (!args.empty()) {
  357. nout << "Unexpected arguments on command line:\n";
  358. Args::const_iterator ai;
  359. for (ai = args.begin(); ai != args.end(); ++ai) {
  360. nout << (*ai) << " ";
  361. }
  362. nout << "\r";
  363. return false;
  364. }
  365. return true;
  366. }
  367. ////////////////////////////////////////////////////////////////////
  368. // Function: ProgramBase::post_command_line
  369. // Access: Protected, Virtual
  370. // Description: This is called after the command line has been
  371. // completely processed, and it gives the program a
  372. // chance to do some last-minute processing and
  373. // validation of the options and arguments. It should
  374. // return true if everything is fine, false if there is
  375. // an error.
  376. ////////////////////////////////////////////////////////////////////
  377. bool ProgramBase::
  378. post_command_line() {
  379. return true;
  380. }
  381. ////////////////////////////////////////////////////////////////////
  382. // Function: ProgramBase::set_program_description
  383. // Access: Protected
  384. // Description: Sets the description of the program that will be
  385. // reported by show_usage(). The description should be
  386. // one long string of text. Embedded newline characters
  387. // are interpreted as paragraph breaks and printed as
  388. // blank lines.
  389. ////////////////////////////////////////////////////////////////////
  390. void ProgramBase::
  391. set_program_description(const string &description) {
  392. _description = description;
  393. }
  394. ////////////////////////////////////////////////////////////////////
  395. // Function: ProgramBase::clear_runlines
  396. // Access: Protected
  397. // Description: Removes all of the runlines that were previously
  398. // added, presumably before adding some new ones.
  399. ////////////////////////////////////////////////////////////////////
  400. void ProgramBase::
  401. clear_runlines() {
  402. _runlines.clear();
  403. }
  404. ////////////////////////////////////////////////////////////////////
  405. // Function: ProgramBase::add_runline
  406. // Access: Protected
  407. // Description: Adds an additional line to the list of lines that
  408. // will be displayed to describe briefly how the program
  409. // is to be run. Each line should be something like
  410. // "[opts] arg1 arg2", that is, it does *not* include
  411. // the name of the program, but it includes everything
  412. // that should be printed after the name of the program.
  413. //
  414. // Normally there is only one runline for a given
  415. // program, but it is possible to define more than one.
  416. ////////////////////////////////////////////////////////////////////
  417. void ProgramBase::
  418. add_runline(const string &runline) {
  419. _runlines.push_back(runline);
  420. }
  421. ////////////////////////////////////////////////////////////////////
  422. // Function: ProgramBase::clear_options
  423. // Access: Protected
  424. // Description: Removes all of the options that were previously
  425. // added, presumably before adding some new ones.
  426. // Normally you wouldn't want to do this unless you want
  427. // to completely replace all of the options defined by
  428. // base classes.
  429. ////////////////////////////////////////////////////////////////////
  430. void ProgramBase::
  431. clear_options() {
  432. _options_by_name.clear();
  433. }
  434. ////////////////////////////////////////////////////////////////////
  435. // Function: ProgramBase::add_option
  436. // Access: Protected
  437. // Description: Adds (or redefines) a command line option. When
  438. // parse_command_line() is executed it will look for
  439. // these options (followed by a hyphen) on the command
  440. // line; when a particular option is found it will call
  441. // the indicated option_function, supplying the provided
  442. // option_data. This allows the user to define a
  443. // function that does some special behavior for any
  444. // given option, or to use any of a number of generic
  445. // pre-defined functions to fill in data for each
  446. // option.
  447. //
  448. // Each option may or may not take a parameter. If
  449. // parm_name is nonempty, it is assumed that the option
  450. // does take a parameter (and parm_name contains the
  451. // name that will be printed by show_options()). This
  452. // parameter will be supplied as the second parameter to
  453. // the dispatch function. If parm_name is empty, it is
  454. // assumed that the option does not take a parameter.
  455. // There is no provision for optional parameters.
  456. //
  457. // The options are listed first in order by their
  458. // index_group number, and then in the order that
  459. // add_option() was called. This provides a mechanism
  460. // for listing the options defined in derived classes
  461. // before those of the base classes.
  462. ////////////////////////////////////////////////////////////////////
  463. void ProgramBase::
  464. add_option(const string &option, const string &parm_name,
  465. int index_group, const string &description,
  466. OptionDispatchFunction option_function,
  467. bool *bool_var, void *option_data) {
  468. Option opt;
  469. opt._option = option;
  470. opt._parm_name = parm_name;
  471. opt._index_group = index_group;
  472. opt._sequence = ++_next_sequence;
  473. opt._description = description;
  474. opt._option_function = option_function;
  475. opt._option_method = (OptionDispatchMethod)NULL;
  476. opt._bool_var = bool_var;
  477. opt._option_data = option_data;
  478. _options_by_name[option] = opt;
  479. _sorted_options = false;
  480. if (bool_var != (bool *)NULL) {
  481. (*bool_var) = false;
  482. }
  483. }
  484. ////////////////////////////////////////////////////////////////////
  485. // Function: ProgramBase::add_option
  486. // Access: Protected
  487. // Description: This is another variant on add_option(), above,
  488. // except that it receives a pointer to a "method",
  489. // which is really just another static (or global)
  490. // function, whose first parameter is a ProgramBase *.
  491. //
  492. // We can't easily add a variant that accepts a real
  493. // method, because the C++ syntax for methods requires
  494. // us to know exactly what class object the method is
  495. // defined for, and we want to support adding pointers
  496. // for methods that are defined in other classes. So we
  497. // have this hacky thing, which requires the "method" to
  498. // be declared static, and receive its this pointer
  499. // explicitly, as the first argument.
  500. ////////////////////////////////////////////////////////////////////
  501. void ProgramBase::
  502. add_option(const string &option, const string &parm_name,
  503. int index_group, const string &description,
  504. OptionDispatchMethod option_method,
  505. bool *bool_var, void *option_data) {
  506. Option opt;
  507. opt._option = option;
  508. opt._parm_name = parm_name;
  509. opt._index_group = index_group;
  510. opt._sequence = ++_next_sequence;
  511. opt._description = description;
  512. opt._option_function = (OptionDispatchFunction)NULL;
  513. opt._option_method = option_method;
  514. opt._bool_var = bool_var;
  515. opt._option_data = option_data;
  516. _options_by_name[option] = opt;
  517. _sorted_options = false;
  518. if (bool_var != (bool *)NULL) {
  519. (*bool_var) = false;
  520. }
  521. }
  522. ////////////////////////////////////////////////////////////////////
  523. // Function: ProgramBase::redescribe_option
  524. // Access: Protected
  525. // Description: Changes the description associated with a
  526. // previously-defined option. Returns true if the
  527. // option was changed, false if it hadn't been defined.
  528. ////////////////////////////////////////////////////////////////////
  529. bool ProgramBase::
  530. redescribe_option(const string &option, const string &description) {
  531. OptionsByName::iterator oi = _options_by_name.find(option);
  532. if (oi == _options_by_name.end()) {
  533. return false;
  534. }
  535. (*oi).second._description = description;
  536. return true;
  537. }
  538. ////////////////////////////////////////////////////////////////////
  539. // Function: ProgramBase::remove_option
  540. // Access: Protected
  541. // Description: Removes a previously-defined option. Returns true if
  542. // the option was removed, false if it hadn't existed.
  543. ////////////////////////////////////////////////////////////////////
  544. bool ProgramBase::
  545. remove_option(const string &option) {
  546. OptionsByName::iterator oi = _options_by_name.find(option);
  547. if (oi == _options_by_name.end()) {
  548. return false;
  549. }
  550. _options_by_name.erase(oi);
  551. _sorted_options = false;
  552. return true;
  553. }
  554. ////////////////////////////////////////////////////////////////////
  555. // Function: ProgramBase::add_path_replace_options
  556. // Access: Public
  557. // Description: Adds -pr etc. as valid options for this program.
  558. // These are appropriate for a model converter or model
  559. // reader type program, and specify how to locate
  560. // possibly-invalid pathnames in the source model file.
  561. ////////////////////////////////////////////////////////////////////
  562. void ProgramBase::
  563. add_path_replace_options() {
  564. add_option
  565. ("pr", "path_replace", 40,
  566. "Sometimes references to other files (textures, external references) "
  567. "are stored with a full path that is appropriate for some other system, "
  568. "but does not exist here. This option may be used to specify how "
  569. "those invalid paths map to correct paths. Generally, this is of "
  570. "the form 'orig_prefix=replacement_prefix', which indicates a "
  571. "particular initial sequence of characters that should be replaced "
  572. "with a new sequence; e.g. '/c/home/models=/beta/fish'. "
  573. "If the replacement prefix does not begin with a slash, the file "
  574. "will then be searched for along the search path specified by -pp. "
  575. "You may use standard filename matching characters ('*', '?', etc.) in "
  576. "the original prefix, and '**' as a component by itself stands for "
  577. "any number of components.\n\n"
  578. "This option may be repeated as necessary; each file will be tried "
  579. "against each specified method, in the order in which they appear in "
  580. "the command line, until the file is found. If the file is not found, "
  581. "the last matching prefix is used anyway.",
  582. &ProgramBase::dispatch_path_replace, NULL, _path_replace.p());
  583. add_option
  584. ("pp", "dirname", 40,
  585. "Adds the indicated directory name to the list of directories to "
  586. "search for filenames referenced by the source file. This is used "
  587. "only for relative paths, or for paths that are made relative by a "
  588. "-pr replacement string that doesn't begin with a leading slash. "
  589. "The model-path is always implicitly searched anyway.",
  590. &ProgramBase::dispatch_search_path, NULL, &(_path_replace->_path));
  591. }
  592. ////////////////////////////////////////////////////////////////////
  593. // Function: ProgramBase::add_path_store_options
  594. // Access: Public
  595. // Description: Adds -ps etc. as valid options for this program.
  596. // These are appropriate for a model converter type
  597. // program, and specify how to represent filenames in
  598. // the output file.
  599. ////////////////////////////////////////////////////////////////////
  600. void ProgramBase::
  601. add_path_store_options() {
  602. // If a program has path store options at all, the default path
  603. // store is relative.
  604. _path_replace->_path_store = PS_relative;
  605. add_option
  606. ("ps", "path_store", 40,
  607. "Specifies the way an externally referenced file is to be "
  608. "represented in the resulting output file. This "
  609. "assumes the named filename actually exists; "
  610. "see -pr to indicate how to deal with external "
  611. "references that have bad pathnames. "
  612. "This option will not help you to find a missing file, but simply "
  613. "controls how filenames are represented in the output.\n\n"
  614. "The option may be one of: rel, abs, rel_abs, strip, or keep. If "
  615. "either rel or rel_abs is specified, the files are made relative to "
  616. "the directory specified by -pd. The default is rel.",
  617. &ProgramBase::dispatch_path_store, &_got_path_store,
  618. &(_path_replace->_path_store));
  619. add_option
  620. ("pd", "path_directory", 40,
  621. "Specifies the name of a directory to make paths relative to, if "
  622. "'-ps rel' or '-ps rel_abs' is specified. If this is omitted, the "
  623. "directory name is taken from the name of the output file.",
  624. &ProgramBase::dispatch_filename, &_got_path_directory,
  625. &(_path_replace->_path_directory));
  626. add_option
  627. ("pc", "target_directory", 40,
  628. "Copies textures and other dependent files into the indicated "
  629. "directory. If a relative pathname is specified, it is relative "
  630. "to the directory specified with -pd, above.",
  631. &ProgramBase::dispatch_filename, &(_path_replace->_copy_files),
  632. &(_path_replace->_copy_into_directory));
  633. }
  634. ////////////////////////////////////////////////////////////////////
  635. // Function: ProgramBase::dispatch_none
  636. // Access: Protected, Static
  637. // Description: Standard dispatch function for an option that takes
  638. // no parameters, and does nothing special. Typically
  639. // this would be used for a boolean flag, whose presence
  640. // means something and whose absence means something
  641. // else. Use the bool_var parameter to add_option() to
  642. // determine whether the option appears on the command
  643. // line or not.
  644. ////////////////////////////////////////////////////////////////////
  645. bool ProgramBase::
  646. dispatch_none(const string &, const string &, void *) {
  647. return true;
  648. }
  649. ////////////////////////////////////////////////////////////////////
  650. // Function: ProgramBase::dispatch_true
  651. // Access: Protected, Static
  652. // Description: Standard dispatch function for an option that takes
  653. // no parameters, and when it is present sets a bool
  654. // variable to the 'true' value. This is another way to
  655. // handle a boolean flag. See also dispatch_none() and
  656. // dispatch_false().
  657. //
  658. // The data pointer is to a bool variable.
  659. ////////////////////////////////////////////////////////////////////
  660. bool ProgramBase::
  661. dispatch_true(const string &, const string &, void *var) {
  662. bool *bp = (bool *)var;
  663. (*bp) = true;
  664. return true;
  665. }
  666. ////////////////////////////////////////////////////////////////////
  667. // Function: ProgramBase::dispatch_false
  668. // Access: Protected, Static
  669. // Description: Standard dispatch function for an option that takes
  670. // no parameters, and when it is present sets a bool
  671. // variable to the 'false' value. This is another way to
  672. // handle a boolean flag. See also dispatch_none() and
  673. // dispatch_true().
  674. //
  675. // The data pointer is to a bool variable.
  676. ////////////////////////////////////////////////////////////////////
  677. bool ProgramBase::
  678. dispatch_false(const string &, const string &, void *var) {
  679. bool *bp = (bool *)var;
  680. (*bp) = false;
  681. return true;
  682. }
  683. ////////////////////////////////////////////////////////////////////
  684. // Function: ProgramBase::dispatch_count
  685. // Access: Protected, Static
  686. // Description: Standard dispatch function for an option that takes
  687. // no parameters, but whose presence on the command line
  688. // increments an integer counter for each time it
  689. // appears. -v is often an option that works this way.
  690. // The data pointer is to an int counter variable.
  691. ////////////////////////////////////////////////////////////////////
  692. bool ProgramBase::
  693. dispatch_count(const string &, const string &, void *var) {
  694. int *ip = (int *)var;
  695. (*ip)++;
  696. return true;
  697. }
  698. ////////////////////////////////////////////////////////////////////
  699. // Function: ProgramBase::dispatch_int
  700. // Access: Protected, Static
  701. // Description: Standard dispatch function for an option that takes
  702. // one parameter, which is to be interpreted as an
  703. // integer. The data pointer is to an int variable.
  704. ////////////////////////////////////////////////////////////////////
  705. bool ProgramBase::
  706. dispatch_int(const string &opt, const string &arg, void *var) {
  707. int *ip = (int *)var;
  708. if (!string_to_int(arg, *ip)) {
  709. nout << "Invalid integer parameter for -" << opt << ": "
  710. << arg << "\n";
  711. return false;
  712. }
  713. return true;
  714. }
  715. ////////////////////////////////////////////////////////////////////
  716. // Function: ProgramBase::dispatch_int_pair
  717. // Access: Protected, Static
  718. // Description: Standard dispatch function for an option that takes
  719. // a pair of integer parameters. The data pointer is to
  720. // an array of two integers.
  721. ////////////////////////////////////////////////////////////////////
  722. bool ProgramBase::
  723. dispatch_int_pair(const string &opt, const string &arg, void *var) {
  724. int *ip = (int *)var;
  725. vector_string words;
  726. tokenize(arg, words, ",");
  727. bool okflag = false;
  728. if (words.size() == 2) {
  729. okflag =
  730. string_to_int(words[0], ip[0]) &&
  731. string_to_int(words[1], ip[1]);
  732. }
  733. if (!okflag) {
  734. nout << "-" << opt
  735. << " requires a pair of integers separated by a comma.\n";
  736. return false;
  737. }
  738. return true;
  739. }
  740. ////////////////////////////////////////////////////////////////////
  741. // Function: ProgramBase::dispatch_int_quad
  742. // Access: Protected, Static
  743. // Description: Standard dispatch function for an option that takes
  744. // a quad of integer parameters. The data pointer is to
  745. // an array of four integers.
  746. ////////////////////////////////////////////////////////////////////
  747. bool ProgramBase::
  748. dispatch_int_quad(const string &opt, const string &arg, void *var) {
  749. int *ip = (int *)var;
  750. vector_string words;
  751. tokenize(arg, words, ",");
  752. bool okflag = false;
  753. if (words.size() == 4) {
  754. okflag =
  755. string_to_int(words[0], ip[0]) &&
  756. string_to_int(words[1], ip[1]) &&
  757. string_to_int(words[1], ip[2]) &&
  758. string_to_int(words[1], ip[3]);
  759. }
  760. if (!okflag) {
  761. nout << "-" << opt
  762. << " requires a quad of integers separated by a comma.\n";
  763. return false;
  764. }
  765. return true;
  766. }
  767. ////////////////////////////////////////////////////////////////////
  768. // Function: ProgramBase::dispatch_double
  769. // Access: Protected, Static
  770. // Description: Standard dispatch function for an option that takes
  771. // one parameter, which is to be interpreted as a
  772. // double. The data pointer is to an double variable.
  773. ////////////////////////////////////////////////////////////////////
  774. bool ProgramBase::
  775. dispatch_double(const string &opt, const string &arg, void *var) {
  776. double *ip = (double *)var;
  777. if (!string_to_double(arg, *ip)) {
  778. nout << "Invalid numeric parameter for -" << opt << ": "
  779. << arg << "\n";
  780. return false;
  781. }
  782. return true;
  783. }
  784. ////////////////////////////////////////////////////////////////////
  785. // Function: ProgramBase::dispatch_double_pair
  786. // Access: Protected, Static
  787. // Description: Standard dispatch function for an option that takes
  788. // a pair of double parameters. The data pointer is to
  789. // an array of two doubles.
  790. ////////////////////////////////////////////////////////////////////
  791. bool ProgramBase::
  792. dispatch_double_pair(const string &opt, const string &arg, void *var) {
  793. double *ip = (double *)var;
  794. vector_string words;
  795. tokenize(arg, words, ",");
  796. bool okflag = false;
  797. if (words.size() == 2) {
  798. okflag =
  799. string_to_double(words[0], ip[0]) &&
  800. string_to_double(words[1], ip[1]);
  801. }
  802. if (!okflag) {
  803. nout << "-" << opt
  804. << " requires a pair of numbers separated by a comma.\n";
  805. return false;
  806. }
  807. return true;
  808. }
  809. ////////////////////////////////////////////////////////////////////
  810. // Function: ProgramBase::dispatch_double_triple
  811. // Access: Protected, Static
  812. // Description: Standard dispatch function for an option that takes
  813. // a triple of double parameters. The data pointer is to
  814. // an array of three doubles.
  815. ////////////////////////////////////////////////////////////////////
  816. bool ProgramBase::
  817. dispatch_double_triple(const string &opt, const string &arg, void *var) {
  818. double *ip = (double *)var;
  819. vector_string words;
  820. tokenize(arg, words, ",");
  821. bool okflag = false;
  822. if (words.size() == 3) {
  823. okflag =
  824. string_to_double(words[0], ip[0]) &&
  825. string_to_double(words[1], ip[1]) &&
  826. string_to_double(words[2], ip[2]);
  827. }
  828. if (!okflag) {
  829. nout << "-" << opt
  830. << " requires three numbers separated by commas.\n";
  831. return false;
  832. }
  833. return true;
  834. }
  835. ////////////////////////////////////////////////////////////////////
  836. // Function: ProgramBase::dispatch_double_quad
  837. // Access: Protected, Static
  838. // Description: Standard dispatch function for an option that takes
  839. // a quad of double parameters. The data pointer is to
  840. // an array of four doubles.
  841. ////////////////////////////////////////////////////////////////////
  842. bool ProgramBase::
  843. dispatch_double_quad(const string &opt, const string &arg, void *var) {
  844. double *ip = (double *)var;
  845. vector_string words;
  846. tokenize(arg, words, ",");
  847. bool okflag = false;
  848. if (words.size() == 4) {
  849. okflag =
  850. string_to_double(words[0], ip[0]) &&
  851. string_to_double(words[1], ip[1]) &&
  852. string_to_double(words[2], ip[2]) &&
  853. string_to_double(words[3], ip[3]);
  854. }
  855. if (!okflag) {
  856. nout << "-" << opt
  857. << " requires four numbers separated by commas.\n";
  858. return false;
  859. }
  860. return true;
  861. }
  862. ////////////////////////////////////////////////////////////////////
  863. // Function: ProgramBase::dispatch_color
  864. // Access: Protected, Static
  865. // Description: Standard dispatch function for an option that takes a
  866. // color, as l or l,a or r,g,b or r,g,b,a. The data
  867. // pointer is to an array of four floats, e.g. a LColor.
  868. ////////////////////////////////////////////////////////////////////
  869. bool ProgramBase::
  870. dispatch_color(const string &opt, const string &arg, void *var) {
  871. PN_stdfloat *ip = (PN_stdfloat *)var;
  872. vector_string words;
  873. tokenize(arg, words, ",");
  874. bool okflag = false;
  875. switch (words.size()) {
  876. case 4:
  877. okflag =
  878. string_to_float(words[0], ip[0]) &&
  879. string_to_float(words[1], ip[1]) &&
  880. string_to_float(words[2], ip[2]) &&
  881. string_to_float(words[3], ip[3]);
  882. break;
  883. case 3:
  884. okflag =
  885. string_to_float(words[0], ip[0]) &&
  886. string_to_float(words[1], ip[1]) &&
  887. string_to_float(words[2], ip[2]);
  888. ip[3] = 1.0;
  889. break;
  890. case 2:
  891. okflag =
  892. string_to_float(words[0], ip[0]) &&
  893. string_to_float(words[1], ip[3]);
  894. ip[1] = ip[0];
  895. ip[2] = ip[0];
  896. break;
  897. case 1:
  898. okflag =
  899. string_to_float(words[0], ip[0]);
  900. ip[1] = ip[0];
  901. ip[2] = ip[0];
  902. ip[3] = 1.0;
  903. break;
  904. }
  905. if (!okflag) {
  906. nout << "-" << opt
  907. << " requires one through four numbers separated by commas.\n";
  908. return false;
  909. }
  910. return true;
  911. }
  912. ////////////////////////////////////////////////////////////////////
  913. // Function: ProgramBase::dispatch_string
  914. // Access: Protected, Static
  915. // Description: Standard dispatch function for an option that takes
  916. // one parameter, which is to be interpreted as a
  917. // string. The data pointer is to a string variable.
  918. ////////////////////////////////////////////////////////////////////
  919. bool ProgramBase::
  920. dispatch_string(const string &, const string &arg, void *var) {
  921. string *ip = (string *)var;
  922. (*ip) = arg;
  923. return true;
  924. }
  925. ////////////////////////////////////////////////////////////////////
  926. // Function: ProgramBase::dispatch_vector_string
  927. // Access: Protected, Static
  928. // Description: Standard dispatch function for an option that takes
  929. // one parameter, which is to be interpreted as a
  930. // string. This is different from dispatch_string in
  931. // that the parameter may be repeated multiple times,
  932. // and each time the string value is appended to a
  933. // vector.
  934. //
  935. // The data pointer is to a vector_string variable.
  936. ////////////////////////////////////////////////////////////////////
  937. bool ProgramBase::
  938. dispatch_vector_string(const string &, const string &arg, void *var) {
  939. vector_string *ip = (vector_string *)var;
  940. (*ip).push_back(arg);
  941. return true;
  942. }
  943. ////////////////////////////////////////////////////////////////////
  944. // Function: ProgramBase::dispatch_vector_string_comma
  945. // Access: Protected, Static
  946. // Description: Similar to dispatch_vector_string, but a comma is
  947. // allowed to separate multiple tokens in one argument,
  948. // without having to repeat the argument for each token.
  949. //
  950. // The data pointer is to a vector_string variable.
  951. ////////////////////////////////////////////////////////////////////
  952. bool ProgramBase::
  953. dispatch_vector_string_comma(const string &, const string &arg, void *var) {
  954. vector_string *ip = (vector_string *)var;
  955. vector_string words;
  956. tokenize(arg, words, ",");
  957. vector_string::const_iterator wi;
  958. for (wi = words.begin(); wi != words.end(); ++wi) {
  959. (*ip).push_back(*wi);
  960. }
  961. return true;
  962. }
  963. ////////////////////////////////////////////////////////////////////
  964. // Function: ProgramBase::dispatch_filename
  965. // Access: Protected, Static
  966. // Description: Standard dispatch function for an option that takes
  967. // one parameter, which is to be interpreted as a
  968. // filename. The data pointer is to a Filename variable.
  969. ////////////////////////////////////////////////////////////////////
  970. bool ProgramBase::
  971. dispatch_filename(const string &opt, const string &arg, void *var) {
  972. if (arg.empty()) {
  973. nout << "-" << opt << " requires a filename parameter.\n";
  974. return false;
  975. }
  976. Filename *ip = (Filename *)var;
  977. (*ip) = Filename::from_os_specific(arg);
  978. return true;
  979. }
  980. ////////////////////////////////////////////////////////////////////
  981. // Function: ProgramBase::dispatch_search_path
  982. // Access: Protected, Static
  983. // Description: Standard dispatch function for an option that takes
  984. // one parameter, which is to be interpreted as a
  985. // single directory name to add to a search path. The
  986. // data pointer is to a DSearchPath variable. This kind
  987. // of option may appear multiple times on the command
  988. // line; each time, the new directory is appended.
  989. ////////////////////////////////////////////////////////////////////
  990. bool ProgramBase::
  991. dispatch_search_path(const string &opt, const string &arg, void *var) {
  992. if (arg.empty()) {
  993. nout << "-" << opt << " requires a search path parameter.\n";
  994. return false;
  995. }
  996. DSearchPath *ip = (DSearchPath *)var;
  997. ip->append_directory(Filename::from_os_specific(arg));
  998. return true;
  999. }
  1000. ////////////////////////////////////////////////////////////////////
  1001. // Function: ProgramBase::dispatch_coordinate_system
  1002. // Access: Protected, Static
  1003. // Description: Standard dispatch function for an option that takes
  1004. // one parameter, which is to be interpreted as a
  1005. // coordinate system string. The data pointer is to a
  1006. // CoordinateSystem variable.
  1007. ////////////////////////////////////////////////////////////////////
  1008. bool ProgramBase::
  1009. dispatch_coordinate_system(const string &opt, const string &arg, void *var) {
  1010. CoordinateSystem *ip = (CoordinateSystem *)var;
  1011. (*ip) = parse_coordinate_system_string(arg);
  1012. if ((*ip) == CS_invalid) {
  1013. nout << "Invalid coordinate system for -" << opt << ": " << arg << "\n"
  1014. << "Valid coordinate system strings are any of 'y-up', 'z-up', "
  1015. "'y-up-left', or 'z-up-left'.\n";
  1016. return false;
  1017. }
  1018. return true;
  1019. }
  1020. ////////////////////////////////////////////////////////////////////
  1021. // Function: ProgramBase::dispatch_units
  1022. // Access: Protected, Static
  1023. // Description: Standard dispatch function for an option that takes
  1024. // one parameter, which is to be interpreted as a
  1025. // unit of distance measurement. The data pointer is to
  1026. // a DistanceUnit variable.
  1027. ////////////////////////////////////////////////////////////////////
  1028. bool ProgramBase::
  1029. dispatch_units(const string &opt, const string &arg, void *var) {
  1030. DistanceUnit *ip = (DistanceUnit *)var;
  1031. (*ip) = string_distance_unit(arg);
  1032. if ((*ip) == DU_invalid) {
  1033. nout << "Invalid units for -" << opt << ": " << arg << "\n"
  1034. << "Valid units are mm, cm, m, km, yd, ft, in, nmi, and mi.\n";
  1035. return false;
  1036. }
  1037. return true;
  1038. }
  1039. ////////////////////////////////////////////////////////////////////
  1040. // Function: ProgramBase::dispatch_image_type
  1041. // Access: Protected, Static
  1042. // Description: Standard dispatch function for an option that takes
  1043. // one parameter, which is to indicate an image file
  1044. // type, like rgb, bmp, jpg, etc. The data pointer is
  1045. // to a PNMFileType pointer.
  1046. ////////////////////////////////////////////////////////////////////
  1047. bool ProgramBase::
  1048. dispatch_image_type(const string &opt, const string &arg, void *var) {
  1049. PNMFileType **ip = (PNMFileType **)var;
  1050. PNMFileTypeRegistry *reg = PNMFileTypeRegistry::get_global_ptr();
  1051. (*ip) = reg->get_type_from_extension(arg);
  1052. if ((*ip) == (PNMFileType *)NULL) {
  1053. nout << "Invalid image type for -" << opt << ": " << arg << "\n"
  1054. << "The following image types are known:\n";
  1055. reg->write(nout, 2);
  1056. return false;
  1057. }
  1058. return true;
  1059. }
  1060. ////////////////////////////////////////////////////////////////////
  1061. // Function: ProgramBase::dispatch_path_replace
  1062. // Access: Protected, Static
  1063. // Description: Standard dispatch function for an option that takes
  1064. // one parameter, which is to be interpreted as a
  1065. // single component of a path replace request. The data
  1066. // pointer is to a PathReplace variable.
  1067. ////////////////////////////////////////////////////////////////////
  1068. bool ProgramBase::
  1069. dispatch_path_replace(const string &opt, const string &arg, void *var) {
  1070. PathReplace *ip = (PathReplace *)var;
  1071. size_t equals = arg.find('=');
  1072. if (equals == string::npos) {
  1073. nout << "Invalid path replacement string for -" << opt << ": " << arg << "\n"
  1074. << "String should be of the form 'old-prefix=new-prefix'.\n";
  1075. return false;
  1076. }
  1077. ip->add_pattern(arg.substr(0, equals), arg.substr(equals + 1));
  1078. return true;
  1079. }
  1080. ////////////////////////////////////////////////////////////////////
  1081. // Function: ProgramBase::dispatch_path_store
  1082. // Access: Protected, Static
  1083. // Description: Standard dispatch function for an option that takes
  1084. // one parameter, which is to be interpreted as a
  1085. // path store string. The data pointer is to a
  1086. // PathStore variable.
  1087. ////////////////////////////////////////////////////////////////////
  1088. bool ProgramBase::
  1089. dispatch_path_store(const string &opt, const string &arg, void *var) {
  1090. PathStore *ip = (PathStore *)var;
  1091. (*ip) = string_path_store(arg);
  1092. if ((*ip) == PS_invalid) {
  1093. nout << "Invalid path store for -" << opt << ": " << arg << "\n"
  1094. << "Valid path store strings are any of 'rel', 'abs', "
  1095. << "'rel_abs', 'strip', or 'keep'.\n";
  1096. return false;
  1097. }
  1098. return true;
  1099. }
  1100. ////////////////////////////////////////////////////////////////////
  1101. // Function: ProgramBase::handle_help_option
  1102. // Access: Protected, Static
  1103. // Description: Called when the user enters '-h', this describes how
  1104. // to use the program and then exits.
  1105. ////////////////////////////////////////////////////////////////////
  1106. bool ProgramBase::
  1107. handle_help_option(const string &, const string &, void *data) {
  1108. ProgramBase *me = (ProgramBase *)data;
  1109. me->show_description();
  1110. me->show_usage();
  1111. me->show_options();
  1112. exit(0);
  1113. return false;
  1114. }
  1115. ////////////////////////////////////////////////////////////////////
  1116. // Function: ProgramBase::format_text
  1117. // Access: Protected, Static
  1118. // Description: Word-wraps the indicated text to the indicated output
  1119. // stream. The first line is prefixed with the
  1120. // indicated prefix, then tabbed over to indent_width
  1121. // where the text actually begins. A newline is
  1122. // inserted at or before column line_width. Each
  1123. // subsequent line begins with indent_width spaces.
  1124. //
  1125. // An embedded newline character ('\n') forces a line
  1126. // break, while an embedded carriage-return character
  1127. // ('\r'), or two or more consecutive newlines, marks a
  1128. // paragraph break, which is usually printed as a blank
  1129. // line. Redundant newline and carriage-return
  1130. // characters are generally ignored.
  1131. //
  1132. // The flag last_newline should be initialized to false
  1133. // for the first call to format_text, and then preserved
  1134. // for future calls; it tracks the state of trailing
  1135. // newline characters between calls so we can correctly
  1136. // identify doubled newlines.
  1137. ////////////////////////////////////////////////////////////////////
  1138. void ProgramBase::
  1139. format_text(ostream &out, bool &last_newline,
  1140. const string &prefix, int indent_width,
  1141. const string &text, int line_width) {
  1142. indent_width = min(indent_width, line_width - 20);
  1143. int indent_amount = indent_width;
  1144. bool initial_break = false;
  1145. if (!prefix.empty()) {
  1146. out << prefix;
  1147. indent_amount = indent_width - prefix.length();
  1148. if ((int)prefix.length() + 1 > indent_width) {
  1149. out << "\n";
  1150. initial_break = true;
  1151. indent_amount = indent_width;
  1152. }
  1153. }
  1154. size_t p = 0;
  1155. // Skip any initial whitespace and newlines.
  1156. while (p < text.length() && isspace(text[p])) {
  1157. if (text[p] == '\r' ||
  1158. (p > 0 && text[p] == '\n' && text[p - 1] == '\n') ||
  1159. (p == 0 && text[p] == '\n' && last_newline)) {
  1160. if (!initial_break) {
  1161. // Here's an initial paragraph break, however.
  1162. out << "\n";
  1163. initial_break = true;
  1164. }
  1165. indent_amount = indent_width;
  1166. } else if (text[p] == '\n') {
  1167. // Largely ignore an initial newline.
  1168. indent_amount = indent_width;
  1169. } else if (text[p] == ' ') {
  1170. // Do count up leading spaces.
  1171. indent_amount++;
  1172. }
  1173. p++;
  1174. }
  1175. last_newline = (!text.empty() && text[text.length() - 1] == '\n');
  1176. while (p < text.length()) {
  1177. // Look for the paragraph or line break--the next newline
  1178. // character, if any.
  1179. size_t par = text.find_first_of("\n\r", p);
  1180. bool is_paragraph_break = false;
  1181. if (par == string::npos) {
  1182. par = text.length();
  1183. /*
  1184. This shouldn't be necessary.
  1185. } else {
  1186. is_paragraph_break = (text[par] == '\r');
  1187. */
  1188. }
  1189. indent(out, indent_amount);
  1190. size_t eol = p + (line_width - indent_width);
  1191. if (eol >= par) {
  1192. // The rest of the paragraph fits completely on the line.
  1193. eol = par;
  1194. } else {
  1195. // The paragraph doesn't fit completely on the line. Determine
  1196. // the best place to break the line. Look for the last space
  1197. // before the ideal eol.
  1198. size_t min_eol = max((int)p, (int)eol - 25);
  1199. size_t q = eol;
  1200. while (q > min_eol && !isspace(text[q])) {
  1201. q--;
  1202. }
  1203. // Now roll back to the last non-space before this one.
  1204. while (q > min_eol && isspace(text[q])) {
  1205. q--;
  1206. }
  1207. if (q != min_eol) {
  1208. // Here's a good place to stop!
  1209. eol = q + 1;
  1210. } else {
  1211. // The line cannot be broken cleanly. Just let it keep going;
  1212. // don't try to wrap it.
  1213. eol = par;
  1214. }
  1215. }
  1216. out << text.substr(p, eol - p) << "\n";
  1217. p = eol;
  1218. // Skip additional whitespace between the lines.
  1219. while (p < text.length() && isspace(text[p])) {
  1220. if (text[p] == '\r' ||
  1221. (p > 0 && text[p] == '\n' && text[p - 1] == '\n')) {
  1222. is_paragraph_break = true;
  1223. }
  1224. p++;
  1225. }
  1226. if (eol == par && is_paragraph_break) {
  1227. // Print the paragraph break as a blank line.
  1228. out << "\n";
  1229. if (p >= text.length()) {
  1230. // If we end on a paragraph break, don't try to insert a new
  1231. // one in the next pass.
  1232. last_newline = false;
  1233. }
  1234. }
  1235. indent_amount = indent_width;
  1236. }
  1237. }
  1238. ////////////////////////////////////////////////////////////////////
  1239. // Function: ProgramBase::sort_options
  1240. // Access: Private
  1241. // Description: Puts all the options in order by index number
  1242. // (e.g. in the order they were added, within
  1243. // index_groups), for output by show_options().
  1244. ////////////////////////////////////////////////////////////////////
  1245. void ProgramBase::
  1246. sort_options() {
  1247. if (!_sorted_options) {
  1248. _options_by_index.clear();
  1249. OptionsByName::const_iterator oi;
  1250. for (oi = _options_by_name.begin(); oi != _options_by_name.end(); ++oi) {
  1251. _options_by_index.push_back(&(*oi).second);
  1252. }
  1253. sort(_options_by_index.begin(), _options_by_index.end(),
  1254. SortOptionsByIndex());
  1255. _sorted_options = true;
  1256. }
  1257. }
  1258. ////////////////////////////////////////////////////////////////////
  1259. // Function: ProgramBase::get_terminal_width
  1260. // Access: Private
  1261. // Description: Attempts to determine the ideal terminal width for
  1262. // formatting output.
  1263. ////////////////////////////////////////////////////////////////////
  1264. void ProgramBase::
  1265. get_terminal_width() {
  1266. if (!_got_terminal_width) {
  1267. _got_terminal_width = true;
  1268. _got_option_indent = false;
  1269. #ifdef IOCTL_TERMINAL_WIDTH
  1270. if (use_terminal_width) {
  1271. struct winsize size;
  1272. int result = ioctl(STDIN_FILENO, TIOCGWINSZ, (char *)&size);
  1273. if (result < 0 || size.ws_col < 10) {
  1274. // Couldn't determine the width for some reason. Instead of
  1275. // complaining, just punt.
  1276. _terminal_width = default_terminal_width;
  1277. } else {
  1278. // Subtract 10% for the comfort margin at the edge.
  1279. _terminal_width = size.ws_col - min(8, (int)(size.ws_col * 0.1));
  1280. }
  1281. return;
  1282. }
  1283. #endif // IOCTL_TERMINAL_WIDTH
  1284. _terminal_width = default_terminal_width;
  1285. }
  1286. }