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