PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 "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(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:
47  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  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:
94  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  case ECPGt_struct:
96  case ECPGt_union:
97  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  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  break;
109  case '.':
110  if (members->type->type == ECPGt_array)
111  return find_struct_member(name, end, members->type->u.element->u.members, brace_level);
112  else
113  return find_struct_member(name, end, members->type->u.members, brace_level);
114  break;
115  default:
116  mmfatal(PARSE_ERROR, "incorrectly formed variable \"%s\"", name);
117  break;
118  }
119  }
120  }
121  }
122 
123  return NULL;
124 }
125 
126 static struct variable *
127 find_struct(char *name, char *next, char *end)
128 {
129  struct variable *p;
130  char c = *next;
131 
132  /* first get the mother structure entry */
133  *next = '\0';
134  p = find_variable(name);
135 
136  if (c == '-')
137  {
138  if (p->type->type != ECPGt_array)
139  mmfatal(PARSE_ERROR, "variable \"%s\" is not a pointer", name);
140 
141  if (p->type->u.element->type != ECPGt_struct && p->type->u.element->type != ECPGt_union)
142  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  *next = c;
146 
147  return find_struct_member(name, ++end, p->type->u.element->u.members, p->brace_level);
148  }
149  else
150  {
151  if (next == end)
152  {
153  if (p->type->type != ECPGt_struct && p->type->type != ECPGt_union)
154  mmfatal(PARSE_ERROR, "variable \"%s\" is neither a structure nor a union", name);
155 
156  /* restore the name, we will need it later */
157  *next = c;
158 
159  return find_struct_member(name, end, p->type->u.members, p->brace_level);
160  }
161  else
162  {
163  if (p->type->type != ECPGt_array)
164  mmfatal(PARSE_ERROR, "variable \"%s\" is not an array", name);
165 
166  if (p->type->u.element->type != ECPGt_struct && p->type->u.element->type != ECPGt_union)
167  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  *next = c;
171 
172  return find_struct_member(name, end, p->type->u.element->u.members, p->brace_level);
173  }
174  }
175 }
176 
177 static struct variable *
179 {
180  struct variable *p;
181 
182  for (p = allvariables; p; p = p->next)
183  {
184  if (strcmp(p->name, name) == 0)
185  return p;
186  }
187 
188  return NULL;
189 }
190 
191 /* Note that this function will end the program in case of an unknown */
192 /* variable */
193 struct variable *
195 {
196  char *next,
197  *end;
198  struct variable *p;
199  int count;
200 
201  next = strpbrk(name, ".[-");
202  if (next)
203  {
204  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  for (count = 1, end = next + 1; count; end++)
211  {
212  switch (*end)
213  {
214  case '[':
215  count++;
216  break;
217  case ']':
218  count--;
219  break;
220  default:
221  break;
222  }
223  }
224  if (*end == '.')
225  p = find_struct(name, next, end);
226  else
227  {
228  char c = *next;
229 
230  *next = '\0';
231  p = find_simple(name);
232  if (p == NULL)
233  mmfatal(PARSE_ERROR, "variable \"%s\" is not declared", name);
234 
235  *next = c;
236  switch (p->type->u.element->type)
237  {
238  case ECPGt_array:
239  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  case ECPGt_struct:
241  case ECPGt_union:
242  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  default:
244  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  p = find_struct(name, next, next);
250  }
251  else
252  p = find_simple(name);
253 
254  if (p == NULL)
255  mmfatal(PARSE_ERROR, "variable \"%s\" is not declared", name);
256 
257  return p;
258 }
259 
260 void
262 {
263  struct typedefs *p,
264  *prev;
265 
266  for (p = prev = types; p;)
267  {
268  if (p->brace_level >= brace_level)
269  {
270  /* remove it */
271  if (p == types)
272  prev = types = p->next;
273  else
274  prev->next = p->next;
275 
276  if (p->type->type_enum == ECPGt_struct || p->type->type_enum == ECPGt_union)
278  free(p->type);
279  free(p->name);
280  free(p);
281  if (prev == types)
282  p = types;
283  else
284  p = prev ? prev->next : NULL;
285  }
286  else
287  {
288  prev = p;
289  p = prev->next;
290  }
291  }
292 }
293 
294 void
296 {
297  struct variable *p,
298  *prev;
299 
300  for (p = prev = allvariables; p;)
301  {
302  if (p->brace_level >= brace_level)
303  {
304  /* is it still referenced by a cursor? */
305  struct cursor *ptr;
306 
307  for (ptr = cur; ptr != NULL; ptr = ptr->next)
308  {
309  struct arguments *varptr,
310  *prevvar;
311 
312  for (varptr = prevvar = ptr->argsinsert; varptr != NULL; varptr = varptr->next)
313  {
314  if (p == varptr->variable)
315  {
316  /* remove from list */
317  if (varptr == ptr->argsinsert)
318  ptr->argsinsert = varptr->next;
319  else
320  prevvar->next = varptr->next;
321  }
322  }
323  for (varptr = prevvar = ptr->argsresult; varptr != NULL; varptr = varptr->next)
324  {
325  if (p == varptr->variable)
326  {
327  /* remove from list */
328  if (varptr == ptr->argsresult)
329  ptr->argsresult = varptr->next;
330  else
331  prevvar->next = varptr->next;
332  }
333  }
334  }
335 
336  /* remove it */
337  if (p == allvariables)
338  prev = allvariables = p->next;
339  else
340  prev->next = p->next;
341 
342  ECPGfree_type(p->type);
343  free(p->name);
344  free(p);
345  if (prev == allvariables)
346  p = allvariables;
347  else
348  p = prev ? prev->next : NULL;
349  }
350  else
351  {
352  prev = p;
353  p = prev->next;
354  }
355  }
356 }
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
370 {
371  argsinsert = NULL;
372  argsresult = NULL;
373 }
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 add_variable_to_head(struct arguments **list, struct variable *var, struct variable *ind)
380 {
381  struct arguments *p = (struct arguments *) mm_alloc(sizeof(struct arguments));
382 
383  p->variable = var;
384  p->indicator = ind;
385  p->next = *list;
386  *list = p;
387 }
388 
389 /* Append a new variable to our request list. */
390 void
391 add_variable_to_tail(struct arguments **list, struct variable *var, struct variable *ind)
392 {
393  struct arguments *p,
394  *new = (struct arguments *) mm_alloc(sizeof(struct arguments));
395 
396  for (p = *list; p && p->next; p = p->next);
397 
398  new->variable = var;
399  new->indicator = ind;
400  new->next = NULL;
401 
402  if (p)
403  p->next = new;
404  else
405  *list = new;
406 }
407 
408 void
410 {
411  struct arguments *p,
412  *prev = NULL;
413  bool found = false;
414 
415  for (p = *list; p; p = p->next)
416  {
417  if (p->variable == var)
418  {
419  found = true;
420  break;
421  }
422  prev = p;
423  }
424  if (found)
425  {
426  if (prev)
427  prev->next = p->next;
428  else
429  *list = p->next;
430  }
431 }
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 dump_variables(struct arguments *list, int mode)
439 {
440  char *str_zero;
441 
442  if (list == NULL)
443  return;
444 
445  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  dump_variables(list->next, mode);
453 
454  /* Then the current element and its indicator */
456  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  if (mode != 0)
461  free(list);
462 
463  free(str_zero);
464 }
465 
466 void
468 {
469  /* make sure this is a valid indicator variable */
470  switch (var->type)
471  {
472  struct ECPGstruct_member *p;
473 
474  case ECPGt_short:
475  case ECPGt_int:
476  case ECPGt_long:
477  case ECPGt_long_long:
479  case ECPGt_unsigned_int:
480  case ECPGt_unsigned_long:
482  break;
483 
484  case ECPGt_struct:
485  case ECPGt_union:
486  for (p = var->u.members; p; p = p->next)
487  check_indicator(p->type);
488  break;
489 
490  case ECPGt_array:
491  check_indicator(var->u.element);
492  break;
493  default:
494  mmerror(PARSE_ERROR, ET_ERROR, "indicator variable must have an integer type");
495  break;
496  }
497 }
498 
499 struct typedefs *
501 {
502  struct typedefs *this;
503 
504  for (this = types; this && strcmp(this->name, name) != 0; this = this->next);
505  if (!this)
506  mmfatal(PARSE_ERROR, "unrecognized data type name \"%s\"", name);
507 
508  return this;
509 }
510 
511 void
512 adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *type_dimension, char *type_index, int pointer_len, bool type_definition)
513 {
514  if (atoi(type_index) >= 0)
515  {
516  if (atoi(*length) >= 0)
517  mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
518 
519  *length = type_index;
520  }
521 
522  if (atoi(type_dimension) >= 0)
523  {
524  if (atoi(*dimension) >= 0 && atoi(*length) >= 0)
525  mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
526 
527  if (atoi(*dimension) >= 0)
528  *length = *dimension;
529 
530  *dimension = type_dimension;
531  }
532 
533  if (pointer_len > 2)
534  mmfatal(PARSE_ERROR, ngettext("multilevel pointers (more than 2 levels) are not supported; found %d level",
535  "multilevel pointers (more than 2 levels) are not supported; found %d levels", pointer_len),
536  pointer_len);
537 
538  if (pointer_len > 1 && type_enum != ECPGt_char && type_enum != ECPGt_unsigned_char && type_enum != ECPGt_string)
539  mmfatal(PARSE_ERROR, "pointer to pointer is not supported for this data type");
540 
541  if (pointer_len > 1 && (atoi(*length) >= 0 || atoi(*dimension) >= 0))
542  mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
543 
544  if (atoi(*length) >= 0 && atoi(*dimension) >= 0 && pointer_len)
545  mmfatal(PARSE_ERROR, "multidimensional arrays are not supported");
546 
547  switch (type_enum)
548  {
549  case ECPGt_struct:
550  case ECPGt_union:
551  /* pointer has to get dimension 0 */
552  if (pointer_len)
553  {
554  *length = *dimension;
555  *dimension = mm_strdup("0");
556  }
557 
558  if (atoi(*length) >= 0)
559  mmfatal(PARSE_ERROR, "multidimensional arrays for structures are not supported");
560 
561  break;
562  case ECPGt_varchar:
563  /* pointer has to get dimension 0 */
564  if (pointer_len)
565  *dimension = mm_strdup("0");
566 
567  /* one index is the string length */
568  if (atoi(*length) < 0)
569  {
570  *length = *dimension;
571  *dimension = mm_strdup("-1");
572  }
573 
574  break;
575  case ECPGt_char:
576  case ECPGt_unsigned_char:
577  case ECPGt_string:
578  /* char ** */
579  if (pointer_len == 2)
580  {
581  *length = *dimension = mm_strdup("0");
582  break;
583  }
584 
585  /* pointer has to get length 0 */
586  if (pointer_len == 1)
587  *length = mm_strdup("0");
588 
589  /* one index is the string length */
590  if (atoi(*length) < 0)
591  {
592  /*
593  * make sure we return length = -1 for arrays without given
594  * bounds
595  */
596  if (atoi(*dimension) < 0 && !type_definition)
597 
598  /*
599  * do not change this for typedefs since it will be
600  * changed later on when the variable is defined
601  */
602  *length = mm_strdup("1");
603  else if (strcmp(*dimension, "0") == 0)
604  *length = mm_strdup("-1");
605  else
606  *length = *dimension;
607 
608  *dimension = mm_strdup("-1");
609  }
610  break;
611  default:
612  /* a pointer has dimension = 0 */
613  if (pointer_len)
614  {
615  *length = *dimension;
616  *dimension = mm_strdup("0");
617  }
618 
619  if (atoi(*length) >= 0)
620  mmfatal(PARSE_ERROR, "multidimensional arrays for simple data types are not supported");
621 
622  break;
623  }
624 }
int length(const List *list)
Definition: list.c:1271
void dump_variables(struct arguments *list, int mode)
Definition: variable.c:438
struct typedefs * get_typedef(char *name)
Definition: variable.c:500
struct variable * find_variable(char *name)
Definition: variable.c:194
int brace_level
Definition: type.h:161
static int32 next
Definition: blutils.c:210
struct typedefs * types
Definition: ecpg.c:29
struct ECPGstruct_member * members
Definition: type.h:30
static struct variable * find_struct(char *name, char *next, char *end)
Definition: variable.c:127
struct arguments * argsinsert
Definition: variable.c:365
char * name
Definition: type.h:12
Definition: type.h:188
struct cursor * next
Definition: type.h:135
struct ECPGtype * ECPGmake_array_type(struct ECPGtype *type, char *size)
Definition: type.c:111
enum ECPGttype type
Definition: extern.h:113
struct cursor * cur
Definition: ecpg.c:28
struct variable * indicator
Definition: type.h:168
struct arguments * argsresult
Definition: variable.c:366
struct variable * next
Definition: extern.h:125
Definition: type.h:138
struct typedefs * next
Definition: type.h:144
void mmerror(int errorcode, enum errortype type, const char *error,...) pg_attribute_printf(3
Definition: type.h:17
void remove_typedefs(int brace_level)
Definition: variable.c:261
struct ECPGtype * ECPGmake_simple_type(enum ECPGttype type, char *size, int counter)
Definition: type.c:96
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:239
struct arguments * next
Definition: type.h:169
static struct variable * find_simple(char *name)
Definition: variable.c:178
void * mm_alloc(size_t)
struct arguments * argsinsert
Definition: type.h:131
struct ECPGtype * element
Definition: type.h:28
struct this_type * type
Definition: type.h:141
char * size
Definition: type.h:22
union ECPGtype::@125 u
char * c
char * name
Definition: type.h:140
static struct variable * allvariables
Definition: variable.c:7
int counter
Definition: type.h:32
int brace_level
Definition: type.h:143
Definition: type.h:124
void add_variable_to_head(struct arguments **list, struct variable *var, struct variable *ind)
Definition: variable.c:379
static struct variable * find_struct_member(char *name, char *str, struct ECPGstruct_member *members, int brace_level)
Definition: variable.c:25
FILE * base_yyout
void void mmfatal(int errorcode, const char *error,...) pg_attribute_printf(2
struct ECPGtype * type
Definition: type.h:13
struct variable * new_variable(const char *name, struct ECPGtype *type, int brace_level)
Definition: variable.c:10
#define ngettext(s, p, n)
Definition: c.h:127
void adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *type_dimension, char *type_index, int pointer_len, bool type_definition)
Definition: variable.c:512
struct arguments * argsresult
Definition: type.h:133
#define free(a)
Definition: header.h:65
void ECPGfree_type(struct ECPGtype *type)
Definition: type.c:634
void reset_variables(void)
Definition: variable.c:369
void add_variable_to_tail(struct arguments **list, struct variable *var, struct variable *ind)
Definition: variable.c:391
void remove_variables(int brace_level)
Definition: variable.c:295
struct ECPGtype * ECPGmake_struct_type(struct ECPGstruct_member *rm, enum ECPGttype type, char *type_name, char *struct_sizeof)
Definition: type.c:121
char * type_name
Definition: type.h:20
enum ECPGttype type
Definition: type.h:19
enum ECPGttype type_enum
Definition: type.h:111
const char * name
Definition: encode.c:521
tuple list
Definition: sort-test.py:11
char * struct_sizeof
Definition: type.h:24
#define PARSE_ERROR
Definition: extern.h:117
struct variable * variable
Definition: type.h:167
void check_indicator(struct ECPGtype *var)
Definition: variable.c:467
char * mm_strdup(const char *)
Definition: type.c:25
struct ECPGstruct_member * struct_member_list
Definition: type.h:142
char * name
Definition: type.h:159
void remove_variable_from_list(struct arguments **list, struct variable *var)
Definition: variable.c:409
struct ECPGstruct_member * next
Definition: type.h:14
ECPGttype
Definition: ecpgtype.h:41