1
/* Copyright (C) 2003 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; either version 2 of the License, or
6
(at your option) any later version.
8
This program is distributed in the hope that it will be useful,
9
but WITHOUT ANY WARRANTY; without even the implied warranty of
10
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License
14
along with this program; if not, write to the Free Software
15
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
18
#include <ndb_global.h>
22
#include <Properties.hpp>
25
#define DEBUG(x) ndbout << x << endl;
27
static void trim(char * str);
29
class ParseInputStream : public InputStream {
31
ParseInputStream(InputStream & in, bool trim = true, char eofComment = '#');
33
char* gets(char * buf, int bufLen);
34
void push_back(const char *);
40
ParseInputStream::ParseInputStream(InputStream & _in,
48
ParseInputStream::gets(char * buf, int bufLen){
50
strncpy(buf, buffer, bufLen);
55
char *t = in.gets(buf, bufLen);
60
ParseInputStream::push_back(const char * str){
66
ParserImpl::ParserImpl(const DummyRow * rows, InputStream & in,
67
bool b_cmd, bool b_empty, bool b_iarg)
68
: m_rows(rows), input(* new ParseInputStream(in))
71
m_breakOnEmpty = b_empty;
72
m_breakOnInvalidArg = b_iarg;
75
ParserImpl::~ParserImpl(){
81
Empty(const char * str){
84
const int len = strlen(str);
87
for(int i = 0; i<len; i++)
88
if(str[i] != ' ' && str[i] != '\t' && str[i] != '\n')
95
Eof(const char * str) { return str == 0;}
102
int len = strlen(str);
103
for(len--; str[len] == '\n' || str[len] == ' ' || str[len] == '\t'; len--)
107
while(str[pos] == ' ' || str[pos] == '\t')
110
if(str[pos] == '\"' && str[len] == '\"') {
116
memmove(str, &str[pos], len - pos + 2);
121
split(char * buf, char ** name, char ** value){
123
* value = strchr(buf, ':');
125
* value = strchr(buf, '=');
132
* value = (* value + 1);
142
ParserImpl::run(Context * ctx, const class Properties ** pDst,
143
volatile bool * stop) const
145
DBUG_ENTER("ParserImpl::run");
148
bool ownStop = false;
152
ctx->m_aliasUsed.clear();
154
const unsigned sz = sizeof(ctx->m_tokenBuffer);
155
ctx->m_currentToken = input.gets(ctx->m_tokenBuffer, sz);
156
if(Eof(ctx->m_currentToken)){
157
ctx->m_status = Parser<Dummy>::Eof;
161
int last= strlen(ctx->m_currentToken);
165
if(ctx->m_currentToken[last] !='\n'){
166
ctx->m_status = Parser<Dummy>::NoLine;
167
ctx->m_tokenBuffer[0]= '\0';
171
if(Empty(ctx->m_currentToken)){
172
ctx->m_status = Parser<Dummy>::EmptyLine;
176
trim(ctx->m_currentToken);
177
ctx->m_currentCmd = matchCommand(ctx, ctx->m_currentToken, m_rows);
178
if(ctx->m_currentCmd == 0){
179
ctx->m_status = Parser<Dummy>::UnknownCommand;
183
Properties * p = new Properties();
185
bool invalidArgument = false;
186
ctx->m_currentToken = input.gets(ctx->m_tokenBuffer, sz);
189
!Eof(ctx->m_currentToken) &&
190
!Empty(ctx->m_currentToken)){
191
if(ctx->m_currentToken[0] != 0){
192
trim(ctx->m_currentToken);
193
if(!parseArg(ctx, ctx->m_currentToken, ctx->m_currentCmd + 1, p)){
195
invalidArgument = true;
199
ctx->m_currentToken = input.gets(ctx->m_tokenBuffer, sz);
205
if(!m_breakOnInvalidArg){
207
tmp = input.gets(buf, sz);
208
} while((! * stop) && !Eof(tmp) && !Empty(tmp));
215
ctx->m_status = Parser<Dummy>::ExternalStop;
219
if(!checkMandatory(ctx, p)){
220
ctx->m_status = Parser<Dummy>::MissingMandatoryArgument;
226
* Add alias to properties
228
for(unsigned i = 0; i<ctx->m_aliasUsed.size(); i++){
229
const ParserRow<Dummy> * alias = ctx->m_aliasUsed[i];
231
tmp.put("name", alias->name);
232
tmp.put("realName", alias->realName);
233
p->put("$ALIAS", i, &tmp);
235
p->put("$ALIAS", ctx->m_aliasUsed.size());
237
ctx->m_status = Parser<Dummy>::Ok;
242
const ParserImpl::DummyRow*
243
ParserImpl::matchCommand(Context* ctx, const char* buf, const DummyRow rows[]){
244
const char * name = buf;
245
const DummyRow * tmp = &rows[0];
246
while(tmp->name != 0 && name != 0){
247
if(strcmp(tmp->name, name) == 0){
248
if(tmp->type == DummyRow::Cmd)
250
if(tmp->type == DummyRow::CmdAlias){
252
ctx->m_aliasUsed.push_back(tmp);
253
name = tmp->realName;
263
const ParserImpl::DummyRow*
264
ParserImpl::matchArg(Context* ctx, const char * buf, const DummyRow rows[]){
265
const char * name = buf;
266
const DummyRow * tmp = &rows[0];
267
while(tmp->name != 0){
268
const DummyRow::Type t = tmp->type;
269
if(t != DummyRow::Arg && t != DummyRow::ArgAlias && t !=DummyRow::CmdAlias)
271
if(t !=DummyRow::CmdAlias && strcmp(tmp->name, name) == 0){
272
if(tmp->type == DummyRow::Arg){
275
if(tmp->type == DummyRow::ArgAlias){
277
ctx->m_aliasUsed.push_back(tmp);
278
name = tmp->realName;
289
ParserImpl::parseArg(Context * ctx,
291
const DummyRow * rows,
295
if(!split(buf, &name, &value)){
296
ctx->m_status = Parser<Dummy>::InvalidArgumentFormat;
299
const DummyRow * arg = matchArg(ctx, name, rows);
301
ctx->m_status = Parser<Dummy>::UnknownArgument;
305
switch(arg->argType){
306
case DummyRow::String:
307
if(p->put(arg->name, value))
312
int c = sscanf(value, "%u", &i);
314
ctx->m_status = Parser<Dummy>::TypeMismatch;
317
if(p->put(arg->name, i))
322
case DummyRow::Properties: {
327
ctx->m_status = Parser<Dummy>::UnknownArgumentType;
330
if(p->getPropertiesErrno() == E_PROPERTIES_ELEMENT_ALREADY_EXISTS){
331
ctx->m_status = Parser<Dummy>::ArgumentGivenTwice;
339
ParserImpl::checkMandatory(Context* ctx, const Properties* props){
340
const DummyRow * tmp = &ctx->m_currentCmd[1];
341
while(tmp->name != 0 && tmp->type == DummyRow::Arg){
342
if(tmp->argRequired == ParserRow<Dummy>::Mandatory &&
343
!props->contains(tmp->name)){
344
ctx->m_status = Parser<Dummy>::MissingMandatoryArgument;
345
ctx->m_currentArg = tmp;
353
template class Vector<const ParserRow<ParserImpl::Dummy>*>;