00001 #include "ace_pch.h"
00002
00003
00004
00005 #include "ace/Get_Opt.h"
00006 #include "ace/Log_Msg.h"
00007
00008 #if !defined (__ACE_INLINE__)
00009 #include "ace/Get_Opt.i"
00010 #endif
00011
00012 ACE_RCSID(ace, Get_Opt, "$Id: Get_Opt.cpp,v 1.1.1.4.2.1 2003/03/13 19:44:21 chad Exp $")
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 ACE_ALLOC_HOOK_DEFINE(ACE_Get_Opt)
00084
00085 ACE_Get_Opt::ACE_Get_Opt (int argc,
00086 ACE_TCHAR **argv,
00087 const ACE_TCHAR *optstring,
00088 int skip,
00089 int report_errors,
00090 int ordering,
00091 int long_only)
00092 : argc_ (argc),
00093 argv_ (argv),
00094 optind (skip),
00095 opterr (report_errors),
00096 optarg (0),
00097 optstring_ (optstring),
00098 long_only_ (long_only),
00099 has_colon_ (0),
00100 nextchar_ (0),
00101 optopt_ (0),
00102 ordering_ (ordering),
00103 nonopt_start_ (optind),
00104 nonopt_end_ (optind),
00105 long_option_ (0)
00106 {
00107 ACE_TRACE ("ACE_Get_Opt::ACE_Get_Opt");
00108
00109
00110 if (ACE_OS::getenv (ACE_LIB_TEXT ("POSIXLY_CORRECT")) != 0)
00111 this->ordering_ = REQUIRE_ORDER;
00112
00113
00114
00115
00116
00117
00118
00119 int done = 0;
00120 int offset = 0;
00121 while (!done)
00122 {
00123 switch (optstring[offset++])
00124 {
00125 case '+':
00126 this->ordering_ = REQUIRE_ORDER;
00127 break;
00128 case '-':
00129 this->ordering_ = RETURN_IN_ORDER;
00130 break;
00131 case ':':
00132 this->has_colon_ = 1;
00133 break;
00134 default:
00135
00136 done = 1;
00137 break;
00138 }
00139 }
00140 }
00141
00142 ACE_Get_Opt::~ACE_Get_Opt (void)
00143 {
00144 ACE_TRACE ("ACE_Get_Opt::~ACE_Get_Opt");
00145
00146 size_t i = 0;
00147 size_t size = this->long_opts_.size ();
00148 ACE_Get_Opt_Long_Option *option = 0;
00149 for (i = 0; i < size; ++i)
00150 {
00151 int retval = this->long_opts_.get (option, i);
00152 if (retval != 0)
00153 {
00154
00155 retval = 0;
00156 continue;
00157 }
00158 if (option)
00159 {
00160 delete option;
00161 option = 0;
00162 }
00163 }
00164 }
00165
00166 int
00167 ACE_Get_Opt::nextchar_i (void)
00168 {
00169 ACE_TRACE ("ACE_Get_Opt::nextchar_i");
00170
00171 if (this->ordering_ == PERMUTE_ARGS)
00172 if (this->permute () == EOF)
00173 return EOF;
00174
00175
00176 if (this->optind >= this->argc_)
00177 {
00178
00179 this->nextchar_ = 0;
00180 return EOF;
00181 }
00182 else if (*(this->nextchar_ = this->argv_[this->optind]) != '-'
00183 || this->nextchar_[1] == '\0')
00184 {
00185
00186
00187 if (this->ordering_ == REQUIRE_ORDER
00188 || this->ordering_ == PERMUTE_ARGS)
00189
00190 return EOF;
00191
00192
00193 this->optarg = this->argv_[this->optind++];
00194 this->nextchar_ = 0;
00195 return 1;
00196 }
00197 else if (this->nextchar_[1] != 0
00198 && *++this->nextchar_ == '-'
00199 && this->nextchar_[1] == 0)
00200 {
00201
00202 ++this->optind;
00203 this->nextchar_ = 0;
00204 return EOF;
00205 }
00206
00207
00208 if (*this->nextchar_ == '-' && this->long_opts_.size () != 0)
00209 this->nextchar_++;
00210
00211 return 0;
00212 }
00213
00214 int
00215 ACE_Get_Opt::long_option_i (void)
00216 {
00217 ACE_TRACE ("ACE_Get_Opt::long_option_i");
00218
00219 ACE_Get_Opt_Long_Option *p;
00220 ACE_TCHAR *s = this->nextchar_;
00221 int hits = 0;
00222 int exact = 0;
00223 ACE_Get_Opt_Long_Option *pfound = 0;
00224 int indfound = 0;
00225
00226
00227
00228 while (*s && *s != '=')
00229 s++;
00230
00231 size_t len = s - this->nextchar_;
00232 size_t size = this->long_opts_.size ();
00233 u_int option_index = 0;
00234 for (option_index = 0; option_index < size ; option_index++)
00235 {
00236 p = this->long_opts_[option_index];
00237 ACE_ASSERT (p);
00238
00239 if (!ACE_OS::strncmp (p->name_, this->nextchar_, len))
00240 {
00241
00242 pfound = p;
00243 indfound = option_index;
00244 hits += 1;
00245 if (len == ACE_OS::strlen(p->name_))
00246 {
00247
00248 exact = 1;
00249 break;
00250 }
00251 }
00252 }
00253
00254 if ((hits > 1) && !exact)
00255 {
00256
00257
00258 if (this->opterr)
00259 ACE_ERROR ((LM_ERROR,
00260 ACE_LIB_TEXT ("%s: option `%s' is ambiguous\n"),
00261 this->argv_[0], this->argv_[this->optind]));
00262 this->nextchar_ = 0;
00263 this->optind++;
00264 return '?';
00265 }
00266
00267 if (pfound != 0)
00268 {
00269
00270 option_index = indfound;
00271 this->optind++;
00272 if (*s)
00273 {
00274
00275
00276 if (pfound->has_arg_ != NO_ARG)
00277
00278 this->optarg = ++s;
00279 else
00280 {
00281
00282
00283 if (this->opterr)
00284 ACE_ERROR
00285 ((LM_ERROR,
00286 ACE_LIB_TEXT ("%s: long option `--%s' doesn't allow an argument\n"),
00287 this->argv_[0], pfound->name_));
00288
00289
00290 }
00291 }
00292 else if (pfound->has_arg_ == ARG_REQUIRED)
00293 {
00294
00295
00296
00297 if (this->optind < this->argc_)
00298
00299 this->optarg = this->argv_[this->optind++];
00300 else
00301 {
00302
00303 if (this->opterr)
00304 ACE_ERROR ((LM_ERROR,
00305 ACE_LIB_TEXT ("%s: long option '--%s' requires an argument\n"),
00306 this->argv_[0], pfound->name_));
00307 this->nextchar_ = 0;
00308 this->optopt_ = pfound->val_;
00309 return this->has_colon_ ? ':' : '?';
00310 }
00311 }
00312 this->nextchar_ = 0;
00313 this->long_option_ = pfound;
00314
00315
00316 this->optopt_ = pfound->val_;
00317 return pfound->val_;
00318 }
00319 if (!this->long_only_ || this->argv_[this->optind][1] == '-'
00320 || this->optstring_.find (*this->nextchar_) == ACE_TString::npos)
00321 {
00322
00323
00324
00325
00326 if (this->opterr)
00327 ACE_ERROR ((LM_ERROR,
00328 ACE_LIB_TEXT ("%s: illegal long option '--%s'\n"),
00329 this->argv_[0], this->nextchar_));
00330 this->nextchar_ = 0;
00331 this->optind++;
00332 return '?';
00333 }
00334 return this->short_option_i ();
00335 }
00336
00337 int
00338 ACE_Get_Opt::short_option_i (void)
00339 {
00340 ACE_TRACE ("ACE_Get_Opt::short_option_i");
00341
00342
00343 ACE_TCHAR opt = *this->nextchar_++;
00344 ACE_TCHAR *oli = 0;
00345 oli = ACE_const_cast (ACE_TCHAR*, ACE_OS::strchr (this->optstring_.c_str (), opt));
00346
00347
00348 if (*this->nextchar_ == '\0')
00349 ++this->optind;
00350
00351 if (oli == 0 || opt == ':')
00352 {
00353 if (this->opterr)
00354 ACE_ERROR ((LM_ERROR,
00355 ACE_LIB_TEXT ("%s: illegal short option -- %c\n"),
00356 this->argv_[0], opt));
00357 return '?';
00358 }
00359 if (opt == 'W' && oli[1] == ';')
00360 {
00361 if (this->nextchar_[0] == 0)
00362 this->nextchar_ = this->argv_[this->optind];
00363 return long_option_i ();
00364 }
00365 this->optopt_ = oli[0];
00366 if (oli[1] == ':')
00367 {
00368 if (oli[2] == ':')
00369 {
00370
00371
00372
00373 if (*this->nextchar_ != '\0')
00374 {
00375 this->optarg = this->nextchar_;
00376 this->optind++;
00377 }
00378 else
00379 this->optarg = 0;
00380 this->nextchar_ = 0;
00381 }
00382 else
00383 {
00384
00385 if (*this->nextchar_ != '\0')
00386 {
00387
00388 this->optarg = this->nextchar_;
00389 this->optind++;
00390 }
00391 else if (this->optind == this->argc_)
00392 {
00393
00394 if (this->opterr)
00395 ACE_ERROR ((LM_ERROR,
00396 ACE_LIB_TEXT ("%s: short option requires an argument -- %c\n"),
00397 this->argv_[0], opt));
00398 opt = this->has_colon_ ? ':' : '?';
00399 }
00400 else
00401
00402 this->optarg = this->argv_[this->optind++];
00403 this->nextchar_ = 0;
00404 }
00405 }
00406 return opt;
00407 }
00408
00409 int
00410 ACE_Get_Opt::operator () (void)
00411 {
00412 ACE_TRACE ("ACE_Get_Opt_Long::operator");
00413
00414
00415 this->optarg = 0;
00416 this->long_option_ = 0;
00417
00418 if (this->argv_ == 0)
00419 {
00420
00421 this->optind = 0;
00422 return -1;
00423 }
00424
00425
00426
00427 if (this->nextchar_ == 0 || *this->nextchar_ == '\0')
00428 {
00429 int retval = this->nextchar_i ();
00430 if (retval != 0)
00431 return retval;
00432 }
00433
00434 if (((this->argv_[this->optind][0] == '-')
00435 && (this->argv_[this->optind][1] == '-')) || this->long_only_)
00436 return this->long_option_i ();
00437
00438 return this->short_option_i ();
00439 }
00440
00441 int
00442 ACE_Get_Opt::long_option (const ACE_TCHAR *name,
00443 OPTION_ARG_MODE has_arg)
00444 {
00445 ACE_TRACE ("ACE_Get_Opt::long_option (const ACE_TCHAR *name, OPTION_ARG_MODE has_arg)");
00446 return this->long_option (name, 0, has_arg);
00447 }
00448
00449 int
00450 ACE_Get_Opt::long_option (const ACE_TCHAR *name,
00451 int short_option,
00452 OPTION_ARG_MODE has_arg)
00453 {
00454 ACE_TRACE ("ACE_Get_Opt::long_option (const ACE_TCHAR *name, int short_option, OPTION_ARG_MODE has_arg)");
00455
00456
00457
00458
00459
00460
00461 #if defined (_MSC_VER) && (_MSC_VER >= 1300)
00462
00463
00464 if (short_option > 0 &&
00465 short_option < 256 &&
00466 isalnum (short_option) != 0)
00467 #else
00468 if (isalnum (short_option) != 0)
00469 #endif
00470 {
00471
00472
00473 ACE_TCHAR *s = 0;
00474 if ((s = ACE_const_cast (ACE_TCHAR*,
00475 ACE_OS::strchr (this->optstring_.c_str (), short_option))) != 0)
00476 {
00477
00478 if (s[1] == ':')
00479 {
00480 if (s[2] == ':')
00481 {
00482 if (has_arg != ARG_OPTIONAL)
00483 {
00484 if (this->opterr)
00485 ACE_ERROR
00486 ((LM_ERROR,
00487 ACE_LIB_TEXT ("Existing short option '%c' takes ")
00488 ACE_LIB_TEXT ("optional argument; adding %s ")
00489 ACE_LIB_TEXT ("requires ARG_OPTIONAL\n"),
00490 short_option, name));
00491 return -1;
00492 }
00493 }
00494 else
00495 if (has_arg != ARG_REQUIRED)
00496 {
00497 if (this->opterr)
00498 ACE_ERROR
00499 ((LM_ERROR,
00500 ACE_LIB_TEXT ("Existing short option '%c' requires ")
00501 ACE_LIB_TEXT ("an argument; adding %s ")
00502 ACE_LIB_TEXT ("requires ARG_REQUIRED\n"),
00503 short_option, name));
00504 return -1;
00505 }
00506 }
00507 else if (has_arg != NO_ARG)
00508 {
00509 if (this->opterr)
00510 ACE_ERROR
00511 ((LM_ERROR,
00512 ACE_LIB_TEXT ("Existing short option '%c' does not ")
00513 ACE_LIB_TEXT ("accept an argument; adding %s ")
00514 ACE_LIB_TEXT ("requires NO_ARG\n"),
00515 short_option, name));
00516 return -1;
00517 }
00518 }
00519 else
00520 {
00521
00522 this->optstring_ += (ACE_TCHAR) short_option;
00523 if (has_arg == ARG_REQUIRED)
00524 this->optstring_ += ACE_LIB_TEXT (":");
00525 else if (has_arg == ARG_OPTIONAL)
00526 this->optstring_ += ACE_LIB_TEXT ("::");
00527 }
00528 }
00529
00530 ACE_Get_Opt_Long_Option *option =
00531 new ACE_Get_Opt_Long_Option (name, has_arg, short_option);
00532
00533 if (!option)
00534 return -1;
00535
00536
00537 size_t size = this->long_opts_.size ();
00538 if (this->long_opts_.size (size + 1) != 0
00539 || this->long_opts_.set (option, size) != 0)
00540 {
00541 delete option;
00542 ACE_ERROR_RETURN
00543 ((LM_ERROR, ACE_LIB_TEXT ("Could not add long option to array.\n")),
00544 -1);
00545 }
00546 return 0;
00547 }
00548
00549 const ACE_TCHAR*
00550 ACE_Get_Opt::long_option (void) const
00551 {
00552 ACE_TRACE ("ACE_Get_Opt::long_option (void)");
00553 if (this->long_option_)
00554 return this->long_option_->name_;
00555 return 0;
00556 }
00557
00558 void
00559 ACE_Get_Opt::dump (void) const
00560 {
00561 ACE_TRACE ("ACE_Get_Opt::dump");
00562
00563 ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00564 ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\n")));
00565 ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00566 }
00567
00568 void
00569 ACE_Get_Opt::permute_args (void)
00570 {
00571 ACE_TRACE ("ACE_Get_Opt::permute_args");
00572
00573 int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
00574 ACE_TCHAR *swap;
00575 int opt_end = this->optind;
00576
00577 nnonopts = this->nonopt_end_ - this->nonopt_start_;
00578 nopts = opt_end - this->nonopt_end_;
00579 ncycle = ACE::gcd (nnonopts, nopts);
00580 cyclelen = (opt_end - this->nonopt_start_) / ncycle;
00581
00582 this->optind = this->optind - nnonopts;
00583
00584 for (i = 0; i < ncycle; i++)
00585 {
00586 cstart = this->nonopt_end_ + i;
00587 pos = cstart;
00588 for (j = 0; j < cyclelen; j++)
00589 {
00590 if (pos >= this->nonopt_end_)
00591 pos -= nnonopts;
00592 else
00593 pos += nopts;
00594 swap = this->argv_[pos];
00595
00596 ((ACE_TCHAR **)this->argv_)[pos] = argv_[cstart];
00597
00598 ((ACE_TCHAR **)this->argv_)[cstart] = swap;
00599 }
00600 }
00601 }
00602
00603 int
00604 ACE_Get_Opt::permute (void)
00605 {
00606 ACE_TRACE ("ACE_Get_Opt::permute");
00607
00608 if (this->nonopt_start_ != this->nonopt_end_
00609 && this->nonopt_start_ != this->optind)
00610 this->permute_args ();
00611
00612 this->nonopt_start_ = this->optind;
00613
00614
00615 while (this->optind < this->argc_
00616 && (this->argv_[this->optind][0] != '-'
00617 || this->argv_[this->optind][1] == '\0'))
00618 this->optind++;
00619
00620
00621 this->nonopt_end_ = this->optind;
00622
00623 if (this->optind != this->argc_
00624 && ACE_OS::strcmp (this->argv_[this->optind],
00625 ACE_LIB_TEXT ("--")) == 0)
00626 {
00627
00628 this->optind++;
00629
00630 if (this->nonopt_start_ != this->nonopt_end_
00631 && this->nonopt_end_ != this->optind)
00632 this->permute_args ();
00633 }
00634
00635 if (this->optind == this->argc_)
00636 {
00637 if (this->nonopt_start_ != this->nonopt_end_)
00638 this->optind = this->nonopt_start_;
00639 return EOF;
00640 }
00641 return 0;
00642 }
00643
00644 ACE_Get_Opt::ACE_Get_Opt_Long_Option::ACE_Get_Opt_Long_Option (const ACE_TCHAR *name,
00645 int has_arg,
00646 int val)
00647 : name_ (ACE::strnew(name)),
00648 has_arg_ (has_arg),
00649 val_ (val)
00650 {}
00651
00652 ACE_Get_Opt::ACE_Get_Opt_Long_Option::~ACE_Get_Opt_Long_Option (void)
00653 {
00654 delete [] ACE_const_cast (ACE_TCHAR*, this->name_);
00655 }
00656
00657 #if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
00658 template class ACE_Array<ACE_Get_Opt::ACE_Get_Opt_Long_Option *>;
00659 template class ACE_Array_Base<ACE_Get_Opt::ACE_Get_Opt_Long_Option *>;
00660 #elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
00661 #pragma instantiate ACE_Array<ACE_Get_Opt::ACE_Get_Opt_Long_Option *>
00662 #pragma instantiate ACE_Array_Base<ACE_Get_Opt::ACE_Get_Opt_Long_Option *>
00663 #endif