summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ace/ARGV.cpp329
-rw-r--r--ace/ARGV.h60
-rw-r--r--ace/ARGV.i48
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_;
}
+
+