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; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
#include <ndb_global.h>
21
#include <Properties.hpp>
24
#define DEBUG(x) ndbout << x << endl;
26
static void trim(char * str);
28
class ParseInputStream : public InputStream {
30
ParseInputStream(InputStream & in, bool trim = true, char eofComment = '#');
32
char* gets(char * buf, int bufLen);
33
void push_back(const char *);
34
void set_mutex(NdbMutex *m) { in.set_mutex(m); };
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");
147
input.set_mutex(ctx->m_mutex);
150
bool ownStop = false;
154
ctx->m_aliasUsed.clear();
156
const unsigned sz = sizeof(ctx->m_tokenBuffer);
157
ctx->m_currentToken = input.gets(ctx->m_tokenBuffer, sz);
158
if(Eof(ctx->m_currentToken)){
159
ctx->m_status = Parser<Dummy>::Eof;
163
int last= strlen(ctx->m_currentToken);
167
if(ctx->m_currentToken[last] !='\n'){
168
ctx->m_status = Parser<Dummy>::NoLine;
169
ctx->m_tokenBuffer[0]= '\0';
173
if(Empty(ctx->m_currentToken)){
174
ctx->m_status = Parser<Dummy>::EmptyLine;
178
trim(ctx->m_currentToken);
179
ctx->m_currentCmd = matchCommand(ctx, ctx->m_currentToken, m_rows);
180
if(ctx->m_currentCmd == 0){
181
ctx->m_status = Parser<Dummy>::UnknownCommand;
185
Properties * p = new Properties();
187
bool invalidArgument = false;
188
ctx->m_currentToken = input.gets(ctx->m_tokenBuffer, sz);
191
!Eof(ctx->m_currentToken) &&
192
!Empty(ctx->m_currentToken)){
193
if(ctx->m_currentToken[0] != 0){
194
trim(ctx->m_currentToken);
195
if(!parseArg(ctx, ctx->m_currentToken, ctx->m_currentCmd + 1, p)){
197
invalidArgument = true;
201
ctx->m_currentToken = input.gets(ctx->m_tokenBuffer, sz);
207
if(!m_breakOnInvalidArg){
209
tmp = input.gets(buf, sz);
210
} while((! * stop) && !Eof(tmp) && !Empty(tmp));
217
ctx->m_status = Parser<Dummy>::ExternalStop;
221
if(!checkMandatory(ctx, p)){
222
ctx->m_status = Parser<Dummy>::MissingMandatoryArgument;
228
* Add alias to properties
230
for(unsigned i = 0; i<ctx->m_aliasUsed.size(); i++){
231
const ParserRow<Dummy> * alias = ctx->m_aliasUsed[i];
233
tmp.put("name", alias->name);
234
tmp.put("realName", alias->realName);
235
p->put("$ALIAS", i, &tmp);
237
p->put("$ALIAS", ctx->m_aliasUsed.size());
239
ctx->m_status = Parser<Dummy>::Ok;
244
const ParserImpl::DummyRow*
245
ParserImpl::matchCommand(Context* ctx, const char* buf, const DummyRow rows[]){
246
const char * name = buf;
247
const DummyRow * tmp = &rows[0];
248
while(tmp->name != 0 && name != 0){
249
if(strcmp(tmp->name, name) == 0){
250
if(tmp->type == DummyRow::Cmd)
252
if(tmp->type == DummyRow::CmdAlias){
254
ctx->m_aliasUsed.push_back(tmp);
255
name = tmp->realName;
265
const ParserImpl::DummyRow*
266
ParserImpl::matchArg(Context* ctx, const char * buf, const DummyRow rows[]){
267
const char * name = buf;
268
const DummyRow * tmp = &rows[0];
269
while(tmp->name != 0){
270
const DummyRow::Type t = tmp->type;
271
if(t != DummyRow::Arg && t != DummyRow::ArgAlias && t !=DummyRow::CmdAlias)
273
if(t !=DummyRow::CmdAlias && strcmp(tmp->name, name) == 0){
274
if(tmp->type == DummyRow::Arg){
277
if(tmp->type == DummyRow::ArgAlias){
279
ctx->m_aliasUsed.push_back(tmp);
280
name = tmp->realName;
291
ParserImpl::parseArg(Context * ctx,
293
const DummyRow * rows,
297
if(!split(buf, &name, &value)){
298
ctx->m_status = Parser<Dummy>::InvalidArgumentFormat;
301
const DummyRow * arg = matchArg(ctx, name, rows);
303
ctx->m_status = Parser<Dummy>::UnknownArgument;
307
switch(arg->argType){
308
case DummyRow::String:
309
if(p->put(arg->name, value))
314
int c = sscanf(value, "%u", &i);
316
ctx->m_status = Parser<Dummy>::TypeMismatch;
319
if(p->put(arg->name, i))
324
case DummyRow::Properties: {
329
ctx->m_status = Parser<Dummy>::UnknownArgumentType;
332
if(p->getPropertiesErrno() == E_PROPERTIES_ELEMENT_ALREADY_EXISTS){
333
ctx->m_status = Parser<Dummy>::ArgumentGivenTwice;
341
ParserImpl::checkMandatory(Context* ctx, const Properties* props){
342
const DummyRow * tmp = &ctx->m_currentCmd[1];
343
while(tmp->name != 0 && tmp->type == DummyRow::Arg){
344
if(tmp->argRequired == ParserRow<Dummy>::Mandatory &&
345
!props->contains(tmp->name)){
346
ctx->m_status = Parser<Dummy>::MissingMandatoryArgument;
347
ctx->m_currentArg = tmp;
355
template class Vector<const ParserRow<ParserImpl::Dummy>*>;