Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members

HeyParser.cc

Go to the documentation of this file.
00001 /*
00002  * HeyParser.cc
00003  *
00004  * Copyright (c) 2003 The University of Utah and the Flux Group.
00005  * All rights reserved.
00006  *
00007  * This file is licensed under the terms of the GNU Public License.  
00008  * See the file "license.terms" for restrictions on redistribution 
00009  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
00010  */
00011 
00012 /**
00013  * @file HeyParser.cc
00014  *
00015  * Implementation file for the HeyParser class.
00016  */
00017 
00018 #include "config.h"
00019 
00020 #include <string.h>
00021 #include <assert_pp.h>
00022 
00023 #include "HeyParser.hh"
00024 
00025 HeyPropertyInfo HeyPropertyInfo::HPI_NULL(NULL, 0, NULL, NULL);
00026 
00027 const char *HeyParser::hp_what_strings[WHAT_MAX] = {
00028     "shutdown",
00029     "list",
00030     "get",
00031     "set",
00032     "create",
00033     "delete",
00034     "execute",
00035     "getsuites",
00036 };
00037 
00038 HeyParser::HeyParser(int argc, const char *argv[])
00039     throw (HeyParserException)
00040 {
00041     require(argc > 0);
00042     require(argv != NULL);
00043 
00044     /* Need atleast three args (program name, server name, what value) */
00045     if( argc < 3 )
00046     {
00047         throw HeyParserException("Missing required arguments.");
00048     }
00049 
00050     /* Store the arguments and then */
00051     this->hp_ArgCount = argc;
00052     this->hp_ArgValue = argv;
00053     this->hp_ArgIndex = 3;
00054 
00055     /* ... verify the server name, */
00056     if( strlen(argv[1]) == 0 )
00057     {
00058         throw HeyParserException("Empty server name");
00059     }
00060 
00061     /* ... figure out the 'what' value, and */
00062     if( (strcasecmp(argv[2], "shutdown") == 0) ||
00063         (strcasecmp(argv[2], "exit") == 0) ||
00064         (strcasecmp(argv[2], "quit") == 0) )
00065     {
00066         this->hp_What = SHUTDOWN;
00067     }
00068     else if( strcasecmp(argv[2], "list") == 0 )
00069     {
00070         this->hp_What = LIST_PROPERTIES;
00071     }
00072     else if( strcasecmp(argv[2], "get") == 0 )
00073     {
00074         this->hp_What = GET_PROPERTY;
00075     }
00076     else if( strcasecmp(argv[2], "set") == 0 )
00077     {
00078         this->hp_What = SET_PROPERTY;
00079     }
00080     else if( strcasecmp(argv[2], "create") == 0 )
00081     {
00082         this->hp_What = CREATE_PROPERTY;
00083     }
00084     else if( strcasecmp(argv[2], "delete") == 0 )
00085     {
00086         this->hp_What = DELETE_PROPERTY;
00087     }
00088     else if( strcasecmp(argv[2], "execute") == 0 )
00089     {
00090         this->hp_What = EXECUTE_PROPERTY;
00091     }
00092     else if( strcasecmp(argv[2], "getsuites") == 0 )
00093     {
00094         this->hp_What = GET_SUITES;
00095     }
00096     else
00097     {
00098         throw HeyParserException("Unknown verb value.");
00099     }
00100 
00101     /* ... push any property lists, */
00102     while( (this->hp_ArgIndex < this->hp_ArgCount) &&
00103            (strcasecmp(this->hp_ArgValue[this->hp_ArgIndex], "to") != 0) &&
00104            (strcasecmp(this->hp_ArgValue[this->hp_ArgIndex], "with") != 0) )
00105     {
00106         struct Pair pair;
00107 
00108         this->nextProperty(pair.p_Name, pair.p_Value);
00109         this->hp_PropertyStack.push(pair);
00110     }
00111 
00112     /* ... pickup the 'to' value, if this is a set, */
00113     if( this->hp_What == SET_PROPERTY )
00114     {
00115         try
00116         {
00117             const char *arg;
00118 
00119             arg = this->consumeArg();
00120             if( strcasecmp(arg, "to") != 0 )
00121             {
00122                 throw HeyParserException("Expecting 'to' keyword, found", arg);
00123             }
00124         }
00125         catch(const HeyParserException &e)
00126         {
00127             throw HeyParserException("Missing 'to' keyword.");
00128         }
00129         
00130         try
00131         {
00132             this->hp_ToValue = this->consumeArg();
00133         }
00134         catch(const HeyParserException &e)
00135         {
00136             throw HeyParserException("Missing 'to' value.");
00137         }
00138     }
00139 
00140     /* ... and finally, eliminate the 'with' keyword. */
00141     if( (this->hp_ArgIndex < this->hp_ArgCount) &&
00142         (strcasecmp(this->hp_ArgValue[this->hp_ArgIndex], "with") == 0) )
00143     {
00144         int lpc, with_count;
00145         
00146         this->hp_ArgIndex += 1;
00147         if( this->hp_ArgIndex == this->hp_ArgCount )
00148         {
00149             throw HeyParserException("No arguments after 'with'");
00150         }
00151         for( lpc = this->hp_ArgIndex, with_count = 0;
00152              lpc < this->hp_ArgCount;
00153              lpc++ )
00154         {
00155             with_count += 1;
00156             if( strchr(this->hp_ArgValue[lpc], '=') )
00157             {
00158                 with_count += 1;
00159             }
00160         }
00161         if( (with_count % 2) == 1 )
00162         {
00163             throw HeyParserException("Odd number of 'with' arguments");
00164         }
00165     }
00166 
00167     ensure(this->hp_What >= 0);
00168     ensure(this->hp_What < WHAT_MAX);
00169     ensure(this->hp_ArgValue != NULL);
00170     ensure((this->hp_What != SET_PROPERTY) || (this->hp_ToValue != NULL));
00171     ensure(this->hp_ArgIndex > 0);
00172 }
00173 
00174 HeyParser::~HeyParser(void)
00175 {
00176     this->hp_ArgCount = 0;
00177     this->hp_ArgValue = NULL;
00178     this->hp_ToValue = NULL;
00179     this->hp_ArgIndex = -1;
00180 }
00181 
00182 const char *HeyParser::consumeArg(void)
00183     throw (HeyParserException)
00184 {
00185     const char *retval;
00186 
00187     if( this->hp_ArgIndex >= this->hp_ArgCount )
00188     {
00189         throw HeyParserException("No more arguments");
00190     }
00191     
00192     retval = this->hp_ArgValue[this->hp_ArgIndex];
00193     this->hp_ArgIndex += 1;
00194 
00195     return( retval );
00196 }
00197 
00198 void HeyParser::nextProperty(const char *&name_out, const char *&value_out)
00199     throw (HeyParserException)
00200 {
00201     const char *arg;
00202     
00203     name_out = NULL;
00204     value_out = NULL;
00205     
00206     if( (this->hp_ArgIndex > 3) ||
00207         ((this->hp_What == GET_SUITES) && (this->hp_ArgIndex == 3)) )
00208     {
00209         /* Expect 'of' after the first property is processed. */
00210         if( strcasecmp(this->consumeArg(), "of") == 0 )
00211         {
00212         }
00213         else
00214         {
00215             throw HeyParserException("Expecting 'of' keyword");
00216         }
00217     }
00218 
00219     /* The property name is always required. */
00220     name_out = this->consumeArg();
00221     try
00222     {
00223         arg = this->consumeArg();
00224         if( (strcasecmp(arg, "of") == 0) ||
00225             (strcasecmp(arg, "to") == 0) ||
00226             (strcasecmp(arg, "with") == 0) )
00227         {
00228             /*
00229              * Detected a preposition separating properties.  Back up since it
00230              * will be consumed on the next go around.
00231              */
00232             this->hp_ArgIndex -= 1;
00233         }
00234         else
00235         {
00236             value_out = arg;
00237         }
00238     }
00239     catch(const HeyParserException &e)
00240     {
00241         /* Ignore missing value. */
00242     }
00243 }
00244 
00245 void HeyParser::popProperty(const char *&name_out, const char *&value_out)
00246     throw (HeyParserException)
00247 {
00248     struct Pair pair;
00249 
00250     name_out = NULL;
00251     value_out = NULL;
00252     
00253     if( this->hp_PropertyStack.size() == 0 )
00254     {
00255         throw HeyParserException("No more properties");
00256     }
00257     
00258     pair = this->hp_PropertyStack.top();
00259     name_out = pair.p_Name;
00260     value_out = pair.p_Value;
00261     this->hp_PropertyStack.pop();
00262 }
00263 
00264 void HeyParser::with(const char **&with_out, size_t &count_out) const
00265 {
00266     with_out = &this->hp_ArgValue[this->hp_ArgIndex];
00267     count_out = this->hp_ArgCount - this->hp_ArgIndex;
00268 }
00269 
00270 const char *HeyParser::withValue(const char *name,
00271                                  unsigned int instance,
00272                                  const char *default_value) const
00273     throw (HeyParserException)
00274 {
00275     const char *retval = NULL;
00276     size_t name_len;
00277     int lpc;
00278 
00279     require(name != NULL);
00280 
00281     name_len = strlen(name);
00282     /* Walk over the arguments not consumed by the constructor. */
00283     for( lpc = this->hp_ArgIndex;
00284          (lpc < this->hp_ArgCount) && (retval == NULL);
00285          lpc += 2 )
00286     {
00287         /* Compare the first part of the string to see if we have */
00288         if( (strncasecmp(this->hp_ArgValue[lpc], name, name_len) == 0) &&
00289             /* ... a complete match or */
00290             ((this->hp_ArgValue[lpc][name_len] == '\0') ||
00291              /* ... a value concatenated. */
00292              (this->hp_ArgValue[lpc][name_len] == '=')) )
00293         {
00294             if( instance == 0 )
00295             {
00296                 if( this->hp_ArgValue[lpc][name_len] == '=' )
00297                 {
00298                     retval = &this->hp_ArgValue[lpc][name_len + 1];
00299                 }
00300                 else
00301                 {
00302                     retval = this->hp_ArgValue[lpc + 1];
00303                 }
00304             }
00305             else
00306             {
00307                 instance -= 1;
00308             }
00309         }
00310     }
00311 
00312     if( retval == NULL )
00313     {
00314         if( default_value != NULL )
00315         {
00316             retval = default_value;
00317         }
00318         else
00319         {
00320             throw HeyParserException("Missing value", name);
00321         }
00322     }
00323     
00324     return( retval );
00325 }

Generated on Mon Dec 1 16:29:06 2003 for CPU Broker by doxygen 1.3.4