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
struct ECPGtype ecpg_query = {ECPGt_char_variable, NULL, NULL, NULL, {NULL}, 0};
65
* Handle parsing errors and warnings
68
mmerror(int error_code, enum errortype type, const char *error, ...)
72
/* internationalize the error message string */
75
fprintf(stderr, "%s:%d: ", input_filename, yylineno);
80
fprintf(stderr, _("WARNING: "));
84
fprintf(stderr, _("ERROR: "));
89
vfprintf(stderr, error, ap);
92
fprintf(stderr, "\n");
99
ret_value = error_code;
107
if (strcmp(output_filename, "-") != 0 && unlink(output_filename) != 0)
108
fprintf(stderr, _("could not remove output file \"%s\"\n"), output_filename);
114
* string concatenation
118
cat2_str(char *str1, char *str2)
120
char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) + 2);
122
strcpy(res_str, str1);
123
if (strlen(str1) != 0 && strlen(str2) != 0)
124
strcat(res_str, " ");
125
strcat(res_str, str2);
132
cat_str(int count, ...)
138
va_start(args, count);
140
res_str = va_arg(args, char *);
142
/* now add all other strings */
143
for (i = 1; i < count; i++)
144
res_str = cat2_str(res_str, va_arg(args, char *));
152
make2_str(char *str1, char *str2)
154
char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) + 1);
156
strcpy(res_str, str1);
157
strcat(res_str, str2);
164
make3_str(char *str1, char *str2, char *str3)
166
char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) +strlen(str3) + 1);
168
strcpy(res_str, str1);
169
strcat(res_str, str2);
170
strcat(res_str, str3);
181
return mm_strdup(yytext);
185
create_questionmarks(char *name, bool array)
187
struct variable *p = find_variable(name);
189
char *result = EMPTY;
191
/* In case we have a struct, we have to print as many "?" as there are attributes in the struct
192
* An array is only allowed together with an element argument
193
* This is essantially only used for inserts, but using a struct as input parameter is an error anywhere else
194
* so we don't have to worry here. */
196
if (p->type->type == ECPGt_struct || (array && p->type->type == ECPGt_array && p->type->u.element->type == ECPGt_struct))
198
struct ECPGstruct_member *m;
200
if (p->type->type == ECPGt_struct)
201
m = p->type->u.members;
203
m = p->type->u.element->u.members;
205
for (count = 0; m != NULL; m=m->next, count++);
210
for (; count > 0; count --)
212
sprintf(pacounter_buffer, "$%d", pacounter++);
213
result = cat_str(3, result, mm_strdup(pacounter_buffer), mm_strdup(" , "));
216
/* removed the trailing " ," */
218
result[strlen(result)-3] = '\0';
223
adjust_outofscope_cursor_vars(struct cursor *cur)
225
/* Informix accepts DECLARE with variables that are out of scope when OPEN is called.
226
* For instance you can DECLARE a cursor in one function, and OPEN/FETCH/CLOSE
227
* it in other functions. This is very useful for e.g. event-driver programming,
228
* but may also lead to dangerous programming. The limitation when this is allowed
229
* and doesn's cause problems have to be documented, like the allocated variables
230
* must not be realloc()'ed.
232
* We have to change the variables to our own struct and just store the pointer
233
* instead of the variable. Do it only for local variables, not for globals.
236
char *result = mm_strdup("");
239
for (insert = 1; insert >= 0; insert--)
241
struct arguments *list;
242
struct arguments *ptr;
243
struct arguments *newlist = NULL;
244
struct variable *newvar, *newind;
246
list = (insert ? cur->argsinsert : cur->argsresult);
248
for (ptr = list; ptr != NULL; ptr = ptr->next)
252
bool skip_set_var = false;
254
/* change variable name to "ECPGget_var(<counter>)" */
255
original_var = ptr->variable->name;
256
sprintf(temp, "%d))", ecpg_internal_var);
258
/* Don't emit ECPGset_var() calls for global variables */
259
if (ptr->variable->brace_level == 0)
261
newvar = ptr->variable;
264
else if ((ptr->variable->type->type == ECPGt_char_variable) && (!strncmp(ptr->variable->name, "ECPGprepared_statement", strlen("ECPGprepared_statement"))))
266
newvar = ptr->variable;
269
else if ((ptr->variable->type->type != ECPGt_varchar && ptr->variable->type->type != ECPGt_char && ptr->variable->type->type != ECPGt_unsigned_char && ptr->variable->type->type != ECPGt_string) && atoi(ptr->variable->type->size) > 1)
271
newvar = new_variable(cat_str(4, mm_strdup("("), mm_strdup(ecpg_type_name(ptr->variable->type->u.element->type)), mm_strdup(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type, mm_strdup("1"), ptr->variable->type->u.element->counter), ptr->variable->type->size), 0);
272
sprintf(temp, "%d, (", ecpg_internal_var++);
274
else if ((ptr->variable->type->type == ECPGt_varchar || ptr->variable->type->type == ECPGt_char || ptr->variable->type->type == ECPGt_unsigned_char || ptr->variable->type->type == ECPGt_string) && atoi(ptr->variable->type->size) > 1)
276
newvar = new_variable(cat_str(4, mm_strdup("("), mm_strdup(ecpg_type_name(ptr->variable->type->type)), mm_strdup(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->counter), 0);
277
if (ptr->variable->type->type == ECPGt_varchar)
278
sprintf(temp, "%d, &(", ecpg_internal_var++);
280
sprintf(temp, "%d, (", ecpg_internal_var++);
282
else if (ptr->variable->type->type == ECPGt_struct || ptr->variable->type->type == ECPGt_union)
284
sprintf(temp, "%d)))", ecpg_internal_var);
285
newvar = new_variable(cat_str(4, mm_strdup("(*("), mm_strdup(ptr->variable->type->type_name), mm_strdup(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_struct_type(ptr->variable->type->u.members, ptr->variable->type->type, ptr->variable->type->type_name, ptr->variable->type->struct_sizeof), 0);
286
sprintf(temp, "%d, &(", ecpg_internal_var++);
288
else if (ptr->variable->type->type == ECPGt_array)
290
if (ptr->variable->type->u.element->type == ECPGt_struct || ptr->variable->type->u.element->type == ECPGt_union)
292
sprintf(temp, "%d)))", ecpg_internal_var);
293
newvar = new_variable(cat_str(4, mm_strdup("(*("), mm_strdup(ptr->variable->type->u.element->type_name), mm_strdup(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_struct_type(ptr->variable->type->u.element->u.members, ptr->variable->type->u.element->type, ptr->variable->type->u.element->type_name, ptr->variable->type->u.element->struct_sizeof), 0);
294
sprintf(temp, "%d, (", ecpg_internal_var++);
298
newvar = new_variable(cat_str(4, mm_strdup("("), mm_strdup(ecpg_type_name(ptr->variable->type->type)), mm_strdup(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type, ptr->variable->type->u.element->size, ptr->variable->type->u.element->counter), ptr->variable->type->size), 0);
299
sprintf(temp, "%d, &(", ecpg_internal_var++);
304
newvar = new_variable(cat_str(4, mm_strdup("*("), mm_strdup(ecpg_type_name(ptr->variable->type->type)), mm_strdup(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->counter), 0);
305
sprintf(temp, "%d, &(", ecpg_internal_var++);
308
/* create call to "ECPGset_var(<counter>, <pointer>. <line number>)" */
310
result = cat_str(5, result, mm_strdup("ECPGset_var("), mm_strdup(temp), mm_strdup(original_var), mm_strdup("), __LINE__);\n"));
312
/* now the indicator if there is one and it's not a global variable */
313
if ((ptr->indicator->type->type == ECPGt_NO_INDICATOR) || (ptr->indicator->brace_level == 0))
315
newind = ptr->indicator;
319
/* change variable name to "ECPGget_var(<counter>)" */
320
original_var = ptr->indicator->name;
321
sprintf(temp, "%d))", ecpg_internal_var);
323
if (ptr->indicator->type->type == ECPGt_struct || ptr->indicator->type->type == ECPGt_union)
325
sprintf(temp, "%d)))", ecpg_internal_var);
326
newind = new_variable(cat_str(4, mm_strdup("(*("), mm_strdup(ptr->indicator->type->type_name), mm_strdup(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_struct_type(ptr->indicator->type->u.members, ptr->indicator->type->type, ptr->indicator->type->type_name, ptr->indicator->type->struct_sizeof), 0);
327
sprintf(temp, "%d, &(", ecpg_internal_var++);
329
else if (ptr->indicator->type->type == ECPGt_array)
331
if (ptr->indicator->type->u.element->type == ECPGt_struct || ptr->indicator->type->u.element->type == ECPGt_union)
333
sprintf(temp, "%d)))", ecpg_internal_var);
334
newind = new_variable(cat_str(4, mm_strdup("(*("), mm_strdup(ptr->indicator->type->u.element->type_name), mm_strdup(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_struct_type(ptr->indicator->type->u.element->u.members, ptr->indicator->type->u.element->type, ptr->indicator->type->u.element->type_name, ptr->indicator->type->u.element->struct_sizeof), 0);
335
sprintf(temp, "%d, (", ecpg_internal_var++);
339
newind = new_variable(cat_str(4, mm_strdup("("), mm_strdup(ecpg_type_name(ptr->indicator->type->u.element->type)), mm_strdup(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_array_type(ECPGmake_simple_type(ptr->indicator->type->u.element->type, ptr->indicator->type->u.element->size, ptr->indicator->type->u.element->counter), ptr->indicator->type->size), 0);
340
sprintf(temp, "%d, &(", ecpg_internal_var++);
343
else if (atoi(ptr->indicator->type->size) > 1)
345
newind = new_variable(cat_str(4, mm_strdup("("), mm_strdup(ecpg_type_name(ptr->indicator->type->type)), mm_strdup(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size, ptr->variable->type->counter), 0);
346
sprintf(temp, "%d, (", ecpg_internal_var++);
350
newind = new_variable(cat_str(4, mm_strdup("*("), mm_strdup(ecpg_type_name(ptr->indicator->type->type)), mm_strdup(" *)(ECPGget_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size, ptr->variable->type->counter), 0);
351
sprintf(temp, "%d, &(", ecpg_internal_var++);
354
/* create call to "ECPGset_var(<counter>, <pointer>. <line number>)" */
355
result = cat_str(5, result, mm_strdup("ECPGset_var("), mm_strdup(temp), mm_strdup(original_var), mm_strdup("), __LINE__);\n"));
358
add_variable_to_tail(&newlist, newvar, newind);
362
cur->argsinsert_oos = newlist;
364
cur->argsresult_oos = newlist;
370
/* This tests whether the cursor was declared and opened in the same function. */
371
#define SAMEFUNC(cur) \
372
((cur->function == NULL) || \
373
(cur->function != NULL && !strcmp(cur->function, current_function)))
375
static struct cursor *
376
add_additional_variables(char *name, bool insert)
380
int (* strcmp_fn)(const char *, const char *) = (name[0] == ':' ? strcmp : pg_strcasecmp);
382
for (ptr = cur; ptr != NULL; ptr=ptr->next)
384
if (strcmp_fn(ptr->name, name) == 0)
390
mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" does not exist", name);
396
/* add all those input variables that were given earlier
397
* note that we have to append here but have to keep the existing order */
398
for (p = (SAMEFUNC(ptr) ? ptr->argsinsert : ptr->argsinsert_oos); p; p = p->next)
399
add_variable_to_tail(&argsinsert, p->variable, p->indicator);
402
/* add all those output variables that were given earlier */
403
for (p = (SAMEFUNC(ptr) ? ptr->argsresult : ptr->argsresult_oos); p; p = p->next)
404
add_variable_to_tail(&argsresult, p->variable, p->indicator);
410
add_typedef(char *name, char * dimension, char * length, enum ECPGttype type_enum, char *type_dimension, char *type_index, int initializer, int array)
412
/* add entry to list */
413
struct typedefs *ptr, *this;
415
if ((type_enum == ECPGt_struct ||
416
type_enum == ECPGt_union) &&
418
mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in type definition");
419
else if (INFORMIX_MODE && strcmp(name, "string") == 0)
420
mmerror(PARSE_ERROR, ET_ERROR, "type name \"string\" is reserved in Informix mode");
423
for (ptr = types; ptr != NULL; ptr = ptr->next)
425
if (strcmp(name, ptr->name) == 0)
426
/* re-definition is a bug */
427
mmerror(PARSE_ERROR, ET_ERROR, "type \"%s\" is already defined", name);
429
adjust_array(type_enum, &dimension, &length, type_dimension, type_index, array, true);
431
this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
433
/* initial definition */
436
this->brace_level = braces_open;
437
this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
438
this->type->type_enum = type_enum;
439
this->type->type_str = mm_strdup(name);
440
this->type->type_dimension = dimension; /* dimension of array */
441
this->type->type_index = length; /* length of string */
442
this->type->type_sizeof = ECPGstruct_sizeof;
443
this->struct_member_list = (type_enum == ECPGt_struct || type_enum == ECPGt_union) ?
444
ECPGstruct_member_dup(struct_member_list[struct_level]) : NULL;
446
if (type_enum != ECPGt_varchar &&
447
type_enum != ECPGt_char &&
448
type_enum != ECPGt_unsigned_char &&
449
type_enum != ECPGt_string &&
450
atoi(this->type->type_index) >= 0)
451
mmerror(PARSE_ERROR, ET_ERROR, "multidimensional arrays for simple data types are not supported");
459
%name-prefix="base_yy"
469
struct this_type type;
470
enum ECPGttype type_enum;
471
enum ECPGdtype dtype_enum;
472
struct fetch_desc descriptor;
473
struct su_symbol struct_union;