~ubuntu-branches/ubuntu/lucid/postgresql-8.4/lucid-security

« back to all changes in this revision

Viewing changes to src/interfaces/ecpg/preproc/ecpg.header

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-03-20 12:00:13 UTC
  • Revision ID: james.westby@ubuntu.com-20090320120013-hogj7egc5mjncc5g
Tags: upstream-8.4~0cvs20090328
ImportĀ upstreamĀ versionĀ 8.4~0cvs20090328

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $PostgreSQL$ */
 
2
 
 
3
/* Copyright comment */
 
4
%{
 
5
#include "postgres_fe.h"
 
6
 
 
7
#include "extern.h"
 
8
#include <unistd.h>
 
9
 
 
10
/* Location tracking support --- simpler than bison's default */
 
11
#define YYLLOC_DEFAULT(Current, Rhs, N) \
 
12
        do { \
 
13
                if (N) \
 
14
                        (Current) = (Rhs)[1]; \
 
15
                else \
 
16
                        (Current) = (Rhs)[0]; \
 
17
        } while (0)
 
18
 
 
19
/*
 
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).
 
22
 */
 
23
#define base_yylex filtered_base_yylex
 
24
 
 
25
/*
 
26
 * Variables containing simple states.
 
27
 */
 
28
int struct_level = 0;
 
29
int braces_open; /* brace level counter */
 
30
int ecpg_informix_var = 0;
 
31
char    *connection = NULL;
 
32
char    *input_filename = NULL;
 
33
 
 
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];
 
40
 
 
41
/* temporarily store struct members while creating the data structure */
 
42
struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH] = { NULL };
 
43
 
 
44
/* also store struct type so we can do a sizeof() later */
 
45
static char *ECPGstruct_sizeof = NULL;
 
46
 
 
47
/* for forward declarations we have to store some data as well */
 
48
static char *forward_name = NULL;
 
49
 
 
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};
 
52
 
 
53
struct ECPGtype ecpg_query = {ECPGt_char_variable, NULL, NULL, {NULL}, 0};
 
54
 
 
55
/*
 
56
 * Handle parsing errors and warnings
 
57
 */
 
58
void
 
59
mmerror(int error_code, enum errortype type, char * error, ...)
 
60
{
 
61
        va_list ap;
 
62
 
 
63
        /* internationalize the error message string */
 
64
        error = _(error);
 
65
 
 
66
        fprintf(stderr, "%s:%d: ", input_filename, yylineno);
 
67
 
 
68
        switch(type)
 
69
        {
 
70
                case ET_WARNING:
 
71
                        fprintf(stderr, _("WARNING: "));
 
72
                        break;
 
73
                case ET_ERROR:
 
74
                case ET_FATAL:
 
75
                        fprintf(stderr, _("ERROR: "));
 
76
                        break;
 
77
        }
 
78
 
 
79
        va_start(ap, error);
 
80
        vfprintf(stderr, error, ap);
 
81
        va_end(ap);
 
82
 
 
83
        fprintf(stderr, "\n");
 
84
 
 
85
        switch(type)
 
86
        {
 
87
                case ET_WARNING:
 
88
                        break;
 
89
                case ET_ERROR:
 
90
                        ret_value = error_code;
 
91
                        break;
 
92
                case ET_FATAL:
 
93
                        if (yyin)
 
94
                                fclose(yyin);
 
95
                        if (yyout)
 
96
                                fclose(yyout);
 
97
                        
 
98
                        if (strcmp(output_filename, "-") != 0 && unlink(output_filename) != 0)
 
99
                                fprintf(stderr, _("could not remove output file \"%s\"\n"), output_filename);
 
100
                        exit(error_code);
 
101
        }
 
102
}
 
103
 
 
104
/*
 
105
 * string concatenation
 
106
 */
 
107
 
 
108
static char *
 
109
cat2_str(char *str1, char *str2)
 
110
{
 
111
        char * res_str  = (char *)mm_alloc(strlen(str1) + strlen(str2) + 2);
 
112
 
 
113
        strcpy(res_str, str1);
 
114
        if (strlen(str1) != 0 && strlen(str2) != 0)
 
115
                strcat(res_str, " ");
 
116
        strcat(res_str, str2);
 
117
        free(str1);
 
118
        free(str2);
 
119
        return(res_str);
 
120
}
 
121
 
 
122
static char *
 
123
cat_str(int count, ...)
 
124
{
 
125
        va_list         args;
 
126
        int                     i;
 
127
        char            *res_str;
 
128
 
 
129
        va_start(args, count);
 
130
 
 
131
        res_str = va_arg(args, char *);
 
132
 
 
133
        /* now add all other strings */
 
134
        for (i = 1; i < count; i++)
 
135
                res_str = cat2_str(res_str, va_arg(args, char *));
 
136
 
 
137
        va_end(args);
 
138
 
 
139
        return(res_str);
 
140
}
 
141
 
 
142
char *
 
143
make_str(const char *str)
 
144
{
 
145
        char * res_str = (char *)mm_alloc(strlen(str) + 1);
 
146
 
 
147
        strcpy(res_str, str);
 
148
        return res_str;
 
149
}
 
150
 
 
151
static char *
 
152
make2_str(char *str1, char *str2)
 
153
{
 
154
        char * res_str  = (char *)mm_alloc(strlen(str1) + strlen(str2) + 1);
 
155
 
 
156
        strcpy(res_str, str1);
 
157
        strcat(res_str, str2);
 
158
        free(str1);
 
159
        free(str2);
 
160
        return(res_str);
 
161
}
 
162
 
 
163
static char *
 
164
make3_str(char *str1, char *str2, char *str3)
 
165
{
 
166
        char * res_str  = (char *)mm_alloc(strlen(str1) + strlen(str2) +strlen(str3) + 1);
 
167
 
 
168
        strcpy(res_str, str1);
 
169
        strcat(res_str, str2);
 
170
        strcat(res_str, str3);
 
171
        free(str1);
 
172
        free(str2);
 
173
        free(str3);
 
174
        return(res_str);
 
175
}
 
176
 
 
177
/* and the rest */
 
178
static char *
 
179
make_name(void)
 
180
{
 
181
        char * name = (char *)mm_alloc(yyleng + 1);
 
182
 
 
183
        strncpy(name, yytext, yyleng);
 
184
        name[yyleng] = '\0';
 
185
        return(name);
 
186
}
 
187
 
 
188
static char *
 
189
create_questionmarks(char *name, bool array)
 
190
{
 
191
        struct variable *p = find_variable(name);
 
192
        int count;
 
193
        char *result = EMPTY;
 
194
 
 
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. */
 
199
 
 
200
        if (p->type->type == ECPGt_struct || (array && p->type->type == ECPGt_array && p->type->u.element->type == ECPGt_struct))
 
201
        {
 
202
                struct ECPGstruct_member *m;
 
203
 
 
204
                if (p->type->type == ECPGt_struct)
 
205
                        m = p->type->u.members;
 
206
                else
 
207
                        m = p->type->u.element->u.members;
 
208
 
 
209
                for (count = 0; m != NULL; m=m->next, count++);
 
210
        }
 
211
        else
 
212
                count = 1;
 
213
 
 
214
        for (; count > 0; count --)
 
215
        {
 
216
                sprintf(pacounter_buffer, "$%d", pacounter++);
 
217
                result = cat_str(3, result, strdup(pacounter_buffer), make_str(" , "));
 
218
        }
 
219
 
 
220
        /* removed the trailing " ," */
 
221
 
 
222
        result[strlen(result)-3] = '\0';
 
223
        return(result);
 
224
}
 
225
 
 
226
static char *
 
227
adjust_informix(struct arguments *list)
 
228
{
 
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
 
231
         * {
 
232
         *      declare_vars();
 
233
         *      exec sql ... which uses vars declared in the above function
 
234
         *
 
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
 
239
         */
 
240
 
 
241
         struct arguments *ptr;
 
242
         char *result = make_str("");
 
243
 
 
244
         for (ptr = list; ptr != NULL; ptr = ptr->next)
 
245
         {
 
246
                char temp[20]; /* this should be sufficient unless you have 8 byte integers */
 
247
                char *original_var;
 
248
 
 
249
                /* change variable name to "ECPG_informix_get_var(<counter>)" */
 
250
                original_var = ptr->variable->name;
 
251
                sprintf(temp, "%d))", ecpg_informix_var);
 
252
 
 
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)
 
254
                {
 
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++);
 
257
                }
 
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)
 
259
                {
 
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++);
 
262
                }
 
263
                else
 
264
                {
 
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++);
 
267
                }
 
268
 
 
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"));
 
271
 
 
272
                /* now the indicator if there is one */
 
273
                if (ptr->indicator->type->type != ECPGt_NO_INDICATOR)
 
274
                {
 
275
                        /* change variable name to "ECPG_informix_get_var(<counter>)" */
 
276
                        original_var = ptr->indicator->name;
 
277
                        sprintf(temp, "%d))", ecpg_informix_var);
 
278
 
 
279
                        /* create call to "ECPG_informix_set_var(<counter>, <pointer>. <linen number>)" */
 
280
                        if (atoi(ptr->indicator->type->size) > 1)
 
281
                        {
 
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++);
 
284
                        }
 
285
                        else
 
286
                        {
 
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++);
 
289
                        }
 
290
                        result = cat_str(5, result, make_str("ECPG_informix_set_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n"));
 
291
                }
 
292
         }
 
293
 
 
294
         return result;
 
295
}
 
296
 
 
297
static struct cursor *
 
298
add_additional_variables(char *name, bool insert)
 
299
{
 
300
        struct cursor *ptr;
 
301
        struct arguments *p;
 
302
 
 
303
        for (ptr = cur; ptr != NULL; ptr=ptr->next)
 
304
        {
 
305
                if (strcmp(ptr->name, name) == 0)
 
306
                        break;
 
307
        }
 
308
 
 
309
        if (ptr == NULL)
 
310
        {
 
311
                mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" does not exist", name);
 
312
                return NULL;
 
313
        }
 
314
 
 
315
        if (insert)
 
316
        {
 
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);
 
321
        }
 
322
 
 
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);
 
326
 
 
327
        return ptr;
 
328
}
 
329
 
 
330
static void
 
331
add_typedef(char *name, char * dimension, char * length, enum ECPGttype type_enum, char *type_dimension, char *type_index, int initializer, int array)
 
332
{
 
333
        /* add entry to list */
 
334
        struct typedefs *ptr, *this;
 
335
 
 
336
        if ((type_enum == ECPGt_struct ||
 
337
             type_enum == ECPGt_union) &&
 
338
            initializer == 1)
 
339
                mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in type definition");
 
340
        else
 
341
        {
 
342
                for (ptr = types; ptr != NULL; ptr = ptr->next)
 
343
                {
 
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);
 
347
                }
 
348
                adjust_array(type_enum, &dimension, &length, type_dimension, type_index, array, true);
 
349
 
 
350
                this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
 
351
 
 
352
                /* initial definition */
 
353
                this->next = types;
 
354
                this->name = name;
 
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;
 
364
 
 
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");
 
370
 
 
371
                types = this;
 
372
        }
 
373
}
 
374
%}
 
375
 
 
376
%expect 0
 
377
%name-prefix="base_yy"
 
378
%locations
 
379
 
 
380
%union {
 
381
        double  dval;
 
382
        char    *str;
 
383
        int     ival;
 
384
        struct  when            action;
 
385
        struct  index           index;
 
386
        int             tagname;
 
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;
 
392
        struct  prep            prep;
 
393
}