00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
00045 if( argc < 3 )
00046 {
00047 throw HeyParserException("Missing required arguments.");
00048 }
00049
00050
00051 this->hp_ArgCount = argc;
00052 this->hp_ArgValue = argv;
00053 this->hp_ArgIndex = 3;
00054
00055
00056 if( strlen(argv[1]) == 0 )
00057 {
00058 throw HeyParserException("Empty server name");
00059 }
00060
00061
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
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
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
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
00210 if( strcasecmp(this->consumeArg(), "of") == 0 )
00211 {
00212 }
00213 else
00214 {
00215 throw HeyParserException("Expecting 'of' keyword");
00216 }
00217 }
00218
00219
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
00230
00231
00232 this->hp_ArgIndex -= 1;
00233 }
00234 else
00235 {
00236 value_out = arg;
00237 }
00238 }
00239 catch(const HeyParserException &e)
00240 {
00241
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
00283 for( lpc = this->hp_ArgIndex;
00284 (lpc < this->hp_ArgCount) && (retval == NULL);
00285 lpc += 2 )
00286 {
00287
00288 if( (strncasecmp(this->hp_ArgValue[lpc], name, name_len) == 0) &&
00289
00290 ((this->hp_ArgValue[lpc][name_len] == '\0') ||
00291
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 }