diff options
-rw-r--r-- | ace/ARGV.cpp | 329 | ||||
-rw-r--r-- | ace/ARGV.h | 60 | ||||
-rw-r--r-- | ace/ARGV.i | 48 |
3 files changed, 325 insertions, 112 deletions
diff --git a/ace/ARGV.cpp b/ace/ARGV.cpp index 817e56f7586..370de0b8f97 100644 --- a/ace/ARGV.cpp +++ b/ace/ARGV.cpp @@ -23,122 +23,154 @@ ACE_ARGV::dump (void) const for (size_t i = 0; i < this->argc_; i++) ACE_DEBUG ((LM_DEBUG, "\nargv_[%i] = %s", i, this->argv_[i])); - ACE_DEBUG ((LM_DEBUG, "\nbuf = %s\n")); + ACE_DEBUG ((LM_DEBUG, "\nbuf = %s\n", this->buf_)); ACE_DEBUG ((LM_DEBUG, "\n")); ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); } -ACE_ARGV::ACE_ARGV (char buf[], - int substitute_env_args) - : argc_ (0), - argv_ (0), - buf_ (0) +// Creates this->argv_ out of this->buf_. New memory is allocated +// for each element of the array. This is used by the array-to-string +// style constructor and for creating this->argv_ when in iterative mode. +void +ACE_ARGV::string_to_array() { - ACE_TRACE ("ACE_ARGV::ACE_ARGV"); + ACE_TRACE("ACE_ARGV::string_to_array"); - if (buf == 0) + // Reset the number of arguments + this->argc_ = 0; + + if (this->buf_ == 0) return; - char *cp = buf; + char *cp = this->buf_; + + // First pass: count arguments. + + // '#' is the start-comment token.. + while (*cp != '\0' && *cp != '#') + { + // Skip whitespace.. + while (isspace (*cp)) + cp++; + + // Increment count and move to next whitespace.. + if (*cp != '\0') + this->argc_++; + + // Grok quotes.... + if (*cp == '\'' || *cp == '"') + { + char quote = *cp; + + // Scan past the string.. + for (cp++; *cp != '\0' && *cp != quote; cp++) + continue; + + // '\0' implies unmatched quote.. + if (*cp == '\0') + { + ACE_ERROR ((LM_ERROR, + "unmatched %c detected\n", quote)); + this->argc_--; + break; + } + else + cp++; + } + else // Skip over non-whitespace.... + while (*cp != '\0' && !isspace (*cp)) + cp++; + } + + // Second pass: copy arguments.. + char arg[BUFSIZ]; + + // Make a new argv vector of argc + 1 elements. + ACE_NEW (this->argv_, char *[this->argc_ + 1]); + + char *ptr = this->buf_; + + for (size_t i = 0; i < this->argc_; i++) + { + // Skip whitespace.. + while (isspace (*ptr)) + ptr++; + + // Copy next argument and move to next whitespace.. + if (*ptr == '\'' || *ptr == '"') + { + char quote = *ptr++; + + for (cp = arg; + *ptr != '\0' && *ptr != quote; + ptr++, cp++) + if (unsigned (cp - arg) < sizeof arg) + *cp = *ptr; + + *cp = '\0'; + if (*ptr == quote) + ptr++; + } + else + { + for (cp = arg; + *ptr && !isspace (*ptr); + ptr++, cp++) + if (unsigned (cp - arg) < sizeof arg) + *cp = *ptr; + *cp = '\0'; + } + + // Check for environment variable substitution here. + if (this->substitute_env_args_) + this->argv_[i] = ACE::strenvdup (arg); + else + this->argv_[i] = ACE_OS::strdup (arg); + } + + this->argv_[this->argc_] = 0; +} - // First pass: count arguments. - // '#' is the start-comment token.. - while (*cp != '\0' && *cp != '#') - { - // Skip whitespace.. - while (isspace (*cp)) - cp++; - - // Increment count and move to next whitespace.. - if (*cp != '\0') - this->argc_++; - - // Grok quotes.... - if (*cp == '\'' || *cp == '"') - { - char quote = *cp; - - // Scan past the string.. - for (cp++; *cp != '\0' && *cp != quote; cp++) - continue; - - // '\0' implies unmatched quote.. - if (*cp == '\0') - { - ACE_ERROR ((LM_ERROR, - "unmatched %c detected\n", quote)); - this->argc_--; - break; - } - else - cp++; - } - else // Skip over non-whitespace.... - while (*cp != '\0' && !isspace (*cp)) - cp++; - } - // Second pass: copy arguments.. - char arg[BUFSIZ]; +ACE_ARGV::ACE_ARGV (char buf[], + int substitute_env_args) + : argc_ (0), + substitute_env_args_ (substitute_env_args), + argv_ (0), + buf_ (0), + length_ (0), + state_ (TO_PTR_ARRAY) +{ + ACE_TRACE ("ACE_ARGV::ACE_ARGV char[] to char *[]"); - // Make a new argv vector of argc + 1 elements. - ACE_NEW (this->argv_, char *[this->argc_ + 1]); + if ((buf == 0) || (buf[0]==0)) + return; - for (size_t i = 0; i < this->argc_; i++) - { - // Skip whitespace.. - while (isspace (*buf)) - buf++; - - // Copy next argument and move to next whitespace.. - if (*buf == '\'' || *buf == '"') - { - char quote = *buf++; - - for (cp = arg; - *buf != '\0' && *buf != quote; - buf++, cp++) - if (unsigned (cp - arg) < sizeof arg) - *cp = *buf; - - *cp = '\0'; - if (*buf == quote) - buf++; - } - else - { - for (cp = arg; - *buf && !isspace (*buf); - buf++, cp++) - if (unsigned (cp - arg) < sizeof arg) - *cp = *buf; - *cp = '\0'; - } - - // Check for environment variable substitution here. - if (substitute_env_args) - this->argv_[i] = ACE::strenvdup (arg); - else - this->argv_[i] = ACE_OS::strdup (arg); - } + // Make an internal copy of the string + ACE_NEW(this->buf_, char[ACE_OS::strlen(buf) + 1]); + ACE_OS::strcpy(this->buf_, buf); - this->argv_[this->argc_] = 0; + // Create this->argv_ + this->string_to_array(); } ACE_ARGV::ACE_ARGV (char *argv[], int substitute_env_args) : argc_ (0), + substitute_env_args_ (substitute_env_args), argv_ (0), - buf_ (0) + buf_ (0), + length_ (0), + state_ (TO_STRING) { - ACE_TRACE ("ACE_ARGV::ACE_ARGV"); + ACE_TRACE ("ACE_ARGV::ACE_ARGV char*[] to char[]"); if (argv == 0 || argv[0] == 0) return; int buf_len = 0; - + // Determine the length of the buffer. for (int i = 0; argv[i] != 0; i++) @@ -146,7 +178,7 @@ ACE_ARGV::ACE_ARGV (char *argv[], char *temp; // Account for environment variables. - if (substitute_env_args + if (this->substitute_env_args_ && (argv[i][0] == '$' && (temp = ACE_OS::getenv (&argv[i][1])) != 0)) buf_len += ACE_OS::strlen (temp); @@ -160,7 +192,7 @@ ACE_ARGV::ACE_ARGV (char *argv[], // Step through all argv params and copy each one into buf; separate // each param with white space. - ACE_NEW (this->buf_, char[buf_len]); + ACE_NEW (this->buf_, char[buf_len + 1]); char *end = this->buf_; @@ -169,7 +201,7 @@ ACE_ARGV::ACE_ARGV (char *argv[], char *temp; // Account for environment variables. - if (substitute_env_args + if (this->substitute_env_args_ && (argv[j][0] == '$' && (temp = ACE_OS::getenv (&argv[j][1])) != 0)) end = ACE::strecpy (end, temp); @@ -180,22 +212,121 @@ ACE_ARGV::ACE_ARGV (char *argv[], *end++ = ' '; } + // Remember how many arguments there are + this->argc_ = j; + // Null terminate the string. *end = '\0'; } -// Free up the space allocated by the constructor.. +ACE_ARGV::ACE_ARGV(int substitute_env_args) + : argc_ (0), + substitute_env_args_ (substitute_env_args), + argv_ (0), + buf_ (0), + length_ (0), + state_ (ITERATIVE) +{ + ACE_TRACE ("ACE_ARGV::ACE_ARGV Iterative"); + + // Nothing to do yet -- the user puts in arguments via add() +}; + +int +ACE_ARGV::add(const char *next_arg) +{ + // Only allow this to work in the "iterative" verion -- the + // ACE_ARGVs created with the one argument constructor. + if (this->state_ != ITERATIVE) + return -1; + + // Put the new argument at the end of the queue + if (this->queue_.enqueue_tail ((char *)next_arg) < 0) { + ACE_ERROR ((LM_ERROR, "Can't add more to ARGV queue")); + return -1; + } + + this->length_ += ACE_OS::strlen(next_arg); + + this->argc_++; + + // Wipe argv_ and buf_ away so that they will be recreated if + // the user calls argv() or buf(). + if (this->argv_ != 0) { + for (int i = 0; this->argv_[i] != 0; i++) + ACE_OS::free ((void *) this->argv_[i]); + + delete [] this->argv_; + this->argv_ = 0; + } + + delete [] this->buf_; + this->buf_ = 0; + + return 0; +} + +// Free up argv_ and buf_ ACE_ARGV::~ACE_ARGV (void) { ACE_TRACE ("ACE_ARGV::~ACE_ARGV"); - if (this->argv_ == 0) - return; - - for (int i = 0; this->argv_[i] != 0; i++) - ACE_OS::free ((void *) this->argv_[i]); + + if (this->argv_ != 0) + for (int i = 0; this->argv_[i] != 0; i++) + ACE_OS::free ((void *) this->argv_[i]); delete [] this->argv_; delete [] this->buf_; } +// Create buf_ out of the queue_. This is only used in the +// "iterative" mode. + +int +ACE_ARGV::create_buf_from_queue(void) +{ + ACE_TRACE ("ACE_ARGV::create_buf_from_queue"); + + // If the are no arguments, don't do anything + if (this->argc_ <= 0) + return -1; + + delete [] this->buf_; + + ACE_NEW_RETURN(this->buf_, char[this->length_ + this->argc_], -1); + + // Get an iterator over the queue + ACE_Unbounded_Queue_Iterator<char *> iter(this->queue_); + + char **arg; + char *ptr = this->buf_; + size_t len; + int more = 0; + + while (!iter.done()) { + + // Get next argument from the queue + iter.next(arg); + + more = iter.advance(); + + len = ACE_OS::strlen(*arg); + + // Copy the argument into buf_ + ACE_OS::memcpy((void *)ptr, (const void *)(*arg), len); + + // Move the pointer down + ptr += len; + + // Put in an argument separating space + if (more != 0) + *ptr++ = ' '; + } + + // Put in the null terminator + *ptr = 0; + + return 0; +} + diff --git a/ace/ARGV.h b/ace/ARGV.h index 75f087a5155..27e4068bf98 100644 --- a/ace/ARGV.h +++ b/ace/ARGV.h @@ -11,7 +11,7 @@ // ARGV.h // // = AUTHOR -// Doug Schmidt +// Doug Schmidt, Everett Anderson // // ============================================================================ @@ -19,6 +19,7 @@ #define ACE_ARGUMENT_VECTOR_H #include "ace/ACE.h" +#include "ace/Containers.h" class ACE_Export ACE_ARGV // = TITLE @@ -32,27 +33,39 @@ public: // Converts <buf> into an <argv>-style vector of strings. If // <substitute_env_args> is enabled then we'll substitute the // environment variables for each $ENV encountered in the string. + // The subscript and argv() operations are not allowed on an + // ACE_ARGV created this way. ACE_ARGV (char *argv[], int substitute_env_args = 1); // Converts <argv> into a linear string. If <substitute_env_args> // is enabled then we'll substitute the environment variables for // each $ENV encountered in the string. + // The buf() operation is not allowed on an ACE_ARGV created + // this way. + + ACE_ARGV (int substitute_env_args = 1); + // Entry point for creating an char *[] command line iteratively + // via the add() method. The argv() and buf() method calls are + // allowed, and the result is recreated when called multiple times. + // The subscript operator is not allowed. ~ACE_ARGV (void); // Destructor. // = Accessor arguments. - char *operator[] (int index) const; - // Returns the <index>th string in the ARGV array. + const char *operator[] (int index); + // Returns the <index>th string in the ARGV array. - char **argv (void) const; + char **argv (void); // Returns the <argv> array. Caller should not delete this memory - // since the <ARGV> destructor will delete it. + // since the <ARGV> destructor will delete it. If the caller modifies + // the array in the iterative mode, the changes are not saved to the + // queue. size_t argc (void) const; // Returns <argc>. - char *buf (void) const; + const char *buf (void); // Returns the <buf>. Caller should not delete this memory since // the <ARGV> destructor will delete it. @@ -62,7 +75,34 @@ public: ACE_ALLOC_HOOK_DECLARE; // Declare the dynamic allocation hooks. + int add(const char *next_arg); + // Add another argument. This only works in the ITERATIVE state. + + int state(void) const; + // What state is this ACE_ARGV in? + + // These are the states possible via the different constructors. + enum States + { + TO_STRING = 1, // ACE_ARGV converts buf[] to char *argv[] + TO_PTR_ARRAY = 2, // ACE_ARGV converts char *argv[] to buf[] + ITERATIVE = 3 // Builds buf[] or char *argv[] iteratively with add() + }; + private: + + int substitute_env_args_; + // Replace args with environment variable values? + + int state_; + // Current state marker + + int create_buf_from_queue(void); + // Creates buf_ from the queue, deletes previous buf_ + + void string_to_array(void); + // Converts buf_ into the char *argv[] format + size_t argc_; // Number of arguments in the ARGV array. @@ -71,6 +111,14 @@ private: char *buf_; // Buffer containing the <argv> contents. + + size_t length_; + // Total length of the arguments in the queue, not counting + // separating spaces + + ACE_Unbounded_Queue<char *> queue_; + // Queue which keeps user supplied arguments. This is only + // active in the "iterative" mode. }; #if defined (__ACE_INLINE__) diff --git a/ace/ARGV.i b/ace/ARGV.i index 5bb9d242252..94eb114cae5 100644 --- a/ace/ARGV.i +++ b/ace/ARGV.i @@ -3,6 +3,7 @@ // ARGV.i +// Return the number of args ACE_INLINE size_t ACE_ARGV::argc (void) const { @@ -10,23 +11,56 @@ ACE_ARGV::argc (void) const return this->argc_; } -ACE_INLINE char * -ACE_ARGV::buf (void) const +// Return the state of this ACE_ARGV +ACE_INLINE int +ACE_ARGV::state(void) const +{ + ACE_TRACE ("ACE_ARGV::state"); + return this->state_; +} + +// Return the arguments in a space-separated string +ACE_INLINE const char * +ACE_ARGV::buf (void) { ACE_TRACE ("ACE_ARGV::buf"); - return this->buf_; + + if (this->buf_ == 0 && this->state_ == ITERATIVE) + this->create_buf_from_queue(); + + return (const char *)this->buf_; } -ACE_INLINE char * -ACE_ARGV::operator[] (int i) const +// Subscript operator. +ACE_INLINE const char * +ACE_ARGV::operator[] (int i) { ACE_TRACE ("ACE_ARGV::operator[]"); - return this->argv_[i]; + + // Don't go out of bounds + if (i >= this->argc_) + return 0; + + return (const char *)(this->argv()[i]); } +// Return the arguments in an entry-per-argument array ACE_INLINE char ** -ACE_ARGV::argv (void) const +ACE_ARGV::argv (void) { ACE_TRACE ("ACE_ARGV::argv"); + + // Try to create the argv_ if it isn't there + if (this->argv_ == 0) { + + if (this->state_ == ITERATIVE && this->buf_ == 0) + this->create_buf_from_queue(); + + // Convert buf_ to argv_ + this->string_to_array(); + } + return this->argv_; } + + |