NCBI C++ ToolKit
parser.c
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /*
2  * Test reading data with SQLBindCol
3  */
4 #include "common.h"
5 #include <ctype.h>
6 #include "parser.h"
7 
8 #include <common/test_assert.h>
9 
10 unsigned int odbc_line_num;
11 
12 void
13 odbc_fatal(const char *msg, ...)
14 {
15  va_list ap;
16 
17  va_start(ap, msg);
18  if (msg[0] == ':')
19  fprintf(stderr, "Line %u", odbc_line_num);
20  vfprintf(stderr, msg, ap);
21  va_end(ap);
22 
23  exit(1);
24 }
25 
26 #define SEP " \t\n"
27 
28 const char *
29 odbc_get_tok(char **p)
30 {
31  char *s = *p, *end;
32  s += strspn(s, SEP);
33  if (!*s) return NULL;
34  end = s + strcspn(s, SEP);
35  *end = 0;
36  *p = end+1;
37  return s;
38 }
39 
40 static void
41 parse_cstr(char *s)
42 {
43  char hexbuf[4];
44  char *d = s;
45 
46  while (*s) {
47  if (*s != '\\') {
48  *d++ = *s++;
49  continue;
50  }
51 
52  switch (*++s) {
53  case '\"':
54  *d++ = *s++;
55  break;
56  case '\\':
57  *d++ = *s++;
58  break;
59  case 'x':
60  if (strlen(s) < 3)
61  odbc_fatal(": wrong string format\n");
62  memcpy(hexbuf, ++s, 2);
63  hexbuf[2] = 0;
64  *d++ = (char) strtoul(hexbuf, NULL, 16);
65  s += 2;
66  break;
67  default:
68  odbc_fatal(": wrong string format\n");
69  }
70  }
71  *d = 0;
72 }
73 
74 const char *
75 odbc_get_str(char **p)
76 {
77  char *s = *p, *end;
78  s += strspn(s, SEP);
79  if (!*s) odbc_fatal(": unable to get string\n");
80 
81  if (strncmp(s, "\"\"\"", 3) == 0) {
82  s += 3;
83  end = strstr(s, "\"\"\"");
84  if (!end) odbc_fatal(": string not terminated\n");
85  *end = 0;
86  *p = end+3;
87  } else if (s[0] == '\"') {
88  ++s;
89  end = strchr(s, '\"');
90  if (!end) odbc_fatal(": string not terminated\n");
91  *end = 0;
92  parse_cstr(s);
93  *p = end+1;
94  } else {
95  return odbc_get_tok(p);
96  }
97  return s;
98 }
99 
100 enum { MAX_BOOLS = 64 };
101 typedef struct {
102  char *name;
103  int value;
104 } bool_t;
106 
107 void
108 odbc_set_bool(const char *name, int value)
109 {
110  unsigned n;
111  value = !!value;
112  for (n = 0; n < MAX_BOOLS && bools[n].name; ++n)
113  if (!strcmp(bools[n].name, name)) {
114  bools[n]. value = value;
115  return;
116  }
117 
118  if (n == MAX_BOOLS)
119  odbc_fatal(": no more boolean variable free\n");
120  bools[n].name = strdup(name);
121  if (!bools[n].name) odbc_fatal(": out of memory\n");
122  bools[n].value = value;
123 }
124 
125 static int
126 get_bool(const char *name)
127 {
128  unsigned n;
129  if (!name)
130  odbc_fatal(": boolean variable not provided\n");
131  for (n = 0; n < MAX_BOOLS && bools[n].name; ++n)
132  if (!strcmp(bools[n].name, name))
133  return bools[n]. value;
134 
135  odbc_fatal(": boolean variable %s not found\n", name);
136  return 0;
137 }
138 
139 /** initialize booleans, call after connection */
140 void
142 {
143  int big_endian = 1;
144 
145  if (((char *) &big_endian)[0] == 1)
146  big_endian = 0;
147  odbc_set_bool("bigendian", big_endian);
148 
151 }
152 
153 void
155 {
156  unsigned n;
157  for (n = 0; n < MAX_BOOLS && bools[n].name; ++n) {
158  free(bools[n].name);
159  bools[n].name = NULL;
160  }
161 }
162 
163 enum { MAX_CONDITIONS = 32 };
164 static char conds[MAX_CONDITIONS];
165 static unsigned cond_level = 0;
166 
167 static int
169 {
170  if (cond_level == 0) odbc_fatal(": no related if\n");
171  return conds[--cond_level];
172 }
173 
174 static void
175 push_condition(int cond)
176 {
177  if (cond != 0 && cond != 1) odbc_fatal(": invalid cond value %d\n", cond);
178  if (cond_level >= MAX_CONDITIONS) odbc_fatal(": too much nested conditions\n");
179  conds[cond_level++] = cond;
180 }
181 
182 static int
183 get_not_cond(char **p)
184 {
185  int cond;
186  const char *tok = odbc_get_tok(p);
187  if (!tok) odbc_fatal(": wrong condition syntax\n");
188 
189  if (!strcmp(tok, "not"))
190  cond = !get_bool(odbc_get_tok(p));
191  else
192  cond = get_bool(tok);
193 
194  return cond;
195 }
196 
197 static int
198 get_condition(char **p)
199 {
200  int cond1 = get_not_cond(p), cond2;
201  const char *tok;
202 
203  while ((tok=odbc_get_tok(p)) != NULL) {
204 
205  cond2 = get_not_cond(p);
206 
207  if (!strcmp(tok, "or"))
208  cond1 = cond1 || cond2;
209  else if (!strcmp(tok, "and"))
210  cond1 = cond1 && cond2;
211  else odbc_fatal(": wrong condition syntax\n");
212  }
213  return cond1;
214 }
215 
216 static FILE *parse_file;
217 static char line_buf[1024];
218 
219 void
221 {
222  if (parse_file)
223  odbc_fatal("parser file already setup\n");
224  parse_file = f;
225  odbc_line_num = 0;
227 }
228 
229 const char *
230 odbc_get_cmd_line(char **p_s, int *cond)
231 {
232  while (fgets(line_buf, sizeof(line_buf), parse_file)) {
233  char *p = line_buf;
234  const char *cmd;
235 
236  ++odbc_line_num;
237 
238  cmd = odbc_get_tok(&p);
239 
240  /* skip comments */
241  if (!cmd || cmd[0] == '#' || cmd[0] == 0 || cmd[0] == '\n')
242  continue;
243 
244  /* conditional statement */
245  if (!strcmp(cmd, "else")) {
246  int c = pop_condition();
247  push_condition(c);
248  *cond = c && !*cond;
249  continue;
250  }
251  if (!strcmp(cmd, "endif")) {
252  *cond = pop_condition();
253  continue;
254  }
255  if (!strcmp(cmd, "if")) {
256  push_condition(*cond);
257  if (*cond)
258  *cond = get_condition(&p);
259  continue;
260  }
261 
262  if (strcmp(cmd, "tds_version_cmp") == 0) {
263  const char *bool_name = odbc_get_tok(&p);
264  const char *cmp = odbc_get_tok(&p);
265  const char *s_ver = odbc_get_tok(&p);
266  int ver = odbc_tds_version();
267  int expected;
268  int res;
269  unsigned M, m;
270 
271  if (!cmp || !s_ver)
272  odbc_fatal(": missing parameters\n");
273  if (sscanf(s_ver, "%u.%u", &M, &m) != 2)
274  odbc_fatal(": invalid version %s\n", s_ver);
275  expected = M * 0x100u + m;
276 
277  if (strcmp(cmp, ">") == 0)
278  res = ver > expected;
279  else if (strcmp(cmp, ">=") == 0)
280  res = ver >= expected;
281  else if (strcmp(cmp, "<") == 0)
282  res = ver < expected;
283  else if (strcmp(cmp, "<=") == 0)
284  res = ver <= expected;
285  else if (strcmp(cmp, "==") == 0)
286  res = ver == expected;
287  else if (strcmp(cmp, "!=") == 0)
288  res = ver != expected;
289  else
290  odbc_fatal(": invalid operator %s\n", cmp);
291 
292  if (*cond)
293  odbc_set_bool(bool_name, res);
294  continue;
295  }
296 
297  *p_s = p;
298  return cmd;
299  }
300  return NULL;
301 }
302 
char value[7]
Definition: config.c:431
static CS_COMMAND * cmd
Definition: ct_dynamic.c:26
static int big_endian
Definition: genparams.c:251
#define NULL
Definition: ncbistd.hpp:225
exit(2)
yy_size_t n
int strncmp(const char *str1, const char *str2, size_t count)
Definition: odbc_utils.hpp:133
int strcmp(const char *str1, const char *str2)
Definition: odbc_utils.hpp:160
#define strdup
Definition: ncbi_ansi_ext.h:70
double f(double x_, const double &y_)
Definition: njn_root.hpp:188
static const char * expected[]
Definition: bcp.c:42
int odbc_db_is_microsoft(void)
Definition: common.c:325
int odbc_tds_version(void)
Definition: common.c:444
int odbc_driver_is_freetds(void)
Definition: common.c:345
static bool_t bools[MAX_BOOLS]
Definition: parser.c:105
static int get_condition(char **p)
Definition: parser.c:198
unsigned int odbc_line_num
Definition: parser.c:10
@ MAX_BOOLS
Definition: parser.c:100
void odbc_clear_bools(void)
Definition: parser.c:154
static char conds[MAX_CONDITIONS]
Definition: parser.c:164
const char * odbc_get_cmd_line(char **p_s, int *cond)
Definition: parser.c:230
void odbc_set_bool(const char *name, int value)
Definition: parser.c:108
static int pop_condition(void)
Definition: parser.c:168
static int get_bool(const char *name)
Definition: parser.c:126
static void push_condition(int cond)
Definition: parser.c:175
#define SEP
Definition: parser.c:26
@ MAX_CONDITIONS
Definition: parser.c:163
static FILE * parse_file
Definition: parser.c:216
static void parse_cstr(char *s)
Definition: parser.c:41
void odbc_fatal(const char *msg,...)
Definition: parser.c:13
const char * odbc_get_tok(char **p)
Definition: parser.c:29
void odbc_init_parser(FILE *f)
Definition: parser.c:220
void odbc_init_bools(void)
initialize booleans, call after connection
Definition: parser.c:141
static int get_not_cond(char **p)
Definition: parser.c:183
static char line_buf[1024]
Definition: parser.c:217
static unsigned cond_level
Definition: parser.c:165
const char * odbc_get_str(char **p)
Definition: parser.c:75
Definition: parser.c:101
int value
Definition: parser.c:103
char * name
Definition: parser.c:102
void free(voidpf ptr)
Modified on Tue Feb 27 05:57:04 2024 by modify_doxy.py rev. 669887