3
/* Copyright comment */
5
#include "postgres_fe.h"
10
/* Location tracking support --- simpler than bison's default */
11
#define YYLLOC_DEFAULT(Current, Rhs, N) \
14
(Current) = (Rhs)[1]; \
16
(Current) = (Rhs)[0]; \
20
* The %name-prefix option below will make bison call base_yylex, but we
21
* really want it to call filtered_base_yylex (see parser.c).
23
#define base_yylex filtered_base_yylex
26
* Variables containing simple states.
29
int braces_open; /* brace level counter */
30
int ecpg_informix_var = 0;
31
char *connection = NULL;
32
char *input_filename = NULL;
34
static int QueryIsRule = 0, FoundInto = 0;
35
static int initializer = 0;
36
static int pacounter = 1;
37
static char pacounter_buffer[sizeof(int) * CHAR_BIT * 10 / 3]; /* a rough guess at the size we need */
38
static struct this_type actual_type[STRUCT_DEPTH];
39
static char *actual_startline[STRUCT_DEPTH];
41
/* temporarily store struct members while creating the data structure */
42
struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH] = { NULL };
44
/* also store struct type so we can do a sizeof() later */
45
static char *ECPGstruct_sizeof = NULL;
47
/* for forward declarations we have to store some data as well */
48
static char *forward_name = NULL;
50
struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, NULL, NULL, {NULL}, 0};
51
struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL};
53
struct ECPGtype ecpg_query = {ECPGt_char_variable, NULL, NULL, {NULL}, 0};
56
* Handle parsing errors and warnings
59
mmerror(int error_code, enum errortype type, char * error, ...)
63
/* internationalize the error message string */
66
fprintf(stderr, "%s:%d: ", input_filename, yylineno);
71
fprintf(stderr, _("WARNING: "));
75
fprintf(stderr, _("ERROR: "));
80
vfprintf(stderr, error, ap);
83
fprintf(stderr, "\n");
90
ret_value = error_code;
98
if (strcmp(output_filename, "-") != 0 && unlink(output_filename) != 0)
99
fprintf(stderr, _("could not remove output file \"%s\"\n"), output_filename);
105
* string concatenation
109
cat2_str(char *str1, char *str2)
111
char * res_str = (char *)mm_alloc(strlen(str1) + strlen(str2) + 2);
113
strcpy(res_str, str1);
114
if (strlen(str1) != 0 && strlen(str2) != 0)
115
strcat(res_str, " ");
116
strcat(res_str, str2);
123
cat_str(int count, ...)
129
va_start(args, count);
131
res_str = va_arg(args, char *);
133
/* now add all other strings */
134
for (i = 1; i < count; i++)
135
res_str = cat2_str(res_str, va_arg(args, char *));
143
make_str(const char *str)
145
char * res_str = (char *)mm_alloc(strlen(str) + 1);
147
strcpy(res_str, str);
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
char * name = (char *)mm_alloc(yyleng + 1);
183
strncpy(name, yytext, yyleng);
189
create_questionmarks(char *name, bool array)
191
struct variable *p = find_variable(name);
193
char *result = EMPTY;
195
/* In case we have a struct, we have to print as many "?" as there are attributes in the struct
196
* An array is only allowed together with an element argument
197
* This is essantially only used for inserts, but using a struct as input parameter is an error anywhere else
198
* so we don't have to worry here. */
200
if (p->type->type == ECPGt_struct || (array && p->type->type == ECPGt_array && p->type->u.element->type == ECPGt_struct))
202
struct ECPGstruct_member *m;
204
if (p->type->type == ECPGt_struct)
205
m = p->type->u.members;
207
m = p->type->u.element->u.members;
209
for (count = 0; m != NULL; m=m->next, count++);
214
for (; count > 0; count --)
216
sprintf(pacounter_buffer, "$%d", pacounter++);
217
result = cat_str(3, result, strdup(pacounter_buffer), make_str(" , "));
220
/* removed the trailing " ," */
222
result[strlen(result)-3] = '\0';
227
adjust_informix(struct arguments *list)
229
/* Informix accepts DECLARE with variables that are out of scope when OPEN is called.
230
* for instance you can declare variables in a function, and then subsequently use them
233
* exec sql ... which uses vars declared in the above function
235
* This breaks standard and leads to some very dangerous programming.
236
* Since they do, we have to work around and accept their syntax as well.
237
* But we will do so ONLY in Informix mode.
238
* We have to change the variables to our own struct and just store the pointer instead of the variable
241
struct arguments *ptr;
242
char *result = make_str("");
244
for (ptr = list; ptr != NULL; ptr = ptr->next)
246
char temp[20]; /* this should be sufficient unless you have 8 byte integers */
249
/* change variable name to "ECPG_informix_get_var(<counter>)" */
250
original_var = ptr->variable->name;
251
sprintf(temp, "%d))", ecpg_informix_var);
253
if ((ptr->variable->type->type != ECPGt_varchar && ptr->variable->type->type != ECPGt_char && ptr->variable->type->type != ECPGt_unsigned_char) && atoi(ptr->variable->type->size) > 1)
255
ptr->variable = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->variable->type->u.element->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type, make_str("1"), ptr->variable->type->u.element->lineno), ptr->variable->type->size), 0);
256
sprintf(temp, "%d, (", ecpg_informix_var++);
258
else if ((ptr->variable->type->type == ECPGt_varchar || ptr->variable->type->type == ECPGt_char || ptr->variable->type->type == ECPGt_unsigned_char) && atoi(ptr->variable->type->size) > 1)
260
ptr->variable = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->variable->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->lineno), 0);
261
sprintf(temp, "%d, (", ecpg_informix_var++);
265
ptr->variable = new_variable(cat_str(4, make_str("*("), mm_strdup(ecpg_type_name(ptr->variable->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->lineno), 0);
266
sprintf(temp, "%d, &(", ecpg_informix_var++);
269
/* create call to "ECPG_informix_set_var(<counter>, <pointer>. <linen number>)" */
270
result = cat_str(5, result, make_str("ECPG_informix_set_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n"));
272
/* now the indicator if there is one */
273
if (ptr->indicator->type->type != ECPGt_NO_INDICATOR)
275
/* change variable name to "ECPG_informix_get_var(<counter>)" */
276
original_var = ptr->indicator->name;
277
sprintf(temp, "%d))", ecpg_informix_var);
279
/* create call to "ECPG_informix_set_var(<counter>, <pointer>. <linen number>)" */
280
if (atoi(ptr->indicator->type->size) > 1)
282
ptr->indicator = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->indicator->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size, ptr->variable->type->lineno), 0);
283
sprintf(temp, "%d, (", ecpg_informix_var++);
287
ptr->indicator = new_variable(cat_str(4, make_str("*("), mm_strdup(ecpg_type_name(ptr->indicator->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size, ptr->variable->type->lineno), 0);
288
sprintf(temp, "%d, &(", ecpg_informix_var++);
290
result = cat_str(5, result, make_str("ECPG_informix_set_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n"));
297
static struct cursor *
298
add_additional_variables(char *name, bool insert)
303
for (ptr = cur; ptr != NULL; ptr=ptr->next)
305
if (strcmp(ptr->name, name) == 0)
311
mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" does not exist", name);
317
/* add all those input variables that were given earlier
318
* note that we have to append here but have to keep the existing order */
319
for (p = ptr->argsinsert; p; p = p->next)
320
add_variable_to_tail(&argsinsert, p->variable, p->indicator);
323
/* add all those output variables that were given earlier */
324
for (p = ptr->argsresult; p; p = p->next)
325
add_variable_to_tail(&argsresult, p->variable, p->indicator);
331
add_typedef(char *name, char * dimension, char * length, enum ECPGttype type_enum, char *type_dimension, char *type_index, int initializer, int array)
333
/* add entry to list */
334
struct typedefs *ptr, *this;
336
if ((type_enum == ECPGt_struct ||
337
type_enum == ECPGt_union) &&
339
mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in type definition");
342
for (ptr = types; ptr != NULL; ptr = ptr->next)
344
if (strcmp(name, ptr->name) == 0)
345
/* re-definition is a bug */
346
mmerror(PARSE_ERROR, ET_ERROR, "type \"%s\" is already defined", name);
348
adjust_array(type_enum, &dimension, &length, type_dimension, type_index, array, true);
350
this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
352
/* initial definition */
355
this->brace_level = braces_open;
356
this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
357
this->type->type_enum = type_enum;
358
this->type->type_str = mm_strdup(name);
359
this->type->type_dimension = dimension; /* dimension of array */
360
this->type->type_index = length; /* length of string */
361
this->type->type_sizeof = ECPGstruct_sizeof;
362
this->struct_member_list = (type_enum == ECPGt_struct || type_enum == ECPGt_union) ?
363
ECPGstruct_member_dup(struct_member_list[struct_level]) : NULL;
365
if (type_enum != ECPGt_varchar &&
366
type_enum != ECPGt_char &&
367
type_enum != ECPGt_unsigned_char &&
368
atoi(this->type->type_index) >= 0)
369
mmerror(PARSE_ERROR, ET_ERROR, "multidimensional arrays for simple data types are not supported");
377
%name-prefix="base_yy"
387
struct this_type type;
388
enum ECPGttype type_enum;
389
enum ECPGdtype dtype_enum;
390
struct fetch_desc descriptor;
391
struct su_symbol struct_union;