1 /* src/interfaces/ecpg/preproc/ecpg.header */
3 /* Copyright comment */
5 #include "postgres_fe.h"
8 #include "ecpg_config.h"
11 /* Location tracking support --- simpler than bison's default */
12 #define YYLLOC_DEFAULT(Current, Rhs, N) \
15 (Current) = (Rhs)[1]; \
17 (Current) = (Rhs)[0]; \
21 * The %name-prefix option below will make bison call base_yylex, but we
22 * really want it to call filtered_base_yylex (see parser.c).
24 #define base_yylex filtered_base_yylex
27 * This is only here so the string gets into the POT. Bison uses it
30 #define bison_gettext_dummy gettext_noop("syntax error")
33 * Variables containing simple states.
36 int braces_open; /* brace level counter */
37 char *current_function;
38 int ecpg_internal_var = 0;
39 char *connection = NULL;
40 char *input_filename = NULL;
42 static int FoundInto = 0;
43 static int initializer = 0;
44 static int pacounter = 1;
45 static char pacounter_buffer[sizeof(int) * CHAR_BIT * 10 / 3]; /* a rough guess at the size we need */
46 static struct this_type actual_type[STRUCT_DEPTH];
47 static char *actual_startline[STRUCT_DEPTH];
48 static int varchar_counter = 1;
50 /* temporarily store struct members while creating the data structure */
51 struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH] = { NULL };
53 /* also store struct type so we can do a sizeof() later */
54 static char *ECPGstruct_sizeof = NULL;
56 /* for forward declarations we have to store some data as well */
57 static char *forward_name = NULL;
59 struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, NULL, NULL, NULL, {NULL}, 0};
60 struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL};
62 static struct ECPGtype ecpg_query = {ECPGt_char_variable, NULL, NULL, NULL, {NULL}, 0};
64 static void vmmerror(int error_code, enum errortype type, const char *error, va_list ap) pg_attribute_printf(3, 0);
67 * Handle parsing errors and warnings
70 vmmerror(int error_code, enum errortype type, const char *error, va_list ap)
72 /* localize the error message string */
75 fprintf(stderr, "%s:%d: ", input_filename, base_yylineno);
80 fprintf(stderr, _("WARNING: "));
83 fprintf(stderr, _("ERROR: "));
87 vfprintf(stderr, error, ap);
89 fprintf(stderr, "\n");
96 ret_value = error_code;
102 mmerror(int error_code, enum errortype type, const char *error, ...)
107 vmmerror(error_code, type, error, ap);
112 mmfatal(int error_code, const char *error, ...)
117 vmmerror(error_code, ET_ERROR, error, ap);
125 if (strcmp(output_filename, "-") != 0 && unlink(output_filename) != 0)
126 fprintf(stderr, _("could not remove output file \"%s\"\n"), output_filename);
131 * string concatenation
135 cat2_str(char *str1, char *str2)
137 char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) + 2);
139 strcpy(res_str, str1);
140 if (strlen(str1) != 0 && strlen(str2) != 0)
141 strcat(res_str, " ");
142 strcat(res_str, str2);
149 cat_str(int count, ...)
155 va_start(args, count);
157 res_str = va_arg(args, char *);
159 /* now add all other strings */
160 for (i = 1; i < count; i++)
161 res_str = cat2_str(res_str, va_arg(args, char *));
169 make2_str(char *str1, char *str2)
171 char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) + 1);
173 strcpy(res_str, str1);
174 strcat(res_str, str2);
181 make3_str(char *str1, char *str2, char *str3)
183 char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) +strlen(str3) + 1);
185 strcpy(res_str, str1);
186 strcat(res_str, str2);
187 strcat(res_str, str3);
198 return mm_strdup(base_yytext);
202 create_questionmarks(char *name, bool array)
204 struct variable *p = find_variable(name);
206 char *result = EMPTY;
208 /* In case we have a struct, we have to print as many "?" as there are attributes in the struct
209 * An array is only allowed together with an element argument
210 * This is essantially only used for inserts, but using a struct as input parameter is an error anywhere else
211 * so we don't have to worry here. */
213 if (p->type->type == ECPGt_struct || (array && p->type->type == ECPGt_array && p->type->u.element->type == ECPGt_struct))
215 struct ECPGstruct_member *m;
217 if (p->type->type == ECPGt_struct)
218 m = p->type->u.members;
220 m = p->type->u.element->u.members;
222 for (count = 0; m != NULL; m=m->next, count++);
227 for (; count > 0; count --)
229 sprintf(pacounter_buffer, "$%d", pacounter++);
230 result = cat_str(3, result, mm_strdup(pacounter_buffer), mm_strdup(" , "));
233 /* removed the trailing " ," */
235 result[strlen(result)-3] = '\0';
240 adjust_outofscope_cursor_vars(struct cursor *cur)
242 /* Informix accepts DECLARE with variables that are out of scope when OPEN is called.
243 * For instance you can DECLARE a cursor in one function, and OPEN/FETCH/CLOSE
244 * it in another functions. This is very useful for e.g. event-driver programming,
245 * but may also lead to dangerous programming. The limitation when this is allowed
246 * and doesn't cause problems have to be documented, like the allocated variables
247 * must not be realloc()'ed.
249 * We have to change the variables to our own struct and just store the pointer
250 * instead of the variable. Do it only for local variables, not for globals.
253 char *result = EMPTY;
256 for (insert = 1; insert >= 0; insert--)
258 struct arguments *list;
259 struct arguments *ptr;
260 struct arguments *newlist = NULL;
261 struct variable *newvar, *newind;
263 list = (insert ? cur->argsinsert : cur->argsresult);
265 for (ptr = list; ptr != NULL; ptr = ptr->next)
269 bool skip_set_var = false;
270 bool var_ptr = false;
272 /* change variable name to "ECPGget_var(<counter>)" */
273 original_var = ptr->variable->name;
274 sprintf(var_text, "%d))", ecpg_internal_var);
276 /* Don't emit ECPGset_var() calls for global variables */
277 if (ptr->variable->brace_level == 0)
279 newvar = ptr->variable;
282 else if ((ptr->variable->type->type == ECPGt_char_variable)
283 && (strncmp(ptr->variable->name, "ECPGprepared_statement", strlen("ECPGprepared_statement")) == 0))
285 newvar = ptr->variable;
288 else if ((ptr->variable->type->type != ECPGt_varchar
289 && ptr->variable->type->type != ECPGt_char
290 && ptr->variable->type->type != ECPGt_unsigned_char
291 && ptr->variable->type->type != ECPGt_string)
292 && atoi(ptr->variable->type->size) > 1)
294 newvar = new_variable(cat_str(4, mm_strdup("("),
295 mm_strdup(ecpg_type_name(ptr->variable->type->u.element->type)),
296 mm_strdup(" *)(ECPGget_var("),
297 mm_strdup(var_text)),
298 ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type,
300 ptr->variable->type->u.element->counter),
301 ptr->variable->type->size),
304 else if ((ptr->variable->type->type == ECPGt_varchar
305 || ptr->variable->type->type == ECPGt_char
306 || ptr->variable->type->type == ECPGt_unsigned_char
307 || ptr->variable->type->type == ECPGt_string)
308 && atoi(ptr->variable->type->size) > 1)
310 newvar = new_variable(cat_str(4, mm_strdup("("),
311 mm_strdup(ecpg_type_name(ptr->variable->type->type)),
312 mm_strdup(" *)(ECPGget_var("),
313 mm_strdup(var_text)),
314 ECPGmake_simple_type(ptr->variable->type->type,
315 ptr->variable->type->size,
316 ptr->variable->type->counter),
318 if (ptr->variable->type->type == ECPGt_varchar)
321 else if (ptr->variable->type->type == ECPGt_struct
322 || ptr->variable->type->type == ECPGt_union)
324 newvar = new_variable(cat_str(5, mm_strdup("(*("),
325 mm_strdup(ptr->variable->type->type_name),
326 mm_strdup(" *)(ECPGget_var("),
329 ECPGmake_struct_type(ptr->variable->type->u.members,
330 ptr->variable->type->type,
331 ptr->variable->type->type_name,
332 ptr->variable->type->struct_sizeof),
336 else if (ptr->variable->type->type == ECPGt_array)
338 if (ptr->variable->type->u.element->type == ECPGt_struct
339 || ptr->variable->type->u.element->type == ECPGt_union)
341 newvar = new_variable(cat_str(5, mm_strdup("(*("),
342 mm_strdup(ptr->variable->type->u.element->type_name),
343 mm_strdup(" *)(ECPGget_var("),
346 ECPGmake_struct_type(ptr->variable->type->u.element->u.members,
347 ptr->variable->type->u.element->type,
348 ptr->variable->type->u.element->type_name,
349 ptr->variable->type->u.element->struct_sizeof),
354 newvar = new_variable(cat_str(4, mm_strdup("("),
355 mm_strdup(ecpg_type_name(ptr->variable->type->type)),
356 mm_strdup(" *)(ECPGget_var("),
357 mm_strdup(var_text)),
358 ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type,
359 ptr->variable->type->u.element->size,
360 ptr->variable->type->u.element->counter),
361 ptr->variable->type->size),
368 newvar = new_variable(cat_str(4, mm_strdup("*("),
369 mm_strdup(ecpg_type_name(ptr->variable->type->type)),
370 mm_strdup(" *)(ECPGget_var("),
371 mm_strdup(var_text)),
372 ECPGmake_simple_type(ptr->variable->type->type,
373 ptr->variable->type->size,
374 ptr->variable->type->counter),
379 /* create call to "ECPGset_var(<counter>, <connection>, <pointer>. <line number>)" */
382 sprintf(var_text, "%d, %s", ecpg_internal_var++, var_ptr ? "&(" : "(");
383 result = cat_str(5, result, mm_strdup("ECPGset_var("),
384 mm_strdup(var_text), mm_strdup(original_var),
385 mm_strdup("), __LINE__);\n"));
388 /* now the indicator if there is one and it's not a global variable */
389 if ((ptr->indicator->type->type == ECPGt_NO_INDICATOR) || (ptr->indicator->brace_level == 0))
391 newind = ptr->indicator;
395 /* change variable name to "ECPGget_var(<counter>)" */
396 original_var = ptr->indicator->name;
397 sprintf(var_text, "%d))", ecpg_internal_var);
400 if (ptr->indicator->type->type == ECPGt_struct
401 || ptr->indicator->type->type == ECPGt_union)
403 newind = new_variable(cat_str(5, mm_strdup("(*("),
404 mm_strdup(ptr->indicator->type->type_name),
405 mm_strdup(" *)(ECPGget_var("),
408 ECPGmake_struct_type(ptr->indicator->type->u.members,
409 ptr->indicator->type->type,
410 ptr->indicator->type->type_name,
411 ptr->indicator->type->struct_sizeof),
415 else if (ptr->indicator->type->type == ECPGt_array)
417 if (ptr->indicator->type->u.element->type == ECPGt_struct
418 || ptr->indicator->type->u.element->type == ECPGt_union)
420 newind = new_variable(cat_str(5, mm_strdup("(*("),
421 mm_strdup(ptr->indicator->type->u.element->type_name),
422 mm_strdup(" *)(ECPGget_var("),
425 ECPGmake_struct_type(ptr->indicator->type->u.element->u.members,
426 ptr->indicator->type->u.element->type,
427 ptr->indicator->type->u.element->type_name,
428 ptr->indicator->type->u.element->struct_sizeof),
433 newind = new_variable(cat_str(4, mm_strdup("("),
434 mm_strdup(ecpg_type_name(ptr->indicator->type->u.element->type)),
435 mm_strdup(" *)(ECPGget_var("), mm_strdup(var_text)),
436 ECPGmake_array_type(ECPGmake_simple_type(ptr->indicator->type->u.element->type,
437 ptr->indicator->type->u.element->size,
438 ptr->indicator->type->u.element->counter),
439 ptr->indicator->type->size),
444 else if (atoi(ptr->indicator->type->size) > 1)
446 newind = new_variable(cat_str(4, mm_strdup("("),
447 mm_strdup(ecpg_type_name(ptr->indicator->type->type)),
448 mm_strdup(" *)(ECPGget_var("),
449 mm_strdup(var_text)),
450 ECPGmake_simple_type(ptr->indicator->type->type,
451 ptr->indicator->type->size,
452 ptr->variable->type->counter),
457 newind = new_variable(cat_str(4, mm_strdup("*("),
458 mm_strdup(ecpg_type_name(ptr->indicator->type->type)),
459 mm_strdup(" *)(ECPGget_var("),
460 mm_strdup(var_text)),
461 ECPGmake_simple_type(ptr->indicator->type->type,
462 ptr->indicator->type->size,
463 ptr->variable->type->counter),
468 /* create call to "ECPGset_var(<counter>, <pointer>. <line number>)" */
469 sprintf(var_text, "%d, %s", ecpg_internal_var++, var_ptr ? "&(" : "(");
470 result = cat_str(5, result, mm_strdup("ECPGset_var("),
471 mm_strdup(var_text), mm_strdup(original_var),
472 mm_strdup("), __LINE__);\n"));
475 add_variable_to_tail(&newlist, newvar, newind);
479 cur->argsinsert_oos = newlist;
481 cur->argsresult_oos = newlist;
487 /* This tests whether the cursor was declared and opened in the same function. */
488 #define SAMEFUNC(cur) \
489 ((cur->function == NULL) || \
490 (cur->function != NULL && strcmp(cur->function, current_function) == 0))
492 static struct cursor *
493 add_additional_variables(char *name, bool insert)
497 int (* strcmp_fn)(const char *, const char *) = ((name[0] == ':' || name[0] == '"') ? strcmp : pg_strcasecmp);
499 for (ptr = cur; ptr != NULL; ptr=ptr->next)
501 if (strcmp_fn(ptr->name, name) == 0)
507 mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" does not exist", name);
513 /* add all those input variables that were given earlier
514 * note that we have to append here but have to keep the existing order */
515 for (p = (SAMEFUNC(ptr) ? ptr->argsinsert : ptr->argsinsert_oos); p; p = p->next)
516 add_variable_to_tail(&argsinsert, p->variable, p->indicator);
519 /* add all those output variables that were given earlier */
520 for (p = (SAMEFUNC(ptr) ? ptr->argsresult : ptr->argsresult_oos); p; p = p->next)
521 add_variable_to_tail(&argsresult, p->variable, p->indicator);
527 add_typedef(char *name, char *dimension, char *length, enum ECPGttype type_enum,
528 char *type_dimension, char *type_index, int initializer, int array)
530 /* add entry to list */
531 struct typedefs *ptr, *this;
533 if ((type_enum == ECPGt_struct ||
534 type_enum == ECPGt_union) &&
536 mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in type definition");
537 else if (INFORMIX_MODE && strcmp(name, "string") == 0)
538 mmerror(PARSE_ERROR, ET_ERROR, "type name \"string\" is reserved in Informix mode");
541 for (ptr = types; ptr != NULL; ptr = ptr->next)
543 if (strcmp(name, ptr->name) == 0)
544 /* re-definition is a bug */
545 mmerror(PARSE_ERROR, ET_ERROR, "type \"%s\" is already defined", name);
547 adjust_array(type_enum, &dimension, &length, type_dimension, type_index, array, true);
549 this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
551 /* initial definition */
554 this->brace_level = braces_open;
555 this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
556 this->type->type_enum = type_enum;
557 this->type->type_str = mm_strdup(name);
558 this->type->type_dimension = dimension; /* dimension of array */
559 this->type->type_index = length; /* length of string */
560 this->type->type_sizeof = ECPGstruct_sizeof;
561 this->struct_member_list = (type_enum == ECPGt_struct || type_enum == ECPGt_union) ?
562 ECPGstruct_member_dup(struct_member_list[struct_level]) : NULL;
564 if (type_enum != ECPGt_varchar &&
565 type_enum != ECPGt_char &&
566 type_enum != ECPGt_unsigned_char &&
567 type_enum != ECPGt_string &&
568 atoi(this->type->type_index) >= 0)
569 mmerror(PARSE_ERROR, ET_ERROR, "multidimensional arrays for simple data types are not supported");
577 %name-prefix="base_yy"
587 struct this_type type;
588 enum ECPGttype type_enum;
589 enum ECPGdtype dtype_enum;
590 struct fetch_desc descriptor;
591 struct su_symbol struct_union;