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 
7 static struct variable *allvariables = NULL;
8 
9 struct variable *
10 new_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 
24 static struct variable *
25 find_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 
125 static struct variable *
126 find_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 
176 static struct variable *
177 find_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 */
192 struct variable *
193 find_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 
263 void
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 
281  if (p->type->type_enum == ECPGt_struct || p->type->type_enum == ECPGt_union)
283  free(p->type->type_storage);
284  free(p->type->type_str);
285  free(p->type->type_dimension);
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 
297 void
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
356  allvariables = next;
357 
358  ECPGfree_type(p->type);
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 
374 struct arguments *argsinsert = NULL;
375 struct arguments *argsresult = NULL;
376 
377 void
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 */
400 void
401 add_variable_to_head(struct arguments **list, struct variable *var, struct variable *ind)
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. */
412 void
413 add_variable_to_tail(struct arguments **list, struct variable *var, struct variable *ind)
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 
430 void
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  */
460 void
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 
489 void
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:
502  case ECPGt_unsigned_int:
503  case ECPGt_unsigned_long:
505  break;
506 
507  case ECPGt_struct:
508  case ECPGt_union:
509  for (p = var->u.members; p; p = p->next)
510  check_indicator(p->type);
511  break;
512 
513  case ECPGt_array:
514  check_indicator(var->u.element);
515  break;
516  default:
517  mmerror(PARSE_ERROR, ET_ERROR, "indicator variable must have an integer type");
518  break;
519  }
520 }
521 
522 struct typedefs *
523 get_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 
539 void
540 adjust_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:
608  case ECPGt_unsigned_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:219
#define ngettext(s, p, n)
Definition: c.h:1135
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_simple(const char *name)
Definition: variable.c:177
static struct variable * allvariables
Definition: variable.c:7
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
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
void reset_variables(void)
Definition: variable.c:378
void remove_variables(int brace_level)
Definition: variable.c:298
static struct variable * find_struct(const char *name, char *next, char *end)
Definition: variable.c:126
struct arguments * argsresult
Definition: variable.c:375
void remove_variable_from_list(struct arguments **list, struct variable *var)
Definition: variable.c:431
struct variable * find_variable(const char *name)
Definition: variable.c:193
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
struct typedefs * get_typedef(const char *name, bool noerror)
Definition: variable.c:523
static struct variable * find_struct_member(const char *name, char *str, struct ECPGstruct_member *members, int brace_level)
Definition: variable.c:25
void remove_typedefs(int brace_level)
Definition: variable.c:264
void check_indicator(struct ECPGtype *var)
Definition: variable.c:490
struct variable * new_variable(const char *name, struct ECPGtype *type, int brace_level)
Definition: variable.c:10
static PgChecksumMode mode
Definition: pg_checksums.c:55
char * c
void mmerror(int error_code, enum errortype type, const char *error,...) pg_attribute_printf(3
char * mm_strdup(const char *string)
Definition: util.c:97
void void mmfatal(int error_code, const char *error,...) pg_attribute_printf(2
#define PARSE_ERROR
FILE * base_yyout
void * mm_alloc(size_t size)
Definition: util.c:85
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
union ECPGtype::@164 u
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
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
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
struct ECPGtype * ECPGmake_array_type(struct ECPGtype *type, const char *size)
Definition: type.c:87
void ECPGfree_type(struct ECPGtype *type)
Definition: type.c:632
struct ECPGtype * ECPGmake_simple_type(enum ECPGttype type, const char *size, int counter)
Definition: type.c:72
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