source: tags/ms_ra2q56/ARBDB/gb_aci_impl.h

Last change on this file was 18186, checked in by westram, 5 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.9 KB
Line 
1// ================================================================= //
2//                                                                   //
3//   File      : gb_aci_impl.h                                       //
4//   Purpose   : provide code useful to implement ACI commands       //
5//                                                                   //
6//   Institute of Microbiology (Technical University Munich)         //
7//   http://www.arb-home.de/                                         //
8//                                                                   //
9// ================================================================= //
10
11#ifndef GB_ACI_IMPL_H
12#define GB_ACI_IMPL_H
13
14#ifndef GB_ACI_H
15#include <gb_aci.h>
16#endif
17
18// export stream
19#define PASS_2_OUT(args,s)  (args)->output.insert(s)
20#define COPY_2_OUT(args,s)  PASS_2_OUT(args, ARB_strdup(s))
21#define IN_2_OUT(args,i)    PASS_2_OUT(args, args->input.get_smart(i))
22#define PARAM_2_OUT(args,i) PASS_2_OUT(args, args->get_param_smart(i))
23
24#define FORMAT_2_OUT(args,fmt,value)  PASS_2_OUT(args, GBS_global_string_copy(fmt, value))
25
26// ----------------------------
27//      Parameter functions
28
29namespace GBL_IMPL {
30
31    const char *search_matching_parenthesis(const char *source);
32    inline char *search_matching_parenthesis(char *source) {
33        return const_cast<char*>(search_matching_parenthesis(const_cast<const char*>(source)));
34    }
35
36
37    struct gbl_param {
38        gbl_param  *next;
39        GB_TYPES    type;                               // type of variable
40        void       *varaddr;                            // address of variable where value gets stored
41        const char *param_name;                         // parameter name (e.g. 'include=')
42        const char *help_text;                          // help text for parameter
43    };
44
45#define GBL_BEGIN_PARAMS gbl_param *params = NULp
46
47    inline void gbl_new_param(gbl_param **pp, GB_TYPES type, void *vaddr, const char *param_name, const char *help_text) {
48        gbl_param *gblp = ARB_calloc<gbl_param>(1);
49
50        gblp->next = *pp;
51        *pp         = gblp;
52
53        gblp->type       = type;
54        gblp->varaddr    = vaddr;
55        gblp->param_name = param_name;
56        gblp->help_text  = help_text;
57    }
58
59    typedef const char   *String;
60    typedef int           bit;
61    typedef unsigned int  nat;
62
63    inline int gbl_param_int(const char *param_name, int def, const char *help_text, gbl_param **pp, int *vaddr) {
64        gbl_new_param(pp, GB_INT, vaddr, param_name, help_text);
65        return def;
66    }
67
68    inline char gbl_param_char(const char *param_name, char def, const char *help_text, gbl_param **pp, char *vaddr) {
69        gbl_new_param(pp, GB_BYTE, vaddr, param_name, help_text);
70        return def;
71    }
72
73    inline nat gbl_param_nat(const char *param_name, nat def, const char *help_text, gbl_param **pp, nat *vaddr) {
74        gbl_new_param(pp, GB_INT, vaddr, param_name, help_text);
75        return def;
76    }
77
78    inline const char *gbl_param_String(const char *param_name, const char *def, const char *help_text, gbl_param **pp, String *vaddr) {
79        gbl_new_param(pp, GB_STRING, vaddr, param_name, help_text);
80        return def;
81    }
82
83    inline int gbl_param_bit(const char *param_name, int def, const char *help_text, gbl_param **pp, bit *vaddr) {
84        gbl_new_param(pp, GB_BIT, vaddr, param_name, help_text);
85        return def;
86    }
87
88    GB_ERROR trace_params(const GBL_streams& param, gbl_param *ppara, const char *com);
89};
90
91#define GBL_PARAM_TYPE(type, var, param_name, def, help_text) type  var = gbl_param_##type(param_name, def, help_text, &params, &var)
92#define GBL_STRUCT_PARAM_TYPE(type, strct, member, param_name, def, help_text) strct.member = gbl_param_##type(param_name, def, help_text, &params, &strct.member)
93
94// use PARAM_IF for parameters whose existence depends on condition
95#define PARAM_IF(cond,param) ((cond) ? (param) : NULp)
96
97#define GBL_PARAM_INT(var,    param_name, def, help_text) GBL_PARAM_TYPE(int,    var, param_name, def, help_text)
98#define GBL_PARAM_CHAR(var,   param_name, def, help_text) GBL_PARAM_TYPE(char,   var, param_name, def, help_text)
99#define GBL_PARAM_UINT(var,   param_name, def, help_text) GBL_PARAM_TYPE(nat,    var, param_name, def, help_text)
100#define GBL_PARAM_STRING(var, param_name, def, help_text) GBL_PARAM_TYPE(String, var, param_name, def, help_text)
101#define GBL_PARAM_BIT(var,    param_name, def, help_text) GBL_PARAM_TYPE(bit,    var, param_name, def, help_text)
102
103#define GBL_STRUCT_PARAM_INT(strct,    member, param_name, def, help_text) GBL_STRUCT_PARAM_TYPE(int,    strct, member, param_name, def, help_text)
104#define GBL_STRUCT_PARAM_CHAR(strct,   member, param_name, def, help_text) GBL_STRUCT_PARAM_TYPE(char,   strct, member, param_name, def, help_text)
105#define GBL_STRUCT_PARAM_UINT(strct,   member, param_name, def, help_text) GBL_STRUCT_PARAM_TYPE(nat,    strct, member, param_name, def, help_text)
106#define GBL_STRUCT_PARAM_STRING(strct, member, param_name, def, help_text) GBL_STRUCT_PARAM_TYPE(String, strct, member, param_name, def, help_text)
107#define GBL_STRUCT_PARAM_BIT(strct,    member, param_name, def, help_text) GBL_STRUCT_PARAM_TYPE(bit,    strct, member, param_name, def, help_text)
108
109#define GBL_TRACE_PARAMS(args)                                                          \
110    do {                                                                                \
111        GB_ERROR def_error =                                                            \
112            trace_params((args)->get_param_streams(), params, (args)->get_cmdName());   \
113        gb_assert((args)->set_params_checked());                                        \
114        if (def_error) { GBL_END_PARAMS; return def_error; }                            \
115    } while(0)
116
117#define GBL_END_PARAMS                                                  \
118    do {                                                                \
119        gbl_param *_gblp;                                               \
120        while (params) {                                                \
121            _gblp = params;                                             \
122            params = params->next;                                      \
123            free(_gblp);                                                \
124        }                                                               \
125    } while (0)
126
127#define GBL_CHECK_FREE_PARAM(nr, cnt)           \
128    do {                                        \
129        if ((nr)+(cnt) >= GBL_MAX_ARGUMENTS) {  \
130            /* gb_assert(0); */                 \
131            return "max. parameters exceeded";  \
132        }                                       \
133    } while (0)
134
135#if defined(WARN_TODO)
136#warning remove GBL_MAX_ARGUMENTS - instead allocate dynamic
137#endif
138
139// --------------------------------
140//      parameter/stream checks
141
142namespace GBL_IMPL {
143
144    extern int traceACI;
145    extern int traceIndent;
146
147    void print_trace(const char *text);
148
149    inline void modify_trace_indent(int diff) {
150        traceIndent += diff;
151        gb_assert(traceIndent>=0);
152    }
153
154    inline GB_ERROR check_no_parameter(GBL_command_arguments *args) {
155        gb_assert(args->set_params_checked());
156        if (args->param_count() == 0) return NULp;
157        return GBS_global_string("syntax: %s (no parameters)", args->get_cmdName());
158    }
159    inline GB_ERROR check_has_parameters(GBL_command_arguments *args, const char *param_syntax) {
160        gb_assert(args->set_params_checked());
161        if (args->param_count() > 0) return NULp;
162        return GBS_global_string("syntax: %s(%s)", args->get_cmdName(), param_syntax);
163    }
164    inline GB_ERROR check_parameters(GBL_command_arguments *args, int expected, const char *parameterList) {
165        gb_assert(args->set_params_checked());
166        if (args->param_count() == expected) return NULp;
167        return GBS_global_string("syntax: %s(%s)", args->get_cmdName(), parameterList);
168    }
169    inline GB_ERROR check_optional_parameters(GBL_command_arguments *args, int fix, const char *fixParam, int opt, const char *optParam, bool opt_trailing, bool opt_expect_all) {
170        // if opt_expect_all == true -> checks whether either NO or ALL optional parameters were specified
171        // if opt_expect_all == false -> accept any number of parameters -> specify 'optParam' e.g. like "p3[,p4[,p5]]"
172        // if opt_trailing == false -> optional parameters are BEFORE fixed (don't use!)
173        gb_assert(args->set_params_checked());
174
175        int params = args->param_count();
176        if (params == fix || params == (fix+opt)) return NULp;
177        if (!opt_expect_all && params >= fix && params <= (fix+opt)) return NULp;
178        if (!fix) return GBS_global_string("syntax: %s[(%s)]", args->get_cmdName(), optParam);
179        if (opt_trailing) return GBS_global_string("syntax: %s(%s[,%s])", args->get_cmdName(), fixParam, optParam);
180        return GBS_global_string("syntax: %s([%s,]%s)", args->get_cmdName(), optParam, fixParam);
181    }
182
183    inline GB_ERROR check_valid_index(int number, const char *what, int min, int max) {
184        if (number >= min && number <= max) return NULp;
185        return GBS_global_string("Illegal %s number '%i' (allowed [%i..%i])", what, number, min, max);
186    }
187    inline GB_ERROR check_valid_stream_index(GBL_command_arguments *args, int number) { return check_valid_index(number, "stream", 1, args->input.size()); }
188    inline GB_ERROR check_valid_param_index (GBL_command_arguments *args, int number) { return check_valid_index(number, "param",  0, args->param_count()-1); }
189
190    inline GB_ERROR check_item_referenced(GBL_command_arguments *args) {
191        return args->get_item_ref()
192            ? NULp
193            : GBS_global_string("command %s cannot be called w/o item", args->get_cmdName());
194    }
195};
196
197#define TRACE_ACI(text) if (GBL_IMPL::traceACI) GBL_IMPL::print_trace(text)
198
199#define DO_AND_RETURN_ON_ERROR(cmd) do {                            \
200        GB_ERROR perr = (cmd);                                      \
201        if (perr) return perr;                                      \
202    } while(0)
203
204#define EXPECT_NO_PARAM(args)             DO_AND_RETURN_ON_ERROR(GBL_IMPL::check_no_parameter(args))
205#define EXPECT_PARAMS_PASSED(args,syntax) DO_AND_RETURN_ON_ERROR(GBL_IMPL::check_has_parameters(args,syntax))
206#define ACCEPT_ANY_PARAMS(args)           gb_assert((args)->set_params_checked())
207
208#define EXPECT_PARAMS(args,cnt,help)                                                DO_AND_RETURN_ON_ERROR(GBL_IMPL::check_parameters(args, cnt, help))
209#define EXPECT_OPTIONAL_PARAMS(args,fixCnt,fixhelp,optCnt,opthelp)                  DO_AND_RETURN_ON_ERROR(GBL_IMPL::check_optional_parameters(args, fixCnt, fixhelp, optCnt, opthelp, true, true))
210#define EXPECT_OPTIONAL_PARAMS_CUSTOM(args,fixCnt,fixhelp,optCnt,opthelp,trail,all) DO_AND_RETURN_ON_ERROR(GBL_IMPL::check_optional_parameters(args, fixCnt, fixhelp, optCnt, opthelp, trail, all))
211
212#define EXPECT_LEGAL_STREAM_INDEX(args,number) do {                             \
213        GB_ERROR serr = GBL_IMPL::check_valid_stream_index(args, number);       \
214        if (serr) return serr;                                                  \
215    } while(0)
216
217#define EXPECT_ITEM_REFERENCED(args) DO_AND_RETURN_ON_ERROR(GBL_IMPL::check_item_referenced(args))
218
219
220#define COMMAND_DROPS_INPUT_STREAMS(args) do {                                                                          \
221        if (GBL_IMPL::traceACI && args->input.size()>0) {                                                              \
222            if (args->input.size()>1 || args->input.get(0)[0]) {                                                        \
223                GBL_IMPL::print_trace(GBS_global_string("Warning: Dropped %i input streams\n", args->input.size())); \
224            }                                                                                                           \
225        }                                                                                                               \
226    } while(0)
227
228
229#else
230#error gb_aci_impl.h included twice
231#endif // GB_ACI_IMPL_H
Note: See TracBrowser for help on using the repository browser.