1 /* Copyright (c) 2003-2006 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 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
;