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 : struct variable *
10 910 : new_variable(const char *name, struct ECPGtype *type, int brace_level)
11 : {
12 910 : struct variable *p = (struct variable *) mm_alloc(sizeof(struct variable));
13 :
14 910 : p->name = mm_strdup(name);
15 910 : p->type = type;
16 910 : p->brace_level = brace_level;
17 :
18 910 : p->next = allvariables;
19 910 : allvariables = p;
20 :
21 910 : return p;
22 : }
23 :
24 : static struct variable *
25 58 : find_struct_member(char *name, char *str, struct ECPGstruct_member *members, int brace_level)
26 : {
27 58 : char *next = strpbrk(++str, ".-["),
28 : *end,
29 58 : c = '\0';
30 :
31 58 : if (next != NULL)
32 : {
33 0 : c = *next;
34 0 : *next = '\0';
35 : }
36 :
37 112 : for (; members; members = members->next)
38 : {
39 112 : if (strcmp(members->name, str) == 0)
40 : {
41 58 : if (next == NULL)
42 : {
43 : /* found the end */
44 58 : switch (members->type->type)
45 : {
46 0 : case ECPGt_array:
47 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);
48 0 : case ECPGt_struct:
49 : case ECPGt_union:
50 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);
51 58 : default:
52 58 : return new_variable(name, ECPGmake_simple_type(members->type->type, members->type->size, members->type->counter), brace_level);
53 : }
54 : }
55 : else
56 : {
57 0 : *next = c;
58 0 : if (c == '[')
59 : {
60 : int count;
61 :
62 : /*
63 : * We don't care about what's inside the array braces so
64 : * just eat up the character
65 : */
66 0 : for (count = 1, end = next + 1; count; end++)
67 : {
68 0 : switch (*end)
69 : {
70 0 : case '[':
71 0 : count++;
72 0 : break;
73 0 : case ']':
74 0 : count--;
75 0 : break;
76 0 : default:
77 0 : break;
78 : }
79 : }
80 : }
81 : else
82 0 : end = next;
83 :
84 0 : switch (*end)
85 : {
86 0 : case '\0': /* found the end, but this time it has to be
87 : * an array element */
88 0 : if (members->type->type != ECPGt_array)
89 0 : mmfatal(PARSE_ERROR, "incorrectly formed variable \"%s\"", name);
90 :
91 0 : switch (members->type->u.element->type)
92 : {
93 0 : case ECPGt_array:
94 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);
95 0 : case ECPGt_struct:
96 : case ECPGt_union:
97 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);
98 0 : default:
99 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);
100 : }
101 : break;
102 0 : case '-':
103 0 : if (members->type->type == ECPGt_array)
104 0 : return find_struct_member(name, ++end, members->type->u.element->u.members, brace_level);
105 : else
106 0 : return find_struct_member(name, ++end, members->type->u.members, brace_level);
107 : break;
108 : break;
109 0 : case '.':
110 0 : if (members->type->type == ECPGt_array)
111 0 : return find_struct_member(name, end, members->type->u.element->u.members, brace_level);
112 : else
113 0 : return find_struct_member(name, end, members->type->u.members, brace_level);
114 : break;
115 0 : default:
116 0 : mmfatal(PARSE_ERROR, "incorrectly formed variable \"%s\"", name);
117 : break;
118 : }
119 : }
120 : }
121 : }
122 :
123 0 : return NULL;
124 : }
125 :
126 : static struct variable *
127 58 : find_struct(char *name, char *next, char *end)
128 : {
129 : struct variable *p;
130 58 : char c = *next;
131 :
132 : /* first get the mother structure entry */
133 58 : *next = '\0';
134 58 : p = find_variable(name);
135 :
136 58 : if (c == '-')
137 : {
138 0 : if (p->type->type != ECPGt_array)
139 0 : mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer", name);
140 :
141 0 : if (p->type->u.element->type != ECPGt_struct && p->type->u.element->type != ECPGt_union)
142 0 : mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer to a structure or a union", name);
143 :
144 : /* restore the name, we will need it later */
145 0 : *next = c;
146 :
147 0 : return find_struct_member(name, ++end, p->type->u.element->u.members, p->brace_level);
148 : }
149 : else
150 : {
151 58 : if (next == end)
152 : {
153 58 : if (p->type->type != ECPGt_struct && p->type->type != ECPGt_union)
154 0 : mmfatal(PARSE_ERROR, "variable \"%s\" is neither a structure nor a union", name);
155 :
156 : /* restore the name, we will need it later */
157 58 : *next = c;
158 :
159 58 : return find_struct_member(name, end, p->type->u.members, p->brace_level);
160 : }
161 : else
162 : {
163 0 : if (p->type->type != ECPGt_array)
164 0 : mmfatal(PARSE_ERROR, "variable \"%s\" is not an array", name);
165 :
166 0 : if (p->type->u.element->type != ECPGt_struct && p->type->u.element->type != ECPGt_union)
167 0 : mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer to a structure or a union", name);
168 :
169 : /* restore the name, we will need it later */
170 0 : *next = c;
171 :
172 0 : return find_struct_member(name, end, p->type->u.element->u.members, p->brace_level);
173 : }
174 : }
175 : }
176 :
177 : static struct variable *
178 2572 : find_simple(char *name)
179 : {
180 : struct variable *p;
181 :
182 20720 : for (p = allvariables; p; p = p->next)
183 : {
184 20720 : if (strcmp(p->name, name) == 0)
185 2572 : return p;
186 : }
187 :
188 0 : return NULL;
189 : }
190 :
191 : /* Note that this function will end the program in case of an unknown */
192 : /* variable */
193 : struct variable *
194 2630 : find_variable(char *name)
195 : {
196 : char *next,
197 : *end;
198 : struct variable *p;
199 : int count;
200 :
201 2630 : next = strpbrk(name, ".[-");
202 2630 : if (next)
203 : {
204 226 : if (*next == '[')
205 : {
206 : /*
207 : * We don't care about what's inside the array braces so just eat
208 : * up the characters
209 : */
210 504 : for (count = 1, end = next + 1; count; end++)
211 : {
212 336 : switch (*end)
213 : {
214 0 : case '[':
215 0 : count++;
216 0 : break;
217 168 : case ']':
218 168 : count--;
219 168 : break;
220 168 : default:
221 168 : break;
222 : }
223 : }
224 168 : if (*end == '.')
225 0 : p = find_struct(name, next, end);
226 : else
227 : {
228 168 : char c = *next;
229 :
230 168 : *next = '\0';
231 168 : p = find_simple(name);
232 168 : if (p == NULL)
233 0 : mmfatal(PARSE_ERROR, "variable \"%s\" is not declared", name);
234 :
235 168 : *next = c;
236 168 : switch (p->type->u.element->type)
237 : {
238 0 : case ECPGt_array:
239 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);
240 6 : case ECPGt_struct:
241 : case ECPGt_union:
242 6 : 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);
243 162 : default:
244 162 : 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);
245 : }
246 : }
247 : }
248 : else
249 58 : p = find_struct(name, next, next);
250 : }
251 : else
252 2404 : p = find_simple(name);
253 :
254 2462 : if (p == NULL)
255 0 : mmfatal(PARSE_ERROR, "variable \"%s\" is not declared", name);
256 :
257 2462 : return p;
258 : }
259 :
260 : void
261 644 : remove_typedefs(int brace_level)
262 : {
263 : struct typedefs *p,
264 : *prev;
265 :
266 950 : for (p = prev = types; p;)
267 : {
268 306 : if (p->brace_level >= brace_level)
269 : {
270 : /* remove it */
271 26 : if (p == types)
272 26 : prev = types = p->next;
273 : else
274 0 : prev->next = p->next;
275 :
276 26 : if (p->type->type_enum == ECPGt_struct || p->type->type_enum == ECPGt_union)
277 24 : free(p->struct_member_list);
278 26 : free(p->type);
279 26 : free(p->name);
280 26 : free(p);
281 26 : if (prev == types)
282 26 : p = types;
283 : else
284 0 : p = prev ? prev->next : NULL;
285 : }
286 : else
287 : {
288 280 : prev = p;
289 280 : p = prev->next;
290 : }
291 : }
292 644 : }
293 :
294 : void
295 644 : remove_variables(int brace_level)
296 : {
297 : struct variable *p,
298 : *prev;
299 :
300 3026 : for (p = prev = allvariables; p;)
301 : {
302 2382 : if (p->brace_level >= brace_level)
303 : {
304 : /* is it still referenced by a cursor? */
305 : struct cursor *ptr;
306 :
307 1436 : for (ptr = cur; ptr != NULL; ptr = ptr->next)
308 : {
309 : struct arguments *varptr,
310 : *prevvar;
311 :
312 1208 : for (varptr = prevvar = ptr->argsinsert; varptr != NULL; varptr = varptr->next)
313 : {
314 506 : if (p == varptr->variable)
315 : {
316 : /* remove from list */
317 20 : if (varptr == ptr->argsinsert)
318 14 : ptr->argsinsert = varptr->next;
319 : else
320 6 : prevvar->next = varptr->next;
321 : }
322 : }
323 712 : for (varptr = prevvar = ptr->argsresult; varptr != NULL; varptr = varptr->next)
324 : {
325 10 : if (p == varptr->variable)
326 : {
327 : /* remove from list */
328 6 : if (varptr == ptr->argsresult)
329 6 : ptr->argsresult = varptr->next;
330 : else
331 0 : prevvar->next = varptr->next;
332 : }
333 : }
334 : }
335 :
336 : /* remove it */
337 734 : if (p == allvariables)
338 412 : prev = allvariables = p->next;
339 : else
340 322 : prev->next = p->next;
341 :
342 734 : ECPGfree_type(p->type);
343 734 : free(p->name);
344 734 : free(p);
345 734 : if (prev == allvariables)
346 468 : p = allvariables;
347 : else
348 266 : p = prev ? prev->next : NULL;
349 : }
350 : else
351 : {
352 1648 : prev = p;
353 1648 : p = prev->next;
354 : }
355 : }
356 644 : }
357 :
358 :
359 : /*
360 : * Here are the variables that need to be handled on every request.
361 : * These are of two kinds: input and output.
362 : * I will make two lists for them.
363 : */
364 :
365 : struct arguments *argsinsert = NULL;
366 : struct arguments *argsresult = NULL;
367 :
368 : void
369 3788 : reset_variables(void)
370 : {
371 3788 : argsinsert = NULL;
372 3788 : argsresult = NULL;
373 3788 : }
374 :
375 : /* Insert a new variable into our request list.
376 : * Note: The list is dumped from the end,
377 : * so we have to add new entries at the beginning */
378 : void
379 930 : add_variable_to_head(struct arguments **list, struct variable *var, struct variable *ind)
380 : {
381 930 : struct arguments *p = (struct arguments *) mm_alloc(sizeof(struct arguments));
382 :
383 930 : p->variable = var;
384 930 : p->indicator = ind;
385 930 : p->next = *list;
386 930 : *list = p;
387 930 : }
388 :
389 : /* Append a new variable to our request list. */
390 : void
391 186 : add_variable_to_tail(struct arguments **list, struct variable *var, struct variable *ind)
392 : {
393 : struct arguments *p,
394 186 : *new = (struct arguments *) mm_alloc(sizeof(struct arguments));
395 :
396 200 : for (p = *list; p && p->next; p = p->next);
397 :
398 186 : new->variable = var;
399 186 : new->indicator = ind;
400 186 : new->next = NULL;
401 :
402 186 : if (p)
403 52 : p->next = new;
404 : else
405 134 : *list = new;
406 186 : }
407 :
408 : void
409 34 : remove_variable_from_list(struct arguments **list, struct variable *var)
410 : {
411 : struct arguments *p,
412 34 : *prev = NULL;
413 34 : bool found = false;
414 :
415 34 : for (p = *list; p; p = p->next)
416 : {
417 34 : if (p->variable == var)
418 : {
419 34 : found = true;
420 34 : break;
421 : }
422 0 : prev = p;
423 : }
424 34 : if (found)
425 : {
426 34 : if (prev)
427 0 : prev->next = p->next;
428 : else
429 34 : *list = p->next;
430 : }
431 34 : }
432 :
433 : /* Dump out a list of all the variable on this list.
434 : This is a recursive function that works from the end of the list and
435 : deletes the list as we go on.
436 : */
437 : void
438 3060 : dump_variables(struct arguments *list, int mode)
439 : {
440 : char *str_zero;
441 :
442 3060 : if (list == NULL)
443 2110 : return;
444 :
445 950 : str_zero = mm_strdup("0");
446 :
447 : /*
448 : * The list is build up from the beginning so lets first dump the end of
449 : * the list:
450 : */
451 :
452 950 : dump_variables(list->next, mode);
453 :
454 : /* Then the current element and its indicator */
455 950 : ECPGdump_a_type(base_yyout, list->variable->name, list->variable->type, list->variable->brace_level,
456 950 : list->indicator->name, list->indicator->type, list->indicator->brace_level,
457 : NULL, NULL, str_zero, NULL, NULL);
458 :
459 : /* Then release the list element. */
460 950 : if (mode != 0)
461 950 : free(list);
462 :
463 950 : free(str_zero);
464 : }
465 :
466 : void
467 134 : check_indicator(struct ECPGtype *var)
468 : {
469 : /* make sure this is a valid indicator variable */
470 134 : switch (var->type)
471 : {
472 : struct ECPGstruct_member *p;
473 :
474 90 : case ECPGt_short:
475 : case ECPGt_int:
476 : case ECPGt_long:
477 : case ECPGt_long_long:
478 : case ECPGt_unsigned_short:
479 : case ECPGt_unsigned_int:
480 : case ECPGt_unsigned_long:
481 : case ECPGt_unsigned_long_long:
482 90 : break;
483 :
484 22 : case ECPGt_struct:
485 : case ECPGt_union:
486 72 : for (p = var->u.members; p; p = p->next)
487 50 : check_indicator(p->type);
488 22 : break;
489 :
490 22 : case ECPGt_array:
491 22 : check_indicator(var->u.element);
492 22 : break;
493 0 : default:
494 0 : mmerror(PARSE_ERROR, ET_ERROR, "indicator variable must have an integer type");
495 0 : break;
496 : }
497 134 : }
498 :
499 : struct typedefs *
500 10560 : get_typedef(const char *name, bool noerror)
501 : {
502 : struct typedefs *this;
503 :
504 17354 : for (this = types; this != NULL; this = this->next)
505 : {
506 6854 : if (strcmp(this->name, name) == 0)
507 60 : return this;
508 : }
509 :
510 10500 : if (!noerror)
511 0 : mmfatal(PARSE_ERROR, "unrecognized data type name \"%s\"", name);
512 :
513 10500 : return NULL;
514 : }
515 :
516 : void
517 726 : adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *type_dimension, char *type_index, int pointer_len, bool type_definition)
518 : {
519 726 : if (atoi(type_index) >= 0)
520 : {
521 12 : if (atoi(*length) >= 0)
522 0 : mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
523 :
524 12 : *length = type_index;
525 : }
526 :
527 726 : if (atoi(type_dimension) >= 0)
528 : {
529 2 : if (atoi(*dimension) >= 0 && atoi(*length) >= 0)
530 0 : mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
531 :
532 2 : if (atoi(*dimension) >= 0)
533 0 : *length = *dimension;
534 :
535 2 : *dimension = type_dimension;
536 : }
537 :
538 726 : if (pointer_len > 2)
539 0 : mmfatal(PARSE_ERROR, ngettext("multilevel pointers (more than 2 levels) are not supported; found %d level",
540 : "multilevel pointers (more than 2 levels) are not supported; found %d levels", pointer_len),
541 : pointer_len);
542 :
543 726 : if (pointer_len > 1 && type_enum != ECPGt_char && type_enum != ECPGt_unsigned_char && type_enum != ECPGt_string)
544 0 : mmfatal(PARSE_ERROR, "pointer to pointer is not supported for this data type");
545 :
546 726 : if (pointer_len > 1 && (atoi(*length) >= 0 || atoi(*dimension) >= 0))
547 0 : mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
548 :
549 726 : if (atoi(*length) >= 0 && atoi(*dimension) >= 0 && pointer_len)
550 0 : mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
551 :
552 726 : switch (type_enum)
553 : {
554 68 : case ECPGt_struct:
555 : case ECPGt_union:
556 : /* pointer has to get dimension 0 */
557 68 : if (pointer_len)
558 : {
559 18 : *length = *dimension;
560 18 : *dimension = mm_strdup("0");
561 : }
562 :
563 68 : if (atoi(*length) >= 0)
564 0 : mmfatal(PARSE_ERROR, "multidimensional arrays for structures are not supported");
565 :
566 68 : break;
567 40 : case ECPGt_varchar:
568 : case ECPGt_bytea:
569 : /* pointer has to get dimension 0 */
570 40 : if (pointer_len)
571 0 : *dimension = mm_strdup("0");
572 :
573 : /* one index is the string length */
574 40 : if (atoi(*length) < 0)
575 : {
576 24 : *length = *dimension;
577 24 : *dimension = mm_strdup("-1");
578 : }
579 :
580 40 : break;
581 234 : case ECPGt_char:
582 : case ECPGt_unsigned_char:
583 : case ECPGt_string:
584 : /* char ** */
585 234 : if (pointer_len == 2)
586 : {
587 16 : *length = *dimension = mm_strdup("0");
588 16 : break;
589 : }
590 :
591 : /* pointer has to get length 0 */
592 218 : if (pointer_len == 1)
593 72 : *length = mm_strdup("0");
594 :
595 : /* one index is the string length */
596 218 : if (atoi(*length) < 0)
597 : {
598 : /*
599 : * make sure we return length = -1 for arrays without given
600 : * bounds
601 : */
602 126 : if (atoi(*dimension) < 0 && !type_definition)
603 :
604 : /*
605 : * do not change this for typedefs since it will be
606 : * changed later on when the variable is defined
607 : */
608 10 : *length = mm_strdup("1");
609 116 : else if (strcmp(*dimension, "0") == 0)
610 4 : *length = mm_strdup("-1");
611 : else
612 112 : *length = *dimension;
613 :
614 126 : *dimension = mm_strdup("-1");
615 : }
616 218 : break;
617 384 : default:
618 : /* a pointer has dimension = 0 */
619 384 : if (pointer_len)
620 : {
621 38 : *length = *dimension;
622 38 : *dimension = mm_strdup("0");
623 : }
624 :
625 384 : if (atoi(*length) >= 0)
626 0 : mmfatal(PARSE_ERROR, "multidimensional arrays for simple data types are not supported");
627 :
628 384 : break;
629 : }
630 726 : }
|