Age Owner Branch data TLA Line data Source code
1 : : /* src/interfaces/ecpg/preproc/variable.c */
2 : :
3 : : #include "postgres_fe.h"
4 : :
5 : : #include "preproc_extern.h"
6 : :
7 : : static struct variable *allvariables = NULL;
8 : :
9 : : /* this probably belongs in util.c, but for now it's only needed here */
10 : : static char *
9 tgl@sss.pgh.pa.us 11 :GNC 165 : loc_nstrdup(const char *in, size_t len)
12 : : {
13 : : char *out;
14 : :
15 : 165 : out = loc_alloc(len + 1);
16 : 165 : memcpy(out, in, len);
17 : 165 : out[len] = '\0';
18 : :
19 : 165 : return out;
20 : : }
21 : :
22 : : struct variable *
3100 tgl@sss.pgh.pa.us 23 :CBC 520 : new_variable(const char *name, struct ECPGtype *type, int brace_level)
24 : : {
9379 bruce@momjian.us 25 : 520 : struct variable *p = (struct variable *) mm_alloc(sizeof(struct variable));
26 : :
27 : 520 : p->name = mm_strdup(name);
28 : 520 : p->type = type;
8738 meskes@postgresql.or 29 : 520 : p->brace_level = brace_level;
30 : :
9379 bruce@momjian.us 31 : 520 : p->next = allvariables;
32 : 520 : allvariables = p;
33 : :
3043 peter_e@gmx.net 34 : 520 : return p;
35 : : }
36 : :
37 : : /*
38 : : * Perform lookup of a field within a struct
39 : : *
40 : : * 'name' is the entire C variable name
41 : : * 'str' points just before the next field name to parse
42 : : * 'members' and 'brace_level' describe the struct we are looking into
43 : : *
44 : : * Returns NULL if field is not found.
45 : : *
46 : : * This recurses if needed to handle sub-fields.
47 : : */
48 : : static struct variable *
9 tgl@sss.pgh.pa.us 49 :GNC 65 : find_struct_member(const char *name, const char *str,
50 : : struct ECPGstruct_member *members, int brace_level)
51 : : {
52 : : /* ++ here skips over the '.', or the '>' of '->' */
53 : 65 : const char *next = strpbrk(++str, ".-["),
54 : : *end,
55 : : *field;
56 : :
9379 bruce@momjian.us 57 [ + + ]:CBC 65 : if (next != NULL)
9 tgl@sss.pgh.pa.us 58 :GNC 12 : field = loc_nstrdup(str, next - str);
59 : : else
60 : 53 : field = str;
61 : :
9379 bruce@momjian.us 62 [ + - ]:CBC 104 : for (; members; members = members->next)
63 : : {
9 tgl@sss.pgh.pa.us 64 [ + + ]:GNC 104 : if (strcmp(members->name, field) == 0)
65 : : {
8237 meskes@postgresql.or 66 [ + + ]:CBC 65 : if (next == NULL)
67 : : {
68 : : /* found the end */
8759 69 [ - - + ]: 53 : switch (members->type->type)
70 : : {
9379 bruce@momjian.us 71 :UBC 0 : case ECPGt_array:
3043 peter_e@gmx.net 72 : 0 : return new_variable(name, ECPGmake_array_type(ECPGmake_simple_type(members->type->u.element->type, members->type->u.element->size, members->type->u.element->counter), members->type->size), brace_level);
9379 bruce@momjian.us 73 : 0 : case ECPGt_struct:
74 : : case ECPGt_union:
3043 peter_e@gmx.net 75 : 0 : return new_variable(name, ECPGmake_struct_type(members->type->u.members, members->type->type, members->type->type_name, members->type->struct_sizeof), brace_level);
9379 bruce@momjian.us 76 :CBC 53 : default:
3043 peter_e@gmx.net 77 : 53 : return new_variable(name, ECPGmake_simple_type(members->type->type, members->type->size, members->type->counter), brace_level);
78 : : }
79 : : }
80 : : else
81 : : {
9 tgl@sss.pgh.pa.us 82 [ + - ]:GNC 12 : if (*next == '[')
83 : : {
84 : : int count;
85 : :
86 : : /*
87 : : * We don't care about what's inside the array brackets so
88 : : * just scan to find the matching right bracket.
89 : : */
8170 bruce@momjian.us 90 [ + + ]:GBC 36 : for (count = 1, end = next + 1; count; end++)
91 : : {
92 [ - + + ]: 24 : switch (*end)
93 : : {
8170 bruce@momjian.us 94 :UBC 0 : case '[':
95 : 0 : count++;
96 : 0 : break;
8170 bruce@momjian.us 97 :GBC 12 : case ']':
98 : 12 : count--;
99 : 12 : break;
100 : 12 : default:
101 : 12 : break;
102 : : }
103 : : }
104 : : }
105 : : else
8170 bruce@momjian.us 106 :UBC 0 : end = next;
107 : :
8237 meskes@postgresql.or 108 [ - - + - ]:GBC 12 : switch (*end)
109 : : {
7367 bruce@momjian.us 110 :UBC 0 : case '\0': /* found the end, but this time it has to be
111 : : * an array element */
8170 112 [ # # ]: 0 : if (members->type->type != ECPGt_array)
4417 peter_e@gmx.net 113 : 0 : mmfatal(PARSE_ERROR, "incorrectly formed variable \"%s\"", name);
114 : :
8170 bruce@momjian.us 115 [ # # # ]: 0 : switch (members->type->u.element->type)
116 : : {
117 : 0 : case ECPGt_array:
3043 peter_e@gmx.net 118 : 0 : return new_variable(name, ECPGmake_array_type(ECPGmake_simple_type(members->type->u.element->u.element->type, members->type->u.element->u.element->size, members->type->u.element->u.element->counter), members->type->u.element->size), brace_level);
8170 bruce@momjian.us 119 : 0 : case ECPGt_struct:
120 : : case ECPGt_union:
3043 peter_e@gmx.net 121 : 0 : return new_variable(name, ECPGmake_struct_type(members->type->u.element->u.members, members->type->u.element->type, members->type->u.element->type_name, members->type->u.element->struct_sizeof), brace_level);
8170 bruce@momjian.us 122 : 0 : default:
3043 peter_e@gmx.net 123 : 0 : return new_variable(name, ECPGmake_simple_type(members->type->u.element->type, members->type->u.element->size, members->type->u.element->counter), brace_level);
124 : : }
125 : : break;
8170 bruce@momjian.us 126 : 0 : case '-':
4765 meskes@postgresql.or 127 [ # # ]: 0 : if (members->type->type == ECPGt_array)
3043 peter_e@gmx.net 128 : 0 : return find_struct_member(name, ++end, members->type->u.element->u.members, brace_level);
129 : : else
130 : 0 : return find_struct_member(name, ++end, members->type->u.members, brace_level);
131 : : break;
8170 bruce@momjian.us 132 :GBC 12 : case '.':
7993 meskes@postgresql.or 133 [ - + ]: 12 : if (members->type->type == ECPGt_array)
3043 peter_e@gmx.net 134 :UBC 0 : return find_struct_member(name, end, members->type->u.element->u.members, brace_level);
135 : : else
3043 peter_e@gmx.net 136 :GBC 12 : return find_struct_member(name, end, members->type->u.members, brace_level);
137 : : break;
8170 bruce@momjian.us 138 :UBC 0 : default:
4417 peter_e@gmx.net 139 : 0 : mmfatal(PARSE_ERROR, "incorrectly formed variable \"%s\"", name);
140 : : break;
141 : : }
142 : : }
143 : : }
144 : : }
145 : :
3043 146 : 0 : return NULL;
147 : : }
148 : :
149 : : /*
150 : : * Do struct lookup when we have found var.field, var->field, or var[n].field
151 : : *
152 : : * 'name' is the entire C variable name
153 : : * 'next' points at the character after the base name
154 : : * 'end' points at the character after the subscript, if there was a
155 : : * subscript, else it's the same as 'next'.
156 : : *
157 : : * This is used only at the first level of field reference; sub-fields will
158 : : * be handled by internal recursion in find_struct_member.
159 : : */
160 : : static struct variable *
9 tgl@sss.pgh.pa.us 161 :GNC 53 : find_struct(const char *name, const char *next, const char *end)
162 : : {
163 : : char *prefix;
164 : : struct variable *p;
165 : :
166 : : /* first get the mother structure entry */
167 : 53 : prefix = loc_nstrdup(name, next - name);
168 : 53 : p = find_variable(prefix);
169 : :
170 [ + + ]: 53 : if (*next == '-')
171 : : {
172 : : /* We have var->field */
8759 meskes@postgresql.or 173 [ - + ]:GBC 6 : if (p->type->type != ECPGt_array)
9 tgl@sss.pgh.pa.us 174 :UNC 0 : mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer", prefix);
175 : :
8759 meskes@postgresql.or 176 [ - + - - ]:GBC 6 : if (p->type->u.element->type != ECPGt_struct && p->type->u.element->type != ECPGt_union)
9 tgl@sss.pgh.pa.us 177 :UNC 0 : mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer to a structure or a union", prefix);
178 : :
8224 meskes@postgresql.or 179 :GBC 6 : return find_struct_member(name, ++end, p->type->u.element->u.members, p->brace_level);
180 : : }
181 : : else
182 : : {
8237 meskes@postgresql.or 183 [ + + ]:CBC 47 : if (next == end)
184 : : {
185 : : /* We have var.field */
186 [ + + - + ]: 41 : if (p->type->type != ECPGt_struct && p->type->type != ECPGt_union)
9 tgl@sss.pgh.pa.us 187 :UNC 0 : mmfatal(PARSE_ERROR, "variable \"%s\" is neither a structure nor a union", prefix);
188 : :
8237 meskes@postgresql.or 189 :CBC 41 : return find_struct_member(name, end, p->type->u.members, p->brace_level);
190 : : }
191 : : else
192 : : {
193 : : /* We have var[n].field */
8237 meskes@postgresql.or 194 [ - + ]:GBC 6 : if (p->type->type != ECPGt_array)
9 tgl@sss.pgh.pa.us 195 :UNC 0 : mmfatal(PARSE_ERROR, "variable \"%s\" is not an array", prefix);
196 : :
8237 meskes@postgresql.or 197 [ - + - - ]:GBC 6 : if (p->type->u.element->type != ECPGt_struct && p->type->u.element->type != ECPGt_union)
9 tgl@sss.pgh.pa.us 198 :UNC 0 : mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer to a structure or a union", prefix);
199 : :
8237 meskes@postgresql.or 200 :GBC 6 : return find_struct_member(name, end, p->type->u.element->u.members, p->brace_level);
201 : : }
202 : : }
203 : : }
204 : :
205 : : /* Look up a variable given its base name */
206 : : static struct variable *
428 tgl@sss.pgh.pa.us 207 :CBC 1391 : find_simple(const char *name)
208 : : {
209 : : struct variable *p;
210 : :
9379 bruce@momjian.us 211 [ + - ]: 11503 : for (p = allvariables; p; p = p->next)
212 : : {
213 [ + + ]: 11503 : if (strcmp(p->name, name) == 0)
214 : 1391 : return p;
215 : : }
216 : :
3043 peter_e@gmx.net 217 :UBC 0 : return NULL;
218 : : }
219 : :
220 : : /*
221 : : * Build a "struct variable" for a C variable reference.
222 : : *
223 : : * The given "name" string is a CVARIABLE per pgc.l, so it can include not
224 : : * only a base variable name but also ".field", "->field", or "[subscript]"
225 : : * decoration. We don't need to understand that fully, because we always
226 : : * duplicate the whole string into the name field of the result variable
227 : : * and emit it literally to the output file; the C compiler will make sense
228 : : * of it later. What we do need to do here is identify the type of the
229 : : * target field or array element so that we can attach a correct ECPGtype
230 : : * struct to the result.
231 : : *
232 : : * Note that this function will end the program in case of an unknown variable.
233 : : */
234 : : struct variable *
428 tgl@sss.pgh.pa.us 235 :CBC 1444 : find_variable(const char *name)
236 : : {
237 : : const char *next,
238 : : *end;
239 : : struct variable *p;
240 : : int count;
241 : :
8237 meskes@postgresql.or 242 : 1444 : next = strpbrk(name, ".[-");
243 [ + + ]: 1444 : if (next)
244 : : {
245 : : /* Deal with field/subscript decoration */
246 [ + + ]: 153 : if (*next == '[')
247 : : {
248 : : /*
249 : : * We don't care about what's inside the array brackets so just
250 : : * scan to find the matching right bracket.
251 : : */
8170 bruce@momjian.us 252 [ + + ]: 318 : for (count = 1, end = next + 1; count; end++)
253 : : {
254 [ - + - + ]: 212 : switch (*end)
255 : : {
8170 bruce@momjian.us 256 :UBC 0 : case '[':
257 : 0 : count++;
258 : 0 : break;
8170 bruce@momjian.us 259 :CBC 106 : case ']':
260 : 106 : count--;
261 : 106 : break;
426 tgl@sss.pgh.pa.us 262 :UBC 0 : case '\0':
235 peter@eisentraut.org 263 : 0 : mmfatal(PARSE_ERROR, "unmatched bracket in variable \"%s\"", name);
264 : : break;
8170 bruce@momjian.us 265 :CBC 106 : default:
266 : 106 : break;
267 : : }
268 : : }
269 [ + + ]: 106 : if (*end == '.')
270 : : {
271 : : /* We have var[n].field */
8170 bruce@momjian.us 272 :GBC 6 : p = find_struct(name, next, end);
273 : : }
274 : : else
275 : : {
276 : : /*
277 : : * Note: this part assumes we must just have var[n] without
278 : : * any further decoration, which fails to handle cases such as
279 : : * var[n]->field. For now, that's okay because
280 : : * pointer-to-pointer variables are rejected elsewhere.
281 : : */
9 tgl@sss.pgh.pa.us 282 :GNC 100 : char *prefix = loc_nstrdup(name, next - name);
283 : :
284 : 100 : p = find_simple(prefix);
7957 meskes@postgresql.or 285 [ - + ]:CBC 100 : if (p == NULL)
9 tgl@sss.pgh.pa.us 286 :UNC 0 : mmfatal(PARSE_ERROR, "variable \"%s\" is not declared", prefix);
425 tgl@sss.pgh.pa.us 287 [ - + ]:CBC 100 : if (p->type->type != ECPGt_array)
9 tgl@sss.pgh.pa.us 288 :UNC 0 : mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer", prefix);
8237 meskes@postgresql.or 289 [ - + + ]:CBC 100 : switch (p->type->u.element->type)
290 : : {
8237 meskes@postgresql.or 291 :UBC 0 : case ECPGt_array:
3043 peter_e@gmx.net 292 : 0 : return new_variable(name, ECPGmake_array_type(ECPGmake_simple_type(p->type->u.element->u.element->type, p->type->u.element->u.element->size, p->type->u.element->u.element->counter), p->type->u.element->size), p->brace_level);
8237 meskes@postgresql.or 293 :CBC 3 : case ECPGt_struct:
294 : : case ECPGt_union:
3043 peter_e@gmx.net 295 : 3 : return new_variable(name, ECPGmake_struct_type(p->type->u.element->u.members, p->type->u.element->type, p->type->u.element->type_name, p->type->u.element->struct_sizeof), p->brace_level);
8237 meskes@postgresql.or 296 : 97 : default:
3043 peter_e@gmx.net 297 : 97 : return new_variable(name, ECPGmake_simple_type(p->type->u.element->type, p->type->u.element->size, p->type->u.element->counter), p->brace_level);
298 : : }
299 : : }
300 : : }
301 : : else
302 : : {
303 : : /* Must be var.field or var->field */
8170 bruce@momjian.us 304 : 47 : p = find_struct(name, next, next);
305 : : }
306 : : }
307 : : else
308 : 1291 : p = find_simple(name);
309 : :
9379 310 [ - + ]: 1344 : if (p == NULL)
4417 peter_e@gmx.net 311 :UBC 0 : mmfatal(PARSE_ERROR, "variable \"%s\" is not declared", name);
312 : :
3043 peter_e@gmx.net 313 :CBC 1344 : return p;
314 : : }
315 : :
316 : : void
7842 meskes@postgresql.or 317 : 331 : remove_typedefs(int brace_level)
318 : : {
319 : : struct typedefs *p,
320 : : *prev,
321 : : *next;
322 : :
380 tgl@sss.pgh.pa.us 323 [ + + ]: 495 : for (p = types, prev = NULL; p; p = next)
324 : : {
325 : 164 : next = p->next;
7842 meskes@postgresql.or 326 [ + + ]: 164 : if (p->brace_level >= brace_level)
327 : : {
328 : : /* remove it */
380 tgl@sss.pgh.pa.us 329 [ - + ]: 14 : if (prev)
380 tgl@sss.pgh.pa.us 330 :UBC 0 : prev->next = next;
331 : : else
380 tgl@sss.pgh.pa.us 332 :CBC 14 : types = next;
333 : :
7779 bruce@momjian.us 334 [ + + - + ]: 14 : if (p->type->type_enum == ECPGt_struct || p->type->type_enum == ECPGt_union)
384 tgl@sss.pgh.pa.us 335 : 12 : ECPGfree_struct_member(p->struct_member_list);
336 : 14 : free(p->type->type_storage);
337 : 14 : free(p->type->type_str);
338 : 14 : free(p->type->type_dimension);
339 : 14 : free(p->type->type_index);
340 : 14 : free(p->type->type_sizeof);
7842 meskes@postgresql.or 341 : 14 : free(p->type);
342 : 14 : free(p->name);
343 : 14 : free(p);
344 : : }
345 : : else
346 : 150 : prev = p;
347 : : }
348 : 331 : }
349 : :
350 : : void
9434 351 : 331 : remove_variables(int brace_level)
352 : : {
353 : : struct variable *p,
354 : : *prev,
355 : : *next;
356 : :
380 tgl@sss.pgh.pa.us 357 [ + + ]: 1673 : for (p = allvariables, prev = NULL; p; p = next)
358 : : {
359 : 1342 : next = p->next;
9379 bruce@momjian.us 360 [ + + ]: 1342 : if (p->brace_level >= brace_level)
361 : : {
362 : : /* remove it, but first remove any references from cursors */
363 : : struct cursor *ptr;
364 : :
8170 365 [ + + ]: 789 : for (ptr = cur; ptr != NULL; ptr = ptr->next)
366 : : {
367 : : struct arguments *varptr,
368 : : *prevvar,
369 : : *nextvar;
370 : :
380 tgl@sss.pgh.pa.us 371 : 369 : for (varptr = ptr->argsinsert, prevvar = NULL;
372 [ + + ]: 630 : varptr != NULL; varptr = nextvar)
373 : : {
384 374 : 261 : nextvar = varptr->next;
8224 meskes@postgresql.or 375 [ + + ]: 261 : if (p == varptr->variable)
376 : : {
377 : : /* remove from list */
380 tgl@sss.pgh.pa.us 378 [ + + ]: 12 : if (prevvar)
379 : 3 : prevvar->next = nextvar;
380 : : else
381 : 9 : ptr->argsinsert = nextvar;
384 382 : 12 : free(varptr);
383 : : }
384 : : else
380 385 : 249 : prevvar = varptr;
386 : : }
387 : 369 : for (varptr = ptr->argsresult, prevvar = NULL;
388 [ + + ]: 374 : varptr != NULL; varptr = nextvar)
389 : : {
384 390 : 5 : nextvar = varptr->next;
8224 meskes@postgresql.or 391 [ + + ]: 5 : if (p == varptr->variable)
392 : : {
393 : : /* remove from list */
380 tgl@sss.pgh.pa.us 394 [ - + ]: 3 : if (prevvar)
380 tgl@sss.pgh.pa.us 395 :UBC 0 : prevvar->next = nextvar;
396 : : else
380 tgl@sss.pgh.pa.us 397 :CBC 3 : ptr->argsresult = nextvar;
384 398 : 3 : free(varptr);
399 : : }
400 : : else
380 401 : 2 : prevvar = varptr;
402 : : }
403 : : }
404 : :
405 : : /* remove it */
406 [ + + ]: 420 : if (prev)
407 : 163 : prev->next = next;
408 : : else
409 : 257 : allvariables = next;
410 : :
9379 bruce@momjian.us 411 : 420 : ECPGfree_type(p->type);
412 : 420 : free(p->name);
413 : 420 : free(p);
414 : : }
415 : : else
416 : 922 : prev = p;
417 : : }
9434 meskes@postgresql.or 418 : 331 : }
419 : :
420 : :
421 : : /*
422 : : * Here are the variables that need to be handled on every request.
423 : : * These are of two kinds: input and output.
424 : : * I will make two lists for them.
425 : : */
426 : :
427 : : struct arguments *argsinsert = NULL;
428 : : struct arguments *argsresult = NULL;
429 : :
430 : : void
431 : 1458 : reset_variables(void)
432 : : {
433 : : struct arguments *p,
434 : : *next;
435 : :
384 tgl@sss.pgh.pa.us 436 [ + + ]: 1460 : for (p = argsinsert; p; p = next)
437 : : {
438 : 2 : next = p->next;
439 : 2 : free(p);
440 : : }
9379 bruce@momjian.us 441 : 1458 : argsinsert = NULL;
384 tgl@sss.pgh.pa.us 442 [ - + ]: 1458 : for (p = argsresult; p; p = next)
443 : : {
384 tgl@sss.pgh.pa.us 444 :UBC 0 : next = p->next;
445 : 0 : free(p);
446 : : }
9379 bruce@momjian.us 447 :CBC 1458 : argsresult = NULL;
9434 meskes@postgresql.or 448 : 1458 : }
449 : :
450 : : /* Insert a new variable into our request list.
451 : : * Note: The list is dumped from the end,
452 : : * so we have to add new entries at the beginning */
453 : : void
3100 tgl@sss.pgh.pa.us 454 : 515 : add_variable_to_head(struct arguments **list, struct variable *var, struct variable *ind)
455 : : {
9379 bruce@momjian.us 456 : 515 : struct arguments *p = (struct arguments *) mm_alloc(sizeof(struct arguments));
457 : :
458 : 515 : p->variable = var;
459 : 515 : p->indicator = ind;
460 : 515 : p->next = *list;
461 : 515 : *list = p;
9434 meskes@postgresql.or 462 : 515 : }
463 : :
464 : : /* Append a new variable to our request list. */
465 : : void
3100 tgl@sss.pgh.pa.us 466 : 97 : add_variable_to_tail(struct arguments **list, struct variable *var, struct variable *ind)
467 : : {
468 : : struct arguments *p,
9379 bruce@momjian.us 469 : 97 : *new = (struct arguments *) mm_alloc(sizeof(struct arguments));
470 : :
471 [ + + + + ]: 104 : for (p = *list; p && p->next; p = p->next);
472 : :
473 : 97 : new->variable = var;
474 : 97 : new->indicator = ind;
475 : 97 : new->next = NULL;
476 : :
477 [ + + ]: 97 : if (p)
478 : 26 : p->next = new;
479 : : else
480 : 71 : *list = new;
9413 meskes@postgresql.or 481 : 97 : }
482 : :
483 : : void
3100 tgl@sss.pgh.pa.us 484 : 17 : remove_variable_from_list(struct arguments **list, struct variable *var)
485 : : {
486 : : struct arguments *p,
5772 bruce@momjian.us 487 : 17 : *prev = NULL;
488 : 17 : bool found = false;
489 : :
5864 meskes@postgresql.or 490 [ + - ]: 17 : for (p = *list; p; p = p->next)
491 : : {
492 [ + - ]: 17 : if (p->variable == var)
493 : : {
494 : 17 : found = true;
495 : 17 : break;
496 : : }
5864 meskes@postgresql.or 497 :UBC 0 : prev = p;
498 : : }
5864 meskes@postgresql.or 499 [ + - ]:CBC 17 : if (found)
500 : : {
501 [ - + ]: 17 : if (prev)
5864 meskes@postgresql.or 502 :UBC 0 : prev->next = p->next;
503 : : else
5864 meskes@postgresql.or 504 :CBC 17 : *list = p->next;
384 tgl@sss.pgh.pa.us 505 : 17 : free(p);
506 : : }
5864 meskes@postgresql.or 507 : 17 : }
508 : :
509 : : /* Dump out a list of all the variable on this list.
510 : : This is a recursive function that works from the end of the list and
511 : : deletes the list as we go on.
512 : : */
513 : : void
3100 tgl@sss.pgh.pa.us 514 : 1656 : dump_variables(struct arguments *list, int mode)
515 : : {
516 : : char *str_zero;
517 : :
9379 bruce@momjian.us 518 [ + + ]: 1656 : if (list == NULL)
519 : 1133 : return;
520 : :
3840 meskes@postgresql.or 521 : 523 : str_zero = mm_strdup("0");
522 : :
523 : : /*
524 : : * The list is build up from the beginning so lets first dump the end of
525 : : * the list:
526 : : */
527 : :
9379 bruce@momjian.us 528 : 523 : dump_variables(list->next, mode);
529 : :
530 : : /* Then the current element and its indicator */
3292 tgl@sss.pgh.pa.us 531 : 523 : ECPGdump_a_type(base_yyout, list->variable->name, list->variable->type, list->variable->brace_level,
5738 meskes@postgresql.or 532 : 523 : list->indicator->name, list->indicator->type, list->indicator->brace_level,
533 : : NULL, NULL, str_zero, NULL, NULL);
534 : :
535 : : /* Then release the list element. */
9379 bruce@momjian.us 536 [ + - ]: 523 : if (mode != 0)
537 : 523 : free(list);
538 : :
4308 sfrost@snowman.net 539 : 523 : free(str_zero);
540 : : }
541 : :
542 : : void
3100 tgl@sss.pgh.pa.us 543 : 67 : check_indicator(struct ECPGtype *var)
544 : : {
545 : : /* make sure this is a valid indicator variable */
8759 meskes@postgresql.or 546 [ + + + - ]: 67 : switch (var->type)
547 : : {
548 : : struct ECPGstruct_member *p;
549 : :
9434 550 : 45 : case ECPGt_short:
551 : : case ECPGt_int:
552 : : case ECPGt_long:
553 : : case ECPGt_long_long:
554 : : case ECPGt_unsigned_short:
555 : : case ECPGt_unsigned_int:
556 : : case ECPGt_unsigned_long:
557 : : case ECPGt_unsigned_long_long:
558 : 45 : break;
559 : :
560 : 11 : case ECPGt_struct:
561 : : case ECPGt_union:
562 [ + + ]: 36 : for (p = var->u.members; p; p = p->next)
8759 563 : 25 : check_indicator(p->type);
9434 564 : 11 : break;
565 : :
566 : 11 : case ECPGt_array:
567 : 11 : check_indicator(var->u.element);
568 : 11 : break;
9379 bruce@momjian.us 569 :UBC 0 : default:
6171 peter_e@gmx.net 570 : 0 : mmerror(PARSE_ERROR, ET_ERROR, "indicator variable must have an integer type");
9434 meskes@postgresql.or 571 : 0 : break;
572 : : }
9434 meskes@postgresql.or 573 :CBC 67 : }
574 : :
575 : : struct typedefs *
1253 tgl@sss.pgh.pa.us 576 : 5683 : get_typedef(const char *name, bool noerror)
577 : : {
578 : : struct typedefs *this;
579 : :
580 [ + + ]: 9280 : for (this = types; this != NULL; this = this->next)
581 : : {
582 [ + + ]: 3633 : if (strcmp(this->name, name) == 0)
583 : 36 : return this;
584 : : }
585 : :
586 [ - + ]: 5647 : if (!noerror)
4417 peter_e@gmx.net 587 :UBC 0 : mmfatal(PARSE_ERROR, "unrecognized data type name \"%s\"", name);
588 : :
1253 tgl@sss.pgh.pa.us 589 :CBC 5647 : return NULL;
590 : : }
591 : :
592 : : void
428 593 : 392 : adjust_array(enum ECPGttype type_enum,
594 : : const char **dimension, const char **length,
595 : : const char *type_dimension, const char *type_index,
596 : : int pointer_len, bool type_definition)
597 : : {
8252 meskes@postgresql.or 598 [ + + ]: 392 : if (atoi(type_index) >= 0)
599 : : {
600 [ - + ]: 6 : if (atoi(*length) >= 0)
4417 peter_e@gmx.net 601 :UBC 0 : mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
602 : :
9434 meskes@postgresql.or 603 :CBC 6 : *length = type_index;
604 : : }
605 : :
8252 606 [ + + ]: 392 : if (atoi(type_dimension) >= 0)
607 : : {
608 [ - + - - ]: 1 : if (atoi(*dimension) >= 0 && atoi(*length) >= 0)
4417 peter_e@gmx.net 609 :UBC 0 : mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
610 : :
8252 meskes@postgresql.or 611 [ - + ]:CBC 1 : if (atoi(*dimension) >= 0)
9434 meskes@postgresql.or 612 :UBC 0 : *length = *dimension;
613 : :
9434 meskes@postgresql.or 614 :CBC 1 : *dimension = type_dimension;
615 : : }
616 : :
8504 bruce@momjian.us 617 [ - + ]: 392 : if (pointer_len > 2)
4417 peter_e@gmx.net 618 :UBC 0 : mmfatal(PARSE_ERROR, ngettext("multilevel pointers (more than 2 levels) are not supported; found %d level",
619 : : "multilevel pointers (more than 2 levels) are not supported; found %d levels", pointer_len),
620 : : pointer_len);
621 : :
5975 meskes@postgresql.or 622 [ + + - + :CBC 392 : if (pointer_len > 1 && type_enum != ECPGt_char && type_enum != ECPGt_unsigned_char && type_enum != ECPGt_string)
- - - - ]
4417 peter_e@gmx.net 623 :UBC 0 : mmfatal(PARSE_ERROR, "pointer to pointer is not supported for this data type");
624 : :
8252 meskes@postgresql.or 625 [ + + + - :CBC 392 : if (pointer_len > 1 && (atoi(*length) >= 0 || atoi(*dimension) >= 0))
- + ]
4417 peter_e@gmx.net 626 :UBC 0 : mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
627 : :
8252 meskes@postgresql.or 628 [ + + + + :CBC 392 : if (atoi(*length) >= 0 && atoi(*dimension) >= 0 && pointer_len)
- + ]
4417 peter_e@gmx.net 629 :UBC 0 : mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
630 : :
9434 meskes@postgresql.or 631 [ + + + + ]:CBC 392 : switch (type_enum)
632 : : {
9379 bruce@momjian.us 633 : 40 : case ECPGt_struct:
634 : : case ECPGt_union:
635 : : /* pointer has to get dimension 0 */
8796 meskes@postgresql.or 636 [ + + ]: 40 : if (pointer_len)
637 : : {
9379 bruce@momjian.us 638 : 10 : *length = *dimension;
428 tgl@sss.pgh.pa.us 639 : 10 : *dimension = "0";
640 : : }
641 : :
8252 meskes@postgresql.or 642 [ - + ]: 40 : if (atoi(*length) >= 0)
4417 peter_e@gmx.net 643 :UBC 0 : mmfatal(PARSE_ERROR, "multidimensional arrays for structures are not supported");
644 : :
9379 bruce@momjian.us 645 :CBC 40 : break;
646 : 23 : case ECPGt_varchar:
647 : : case ECPGt_bytea:
648 : : /* pointer has to get dimension 0 */
8796 meskes@postgresql.or 649 [ - + ]: 23 : if (pointer_len)
428 tgl@sss.pgh.pa.us 650 :UBC 0 : *dimension = "0";
651 : :
652 : : /* one index is the string length */
8252 meskes@postgresql.or 653 [ + + ]:CBC 23 : if (atoi(*length) < 0)
654 : : {
9379 bruce@momjian.us 655 : 15 : *length = *dimension;
428 tgl@sss.pgh.pa.us 656 : 15 : *dimension = "-1";
657 : : }
658 : :
9379 bruce@momjian.us 659 : 23 : break;
660 : 129 : case ECPGt_char:
661 : : case ECPGt_unsigned_char:
662 : : case ECPGt_string:
663 : : /* char ** */
8504 664 [ + + ]: 129 : if (pointer_len == 2)
665 : : {
428 tgl@sss.pgh.pa.us 666 : 8 : *length = *dimension = "0";
8796 meskes@postgresql.or 667 : 8 : break;
668 : : }
669 : :
670 : : /* pointer has to get length 0 */
8504 bruce@momjian.us 671 [ + + ]: 121 : if (pointer_len == 1)
428 tgl@sss.pgh.pa.us 672 : 45 : *length = "0";
673 : :
674 : : /* one index is the string length */
8252 meskes@postgresql.or 675 [ + + ]: 121 : if (atoi(*length) < 0)
676 : : {
677 : : /*
678 : : * make sure we return length = -1 for arrays without given
679 : : * bounds
680 : : */
7893 681 [ + + + + ]: 66 : if (atoi(*dimension) < 0 && !type_definition)
682 : :
683 : : /*
684 : : * do not change this for typedefs since it will be
685 : : * changed later on when the variable is defined
686 : : */
428 tgl@sss.pgh.pa.us 687 : 5 : *length = "1";
7680 meskes@postgresql.or 688 [ + + ]: 61 : else if (strcmp(*dimension, "0") == 0)
428 tgl@sss.pgh.pa.us 689 : 2 : *length = "-1";
690 : : else
8198 meskes@postgresql.or 691 : 59 : *length = *dimension;
692 : :
428 tgl@sss.pgh.pa.us 693 : 66 : *dimension = "-1";
694 : : }
9379 bruce@momjian.us 695 : 121 : break;
696 : 200 : default:
697 : : /* a pointer has dimension = 0 */
8796 meskes@postgresql.or 698 [ + + ]: 200 : if (pointer_len)
699 : : {
9379 bruce@momjian.us 700 : 20 : *length = *dimension;
428 tgl@sss.pgh.pa.us 701 : 20 : *dimension = "0";
702 : : }
703 : :
8252 meskes@postgresql.or 704 [ - + ]: 200 : if (atoi(*length) >= 0)
4417 peter_e@gmx.net 705 :UBC 0 : mmfatal(PARSE_ERROR, "multidimensional arrays for simple data types are not supported");
706 : :
9379 bruce@momjian.us 707 :CBC 200 : break;
708 : : }
9434 meskes@postgresql.or 709 : 392 : }
|