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 */
16
#ifndef CPCD_PARSER_HPP
17
#define CPCD_PARSER_HPP
20
#include "Properties.hpp"
21
#include "InputStream.hpp"
25
template<class T> struct ParserRow;
27
//#define PARSER_DEBUG
30
ndbout_c("%s:%d:%s", __FILE__, __LINE__, x);
52
InvalidArgumentFormat = 7,
53
UnknownArgumentType = 8,
54
CommandWithoutFunction = 9,
55
ArgumentGivenTwice = 10,
57
MissingMandatoryArgument = 12
65
Context() { m_mutex= NULL; };
66
ParserStatus m_status;
67
const ParserRow<T> * m_currentCmd;
68
const ParserRow<T> * m_currentArg;
69
char * m_currentToken;
70
char m_tokenBuffer[512];
73
Vector<const ParserRow<T> *> m_aliasUsed;
79
Parser(const ParserRow<T> rows[], class InputStream & in = Stdin,
80
bool breakOnCommand = false,
81
bool breakOnEmptyLine = true,
82
bool breakOnInvalidArg = false);
88
bool run(Context &, T &, volatile bool * stop = 0) const;
91
* Parse only one entry and return Properties object representing
94
const Properties *parse(Context &, T &);
96
bool getBreakOnCommand() const;
97
void setBreakOnCommand(bool v);
99
bool getBreakOnEmptyLine() const;
100
void setBreakOnEmptyLine(bool v);
102
bool getBreakOnInvalidArg() const;
103
void setBreakOnInvalidArg(bool v);
112
enum Type { Cmd, Arg, CmdAlias, ArgAlias };
113
enum ArgType { String, Int, Properties };
114
enum ArgRequired { Mandatory, Optional };
115
enum ArgMinMax { CheckMinMax, IgnoreMinMax };
118
const char * realName;
121
ArgRequired argRequired;
125
void (T::* function)(typename Parser<T>::Context & ctx,
126
const class Properties& args);
127
const char * description;
132
* The void* equivalent implementation
137
typedef ParserRow<Dummy> DummyRow;
138
typedef Parser<Dummy>::Context Context;
141
ParserImpl(const DummyRow rows[], class InputStream & in,
142
bool b_cmd, bool b_empty, bool b_iarg);
145
bool run(Context *ctx, const class Properties **, volatile bool *) const ;
147
static const DummyRow* matchCommand(Context*, const char*, const DummyRow*);
148
static const DummyRow* matchArg(Context*, const char *, const DummyRow *);
149
static bool parseArg(Context*, char*, const DummyRow*, Properties*);
150
static bool checkMandatory(Context*, const Properties*);
152
const DummyRow * const m_rows;
153
class ParseInputStream & input;
156
bool m_breakOnInvalidArg;
161
Parser<T>::Parser(const ParserRow<T> rows[], class InputStream & in,
162
bool b_cmd, bool b_empty, bool b_iarg){
163
impl = new ParserImpl((ParserImpl::DummyRow *)rows, in,
164
b_cmd, b_empty, b_iarg);
169
Parser<T>::~Parser(){
176
Parser<T>::run(Context & ctx, T & t, volatile bool * stop) const {
177
const Properties * p;
178
DEBUG("Executing Parser<T>::run");
179
if(impl->run((ParserImpl::Context*)&ctx, &p, stop)){
180
const ParserRow<T> * cmd = ctx.m_currentCmd; // Cast to correct type
183
* Should happen if run returns true
188
for(unsigned i = 0; i<ctx.m_aliasUsed.size(); i++){
189
const ParserRow<T> * alias = ctx.m_aliasUsed[i];
190
if(alias->function != 0){
192
* Report alias usage with callback (if specified by user)
194
DEBUG("Alias usage with callback");
195
(t.* alias->function)(ctx, * p);
199
if(cmd->function == 0){
200
ctx.m_status = CommandWithoutFunction;
201
DEBUG("CommandWithoutFunction");
205
(t.* cmd->function)(ctx, * p); // Call the function
216
Parser<T>::parse(Context &ctx, T &t) {
217
const Properties * p;
218
volatile bool stop = false;
219
DEBUG("Executing Parser<T>::parse");
221
if(impl->run((ParserImpl::Context*)&ctx, &p, &stop)){
222
const ParserRow<T> * cmd = ctx.m_currentCmd; // Cast to correct type
225
* Should happen if run returns true
230
for(unsigned i = 0; i<ctx.m_aliasUsed.size(); i++){
231
const ParserRow<T> * alias = ctx.m_aliasUsed[i];
232
if(alias->function != 0){
234
* Report alias usage with callback (if specified by user)
236
DEBUG("Alias usage with callback");
237
(t.* alias->function)(ctx, * p);
241
if(cmd->function == 0){
242
DEBUG("CommandWithoutFunction");
243
ctx.m_status = CommandWithoutFunction;
255
Parser<T>::getBreakOnCommand() const{
256
return impl->m_breakOnCmd;
262
Parser<T>::setBreakOnCommand(bool v){
263
impl->m_breakOnCmd = v;
269
Parser<T>::getBreakOnEmptyLine() const{
270
return impl->m_breakOnEmpty;
275
Parser<T>::setBreakOnEmptyLine(bool v){
276
impl->m_breakOnEmpty = v;
282
Parser<T>::getBreakOnInvalidArg() const{
283
return impl->m_breakOnInvalidArg;
289
Parser<T>::setBreakOnInvalidArg(bool v){
290
impl->m_breakOnInvalidArg = v;