1 karl 1.29 //%2005////////////////////////////////////////////////////////////////////////
|
2 mike 1.13 //
|
3 karl 1.28 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
|
6 karl 1.27 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.28 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
|
9 karl 1.29 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 mike 1.13 //
12 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
13 kumpf 1.19 // of this software and associated documentation files (the "Software"), to
14 // deal in the Software without restriction, including without limitation the
15 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
16 mike 1.13 // sell copies of the Software, and to permit persons to whom the Software is
17 // furnished to do so, subject to the following conditions:
18 //
|
19 kumpf 1.19 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
20 mike 1.13 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
21 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
22 kumpf 1.19 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
23 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
25 mike 1.13 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 //==============================================================================
29 //
30 // Author: Bob Blair (bblair@bmc.com)
31 //
|
32 mike 1.14 // Modified By: Carol Ann Krug Graves, Hewlett-Packard Company
33 // (carolann_graves@hp.com)
|
34 mike 1.13 //
35 //%/////////////////////////////////////////////////////////////////////////////
36
37
38 //
39 // implementation of getoopt
40
|
41 kumpf 1.15 #include <Pegasus/Common/PegasusVersion.h>
|
42 humberto 1.26 #include <Pegasus/Common/MessageLoader.h> //l10n
|
43 kumpf 1.15
|
44 mike 1.13 #include "getoopt.h"
45 #include <cctype>
46 #include <cstdlib>
47
48 PEGASUS_USING_STD;
49
50 //-----------------------------------------------------------------------
51 // Implementation of class Optarg
52 // An Optarg is created for each parameter on the command line.
53 //-----------------------------------------------------------------------
54
55 // Constructors
56 // Default Constructor
57 Optarg::Optarg() : _name(""), _opttype(REGULAR), _value("") {
58 }
59
60 // All-in-one
61 Optarg::Optarg(const String &name, opttype type, const String &value) :
62 _name(name), _opttype(type), _value(value) {
63 }
64
65 mike 1.13 // Destructor
66 Optarg::~Optarg() {};
67
68 //-----------------------------------------------------------------------
69 // Set the class members
70 //-----------------------------------------------------------------------
71
72 // Set the _name member
73 void
74 Optarg::setName(const String &name) {
75 _name = name;
76 }
77
78 // Set the _opttype member
79 void
80 Optarg::setType(opttype type) {
81 _opttype = type;
82 }
83
84 // Set the _value member
85 void
86 mike 1.13 Optarg::setValue(const String &value) {
87 _value = value;
88 }
89
90 //-----------------------------------------------------------------------
91 // Retrieve class members
92 //-----------------------------------------------------------------------
93
94 // Get the _name member
95 const String &
96 Optarg::getName() const { return _name; }
97
98 // Get the _name member using getopt() terminology
99 const String &
100 Optarg::getopt() const { return _name; }
101
102 // Get the _type member
103 Optarg::opttype
104 Optarg::getType() const { return _opttype; }
105
106 //-------------------------------------------------------------------
107 mike 1.13 // Ways to get the _value member
108 //-------------------------------------------------------------------
109
110 // Return _value as const String ref
111 const String &
112 Optarg::Value() const { return _value; }
113
114 // Same thing as Value(), but using getopt() terminology
115 const String &
116 Optarg::optarg() const { return _value; }
117
118 // Fill in a caller-provided String
119 void
120 Optarg::Value(String &s) const { s = _value; }
121
122 // Fill in a caller-provided int with the integer conversion of the value.
|
123 kumpf 1.24 void Optarg::Value (int &i) const throw (TypeMismatchException)
|
124 mike 1.13 {
|
125 kumpf 1.23 CString cs = _value.getCString();
|
126 mike 1.14 const char* s = cs;
127 Boolean valid = true;
128 Uint32 j;
129 for (j = 0; j < strlen (s); j++)
130 {
131 if ((!isdigit (s [j])) && (!isspace (s [j])) && (s [j] != '+') &&
132 (s [j] != '-'))
133 {
134 valid = false;
135 break;
136 }
137 }
138 if (valid)
139 {
|
140 kumpf 1.25 Sint64 i64;
141 if ( !(sscanf (s, "%" PEGASUS_64BIT_CONVERSION_WIDTH "d", &i64)) ||
142 (i64 != Sint64(Sint32(i64))) )
|
143 mike 1.14 {
|
144 kumpf 1.24 throw TypeMismatchException ();
|
145 mike 1.14 }
|
146 kumpf 1.25
147 i = Sint32(i64);
|
148 mike 1.14 }
149 else
150 {
|
151 kumpf 1.24 throw TypeMismatchException ();
|
152 mike 1.14 }
|
153 mike 1.13 }
154
155 // Fill in a caller-provided unsigned int
|
156 kumpf 1.24 void Optarg::Value (unsigned int &i) const throw (TypeMismatchException)
|
157 mike 1.14 {
|
158 kumpf 1.23 CString cs = _value.getCString();
|
159 mike 1.14 const char* s = cs;
160 Boolean valid = true;
161 Uint32 j;
162
163 for (j = 0; j < strlen (s); j++)
164 {
165 if ((!isdigit (s [j])) && (!isspace (s [j])))
166 {
167 valid = false;
168 break;
169 }
170 }
171 if (valid)
172 {
|
173 kumpf 1.25 Uint64 i64;
174 if ( !(sscanf (s, "%" PEGASUS_64BIT_CONVERSION_WIDTH "u", &i64)) ||
|
175 david.dillard 1.30 (i64 > 0xFFFFFFFF))
|
176 mike 1.14 {
|
177 kumpf 1.24 throw TypeMismatchException ();
|
178 mike 1.14 }
|
179 kumpf 1.25
180 i = Uint32(i64);
|
181 mike 1.14 }
182 else
183 {
|
184 kumpf 1.24 throw TypeMismatchException ();
|
185 mike 1.14 }
|
186 mike 1.13 }
187
|
188 kumpf 1.23 // Fill in a caller-provided long
|
189 mike 1.13 void
190 Optarg::Value(long &l) const {
|
191 kumpf 1.23 l = (long)atoi(_value.getCString());
|
192 mike 1.13 }
193
|
194 kumpf 1.23 // Fill in a caller-provided unsigned long
|
195 mike 1.13 void
196 Optarg::Value(unsigned long &l) const {
|
197 kumpf 1.23 l = (unsigned long)atoi(_value.getCString());
|
198 mike 1.13 }
199
|
200 kumpf 1.23 // Fill in a caller-provided double
|
201 mike 1.13 void
202 Optarg::Value(double &d) const {
|
203 kumpf 1.23 d = (double)atof(_value.getCString());
|
204 mike 1.13 }
205
206 //--------------------------------------------------------------------
207 // Provide information about the flag, if any
208 //--------------------------------------------------------------------
209
210 // Is the option value is bound to a flag?
211 Boolean
212 Optarg::isFlag() const { return (_opttype == FLAG || _opttype == LONGFLAG); }
213
214 // Is it bound to a long-named flag?
215 Boolean
216 Optarg::isLongFlag() const { return (_opttype == LONGFLAG); }
217
218 //-----------------------------------------------------------------------
219 // print the members as a formatted String
220 //-----------------------------------------------------------------------
221 ostream &
222 Optarg::print(ostream &os) const {
223 os << "{name:(" << getName();
224 os << ") type:(";
225 mike 1.13 switch (getType()) {
226 case FLAG: os << "FLAG"; break;
227 case LONGFLAG: os << "LONGFLAG"; break;
228 case REGULAR: os << "REGULAR"; break;
229 }
230 os << ") value:(" << Value() << ")}";
231 return os;
232 }
233
234
235
236 //---------------------------------------------------------------------
237 // Implementation of class getoopt
238 //---------------------------------------------------------------------
239
240 // Constructors and destructor
241
242 // Default constructor. The optional String is in the format of
243 // a getopt() optstring
244 getoopt::getoopt(const char *optstring)
245 {
246 mike 1.13 if (optstring) {
247 addFlagspec(optstring);
248 }
249 }
250
251 getoopt::~getoopt() {;}
252
253 //----------------------------------------------------------------------
254 // methods to register program-defined flags and their characteristics
255 // The flags are encapsulated in the struct flagspec, an array of which
256 // is a member of this class.
257 // There are also methods to deregister flags. This is done by resetting
258 // a flagspec's active flag.
259 //----------------------------------------------------------------------
260
261 // Parse through a getopt() optstring and create flagspecs from each
262 // short flag.
263 Boolean
264 getoopt::addFlagspec(const String &opt) {
265 unsigned int size = opt.size();
266 if (size == 0)
267 mike 1.13 return false;
268 for (unsigned int i = 0; i < size; i++) {
269 char c = opt[i];
270 if ( ((i + 1) < size) && (opt[i+1] == ':') ) {
271 if (!(addFlagspec(c, true))) {
272 return false;
273 }
274 ++i;
275 } else {
276 if (!(addFlagspec(c, false)))
277 return false;
278 }
279 }
280 return true;
281 }
282
283 // Create a filespec from a single short flag and push it onto the array
284 Boolean
285 getoopt::addFlagspec(char flag, Boolean hasarg) {
286 if (flag == '*') {
|
287 humberto 1.26 //l10n
288 MessageLoaderParms parms("getoopt.getoopt.CANT_NAME_FLAG",
289 "You can't have a flag named '$0'",
290 flag);
291 addError(MessageLoader::getMessage(parms));
292 //addError("You can't have a flag named '*'");
293 //l10n end
|
294 mike 1.13 return false;
295 }
296 flagspec fs;
297 char c[2];
298 c[0] = flag;
299 c[1] = 0;
300 fs.name = c;
301 fs.argtype = hasarg ? 1 : 0;
302 fs.islong = false;
303 fs.active = true;
304 _flagspecs.append(fs);
305 return true;
306 }
307
308 // Create a flagspec from a single long flag and push it onto the array
309 Boolean
310 getoopt::addLongFlagspec(const String &name, argtype type) {
311 flagspec fs;
312
313 // Changing "fs.name = name" to the following line masks an ugly crash
314 // which occurs when compiling with debug option on WIN32:
315 mike 1.13
316 fs.name = name;
317
318 fs.argtype = type;
319 fs.islong = true;
320 fs.active = true;
321 _flagspecs.append(fs);
322 return true;
323 }
324
325 // Unregister a flagspec
326 Boolean
327 getoopt::removeFlagspec(char opt) {
328 flagspec *fs = getFlagspecForUpdate(opt);
329 if (fs) {
330 fs->active = false;
331 return true;
332 }
333 return false;
334 }
|
335 mike 1.14
336 /**
337 In the valid option definition string, following an option,
338 indicates that the preceding option takes a required argument.
339 */
340 const char getoopt::GETOPT_ARGUMENT_DESIGNATOR = ':';
|
341 mike 1.13
342 //--------------------------------------------------------------------
343 // Routines for parsing the command line
344 //--------------------------------------------------------------------
345
346 //------------------------
347 // Static functions
348 //------------------------
349
350 // Parse out the flagname and the value from a long flag option that
351 // may be in the form
352 // --longflag=value
353 static void
354 partsFromLongOpt (const String &s, String &name, String &value) {
355 for (unsigned int i = 0; i < s.size(); i++) {
356 if (s[i] == '=') {
357 name = s.subString(0, i);
358 value = s.subString(i+1);
359 return;
360 }
361 }
362 mike 1.13 name = s;
363 value = "";
364 }
365
366 // Create an Optarg instance from a long flag String like
367 // --longflag=value
368 // (The =value is optional).
369 static void
370 optargFromLongOpt(Optarg &o, const String &arg) {
371 String name;
372 String value;
373 partsFromLongOpt(arg, name, value);
374 o.setName(name);
375 o.setType(Optarg::LONGFLAG);
376 o.setValue(value);
377 }
378
379 // Create an Optarg instance from a short flag String like
380 // -fValue
381 // (The Value part is optional)
382 static void
383 mike 1.13 optargFromShortOpt(Optarg &o, const char *arg) {
384 char name[2];
385 name[0] = arg[0];
386 name[1] = 0;
387 o.setName(name);
388 o.setType(Optarg::FLAG);
389 const char *p = arg + 1;
390 o.setValue(p);
391 }
392
393 // Look at a command line option and determine whether it is a
394 // long flag, a short flag or an unflagged option.
395 static int
396 catagorize(const char *s) {
397 if (s[0] != '-')
398 return 0;
399 else
400 if (s[1] == '-')
401 return 2;
402 return 1;
403 }
404 mike 1.13
405 // Push an Optarg onto our array
406 static void
407 addarg(getoopt::Arg_List&list, const Optarg &o) {
408 //o.print(cout);
409 list.append(o);
410 }
411
412 // Create an Optarg from its members and push it onto the array
413 static void
414 addarg(getoopt::Arg_List&list, const String &name, Optarg::opttype type,
415 const String &value) {
416 Optarg *o = new Optarg(name, type, value);
417 addarg(list, *o);
418 delete o;
419 }
420
421 // Take an array of arguments and append it to another
422 static void
423 copyargs(getoopt::Arg_List &out, const getoopt::Arg_List &in) {
|
424 kumpf 1.21 Uint32 size = in.size();
425 for (Uint32 i = 0; i < size; i++) {
426 addarg(out, in[i]);
|
427 mike 1.13 }
428 }
429
430 //------------------------------------
431 // The parse method: Way too long.
432 // Note that flag args are pushed
433 // onto the stack, then the regular
434 // args are appended, sorting them
435 // to the rear the way getopt() does.
436 //------------------------------------
437 Boolean
438 getoopt::parse(int argc, char **argv) {
439 Optarg o;
440 int cat;
441 const flagspec *fs;
442 Arg_List nonflagargs;
443 enum states {START, ARGEXPECTED};
444 states state = START;
445 for (unsigned int i = 1; i < (unsigned int)argc; i++) {
446 unsigned int endsize = strlen(argv[i]);
447 switch (state) {
448 mike 1.13 case START:
449 cat = catagorize(argv[i]);
450 switch (cat) {
451 case 0: // non-flag command line argument
452 addarg(nonflagargs, "", Optarg::REGULAR, argv[i]);
453 break;
454 case 1: // short (1-character) flag
455 {
456 unsigned int argpos = 1;
457 while (argpos < endsize) {
458 char c = argv[i][argpos];
459 fs = getFlagspec(c); // Short flag
460 String temp = argv[i];
461 String name = temp.subString(argpos, 1);
462 if (!fs) { // See if we recognize it
|
463 humberto 1.26 //l10n
464 MessageLoaderParms parms("getoopt.getoopt.UNKNOWN_FLAG",
465 "Unknown flag $0$1",
466 "-",
467 name);
468 addError(MessageLoader::getMessage(parms));
469 //addError("Unknown flag -" + name);
470 //l10n end
471 argpos++;
|
472 mike 1.13 } else {
473 if (fs->argtype == NOARG) { // Should this flag be bound
474 addarg(_args, name, Optarg::FLAG, ""); // NO
475 argpos++;
476 } else { // YES -- the value is here or in the next arg
477 optargFromShortOpt(o, &argv[i][argpos]);
478 if (o.Value() == "") { // No value yet
479 state = ARGEXPECTED;
480 } else {
481 addarg(_args, o);
482 }
483 argpos = endsize;
484 }
485 }
486 }
487 } // end subcase 1
488 break;
489 case 2: // long (--xyz) flag
490 {
491 String arg = &(argv[i][2]);
492 optargFromLongOpt(o, arg);
493 mike 1.13 fs = getFlagspec(o.getName());
494 if (!fs) { // see if we recognize this flag
|
495 humberto 1.26 //l10n
496 //String temp = "Unknown flag ";
497 //addError(temp + o.getName());
498 MessageLoaderParms parms("getoopt.getoopt.UNKNOWN_FLAG",
499 "Unknown flag $0$1",
500 "",
501 o.getName());
502 addError(MessageLoader::getMessage(parms));
503 //l10n end
|
504 mike 1.13 } else {
505 // this is a long flag we know about
|
506 kumpf 1.16 if (o.optarg() != "" || fs->argtype != MUSTHAVEARG) {
|
507 mike 1.13 addarg(_args, o);
508 state = START; // we have a completed long flag
509 } else { // no value yet, and we expect one
|
510 kumpf 1.16 if (fs->argtype == MUSTHAVEARG) {
|
511 mike 1.13 state = ARGEXPECTED;
512 }
513 }
514 }
515 break;
516 } // end subcase 2
517 } // end switch catagorize()
518 break; // end of case START
519
520 case ARGEXPECTED:
521 if (argv[i][0] == '-') {
|
522 humberto 1.26 //l10n
523 //addError("Missing required value for flag " + o.getopt());
524 MessageLoaderParms parms("getoopt.getoopt.MISSING_VALUE_FOR_FLAG",
525 "Missing required value for flag $0",
526 o.getopt());
527 addError(MessageLoader::getMessage(parms));
528 //l10n end
|
529 mike 1.13 i--;
530 } else {
531 o.setValue(argv[i]);
532 }
533 addarg(_args, o);
534 state = START;
535 break;
536 } // end switch
537 } // end for
538 if (state != START) {
|
539 humberto 1.26 //l10n
540 //addError("Missing required value for flag " + o.getName());
541 MessageLoaderParms parms("getoopt.getoopt.MISSING_VALUE_FOR_FLAG",
542 "Missing required value for flag $0",
543 o.getName());
544 addError(MessageLoader::getMessage(parms));
545 //l10n end
|
546 mike 1.13 }
547 copyargs(_args, nonflagargs);
548 return !_errorStrings.size();
549 }
550
551 //----------------------------------------------------------------------
552 // Methods to retrieve the command line arguments
553 //----------------------------------------------------------------------
554
555 //----------------------------------------------
556 // Access the command line arguments by index
557 //----------------------------------------------
558
559 // Index operator
560 const Optarg &
561 getoopt::operator[](unsigned int n) {
562 unsigned int lim = _args.size();
563 if (n < lim)
564 return _args[n];
565 else
566 return _emptyopt;
567 mike 1.13 }
568
569 // Return first index
570 unsigned int
571 getoopt::first() const { return 0; }
572
573 // Return one past last index
574 unsigned int
575 getoopt::last() const { return _args.size(); }
576
577 //-----------------------------------------------
578 // Access the command line arguments ad-hoc
579 //-----------------------------------------------
580
581 // Return the number of times a short flag is set
582 // on the command line
583 unsigned int
584 getoopt::isSet(char c) const {
585 unsigned int cnt = 0;
586 for (unsigned int i = 0; i < _args.size(); i++) {
587 const Optarg &o = _args[i];
588 mike 1.13 if (o.getType() == Optarg::FLAG) {
589 const String &s = o.getopt();
590 if (s[0] == c) {
591 cnt++;
592 }
593 }
594 }
595 return cnt;
596 }
597
598 // Return the number of times any flag is set
599 // on the command line
600 unsigned int
601 getoopt::isSet(const String &s) const {
602 unsigned int cnt = 0;
603 for (unsigned int i = 0; i < _args.size(); i++) {
604 const Optarg &o = _args[i];
605 if (o.getopt() == s) {
606 cnt++;
607 }
608 }
609 mike 1.13 return cnt;
610 }
611
612 // Return the String value of the nth instance of
613 // a particular short flag on the command line
614 const String &
615 getoopt::value(char opt, unsigned int idx) const {
616 unsigned int cnt = 0;
617 for (unsigned int i = 0; i < _args.size(); i++) {
618 const Optarg &o = _args[i];
619 if (o.getType() == Optarg::FLAG) {
620 const String &s = o.getopt();
621 if (s[0] == opt) {
622 if (cnt == idx) {
623 return o.optarg();
624 } else {
625 cnt++;
626 }
627 }
628 }
629 }
630 mike 1.13 return(emptystring);
631 }
632
633 // Return the nth instance of any flag on the command line
634 const String &
635 getoopt::value(const String &opt, unsigned int idx) const {
636 unsigned int cnt = 0;
637 for (unsigned int i = 0; i < _args.size(); i++) {
638 const Optarg &o = _args[i];
639 if (o.optarg() == opt) {
640 if (cnt == idx) {
641 return o.getopt();
642 } else {
643 cnt++;
644 }
645 }
646 }
647 return(emptystring);
648 }
649
650 // Of the command line arguments, how many are flags?
651 mike 1.13 unsigned int
652 getoopt::flagcnt() const {
653 unsigned int cnt = 0;
|
654 kumpf 1.21 for (Uint32 i = 0; i < _args.size(); i++) {
655 if (_args[i].getType() != Optarg::REGULAR)
|
656 mike 1.13 cnt++;
657 }
658 return cnt;
659 }
660
661 // How many command line arguments were there?
662 unsigned int
663 getoopt::size() const {
664 return _args.size();
665 }
666
667 // Return the list of command line arguments for use by
668 // the program.
669 const getoopt::Arg_List &
670 getoopt::getArgs() const { return _args; }
671
672
673 //-----------------------------------------------------------
674 // Routines dealing with errors during parsing
675 // FIXME: This needs to be reworked so that the error text
676 // is hidden and provided by the caller
677 mike 1.13 //----------------------------------------------------------
678
679 // Add an error into the list
680 void
681 getoopt::addError(const String &s)
682 {
683 _errorStrings.append(s);
684 }
685
686 // Return a list of the errors
687 const getoopt::Error_List &
688 getoopt::getErrorStrings() const {
689 return _errorStrings;
690 }
691
692 // Did any errors occur?
693 Boolean
694 getoopt::hasErrors() const {
695 return _errorStrings.size() ? true : false;
696 }
697
698 mike 1.13
699
700 flagspec *
701 getoopt::getFlagspecForUpdate(const String &s) {
702 for (unsigned int i = 0; i < _flagspecs.size(); i++) {
703 flagspec &o = _flagspecs[i];
704 if (o.islong && s == o.name)
705 return &_flagspecs[i];
706 }
707 return 0;
708 }
709
710 const flagspec *
711 getoopt::getFlagspec(const String &s) {
712 return (const flagspec *)getFlagspecForUpdate(s);
713 }
714
715 ostream &
716 getoopt::printErrors(ostream &os) const {
|
717 kumpf 1.21 for (Uint32 i = 0; i < _errorStrings.size(); i++) {
718 os << "> " << _errorStrings[i] << endl;
|
719 mike 1.13 }
720 return os;
721 }
722
723 void
724 getoopt::printErrors(String &s) const {
|
725 kumpf 1.21 for (Uint32 i = 0; i < _errorStrings.size(); i++) {
|
726 kumpf 1.22 s.append("> " + _errorStrings[i] + "\n");
|
727 mike 1.13 }
728 }
729
730 //---------------------------------------------------------------
731 // Private methods
732 //---------------------------------------------------------------
733 flagspec *
734 getoopt::getFlagspecForUpdate(char c) {
735 for (unsigned int i = 0; i < _flagspecs.size(); i++) {
736 flagspec &o = _flagspecs[i];
737 if (!o.islong && c == o.name[0])
738 return &_flagspecs[i];
739 }
740 return 0;
741 }
742
743 const flagspec *
744 getoopt::getFlagspec(char c) {
745 return (const flagspec *)getFlagspecForUpdate(c);
746 }
|