summaryrefslogtreecommitdiff
path: root/ace
diff options
context:
space:
mode:
authoreea1 <eea1@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1997-08-14 16:25:22 +0000
committereea1 <eea1@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1997-08-14 16:25:22 +0000
commitf9d468f6069939f27dcb7248d66ab5d1a992ec14 (patch)
tree82ab637c75f06fe5aa877d776a95b4b183ba9e3b /ace
parentfcab06e944937664d6c990471053e3d3cb0290d2 (diff)
downloadATCD-f9d468f6069939f27dcb7248d66ab5d1a992ec14.tar.gz
I added another behavior to ACE_ARGV: now a user can iteratively build
the parameter set with add(). I also made this class more consistent so that the member functions will work the same no matter which constructor is used. The only exception is that add() only does something useful in iterative mode.
Diffstat (limited to 'ace')
-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_;
}
+
+