~ubuntu-branches/ubuntu/oneiric/postgresql-9.1/oneiric-security

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* src/interfaces/ecpg/preproc/ecpg.trailer */
 
2
 
 
3
statements: /*EMPTY*/
 
4
                | statements statement
 
5
                ;
 
6
 
 
7
statement: ecpgstart at stmt ';'        { connection = NULL; }
 
8
                | ecpgstart stmt ';'
 
9
                | ecpgstart ECPGVarDeclaration
 
10
                {
 
11
                        fprintf(yyout, "%s", $2);
 
12
                        free($2);
 
13
                        output_line_number();
 
14
                }
 
15
                | ECPGDeclaration
 
16
                | c_thing               { fprintf(yyout, "%s", $1); free($1); }
 
17
                | CPP_LINE              { fprintf(yyout, "%s", $1); free($1); }
 
18
                | '{'                   { braces_open++; fputs("{", yyout); }
 
19
                | '}'
 
20
                {
 
21
                        remove_typedefs(braces_open);
 
22
                        remove_variables(braces_open--);
 
23
                        if (braces_open == 0)
 
24
                        {
 
25
                                free(current_function);
 
26
                                current_function = NULL;
 
27
                        }
 
28
                        fputs("}", yyout);
 
29
                }
 
30
                ;
 
31
 
 
32
CreateAsStmt: CREATE OptTemp TABLE create_as_target AS {FoundInto = 0;} SelectStmt opt_with_data
 
33
                {
 
34
                        if (FoundInto == 1)
 
35
                                mmerror(PARSE_ERROR, ET_ERROR, "CREATE TABLE AS cannot specify INTO");
 
36
 
 
37
                        $$ = cat_str(6, mm_strdup("create"), $2, mm_strdup("table"), $4, mm_strdup("as"), $7);
 
38
                }
 
39
        ;
 
40
 
 
41
at: AT connection_object
 
42
                {
 
43
                        connection = $2;
 
44
                        /*
 
45
                         *      Do we have a variable as connection target?
 
46
                         *      Remove the variable from the variable
 
47
                         *      list or else it will be used twice
 
48
                         */
 
49
                        if (argsinsert != NULL)
 
50
                                argsinsert = NULL;
 
51
                }
 
52
        ;
 
53
 
 
54
/*
 
55
 * the exec sql connect statement: connect to the given database
 
56
 */
 
57
ECPGConnect: SQL_CONNECT TO connection_target opt_connection_name opt_user
 
58
                        { $$ = cat_str(5, $3, mm_strdup(","), $5, mm_strdup(","), $4); }
 
59
                | SQL_CONNECT TO DEFAULT
 
60
                        { $$ = mm_strdup("NULL, NULL, NULL, \"DEFAULT\""); }
 
61
                  /* also allow ORACLE syntax */
 
62
                | SQL_CONNECT ora_user
 
63
                        { $$ = cat_str(3, mm_strdup("NULL,"), $2, mm_strdup(", NULL")); }
 
64
                | DATABASE connection_target
 
65
                        { $$ = cat2_str($2, mm_strdup(", NULL, NULL, NULL")); }
 
66
                ;
 
67
 
 
68
connection_target: opt_database_name opt_server opt_port
 
69
                {
 
70
                        /* old style: dbname[@server][:port] */
 
71
                        if (strlen($2) > 0 && *($2) != '@')
 
72
                                mmerror(PARSE_ERROR, ET_ERROR, "expected \"@\", found \"%s\"", $2);
 
73
 
 
74
                        /* C strings need to be handled differently */
 
75
                        if ($1[0] == '\"')
 
76
                                $$ = $1;
 
77
                        else
 
78
                                $$ = make3_str(mm_strdup("\""), make3_str($1, $2, $3), mm_strdup("\""));
 
79
                }
 
80
                |  db_prefix ':' server opt_port '/' opt_database_name opt_options
 
81
                {
 
82
                        /* new style: <tcp|unix>:postgresql://server[:port][/dbname] */
 
83
                        if (strncmp($1, "unix:postgresql", strlen("unix:postgresql")) != 0 && strncmp($1, "tcp:postgresql", strlen("tcp:postgresql")) != 0)
 
84
                                mmerror(PARSE_ERROR, ET_ERROR, "only protocols \"tcp\" and \"unix\" and database type \"postgresql\" are supported");
 
85
 
 
86
                        if (strncmp($3, "//", strlen("//")) != 0)
 
87
                                mmerror(PARSE_ERROR, ET_ERROR, "expected \"://\", found \"%s\"", $3);
 
88
 
 
89
                        if (strncmp($1, "unix", strlen("unix")) == 0 &&
 
90
                                strncmp($3 + strlen("//"), "localhost", strlen("localhost")) != 0 &&
 
91
                                strncmp($3 + strlen("//"), "127.0.0.1", strlen("127.0.0.1")) != 0)
 
92
                                mmerror(PARSE_ERROR, ET_ERROR, "Unix-domain sockets only work on \"localhost\" but not on \"%s\"", $3 + strlen("//"));
 
93
 
 
94
                        $$ = make3_str(make3_str(mm_strdup("\""), $1, mm_strdup(":")), $3, make3_str(make3_str($4, mm_strdup("/"), $6), $7, mm_strdup("\"")));
 
95
                }
 
96
                | char_variable
 
97
                {
 
98
                        $$ = $1;
 
99
                }
 
100
                | ecpg_sconst
 
101
                {
 
102
                        /* We can only process double quoted strings not single quotes ones,
 
103
                         * so we change the quotes.
 
104
                         * Note, that the rule for ecpg_sconst adds these single quotes. */
 
105
                        $1[0] = '\"';
 
106
                        $1[strlen($1)-1] = '\"';
 
107
                        $$ = $1;
 
108
                }
 
109
                ;
 
110
 
 
111
opt_database_name: database_name                { $$ = $1; }
 
112
                | /*EMPTY*/                     { $$ = EMPTY; }
 
113
                ;
 
114
 
 
115
db_prefix: ecpg_ident cvariable
 
116
                {
 
117
                        if (strcmp($2, "postgresql") != 0 && strcmp($2, "postgres") != 0)
 
118
                                mmerror(PARSE_ERROR, ET_ERROR, "expected \"postgresql\", found \"%s\"", $2);
 
119
 
 
120
                        if (strcmp($1, "tcp") != 0 && strcmp($1, "unix") != 0)
 
121
                                mmerror(PARSE_ERROR, ET_ERROR, "invalid connection type: %s", $1);
 
122
 
 
123
                        $$ = make3_str($1, mm_strdup(":"), $2);
 
124
                }
 
125
                ;
 
126
 
 
127
server: Op server_name
 
128
                {
 
129
                        if (strcmp($1, "@") != 0 && strcmp($1, "//") != 0)
 
130
                                mmerror(PARSE_ERROR, ET_ERROR, "expected \"@\" or \"://\", found \"%s\"", $1);
 
131
 
 
132
                        $$ = make2_str($1, $2);
 
133
                }
 
134
                ;
 
135
 
 
136
opt_server: server                      { $$ = $1; }
 
137
                | /*EMPTY*/                     { $$ = EMPTY; }
 
138
                ;
 
139
 
 
140
server_name: ColId                                      { $$ = $1; }
 
141
                | ColId '.' server_name         { $$ = make3_str($1, mm_strdup("."), $3); }
 
142
                | IP                                            { $$ = make_name(); }
 
143
                ;
 
144
 
 
145
opt_port: ':' Iconst            { $$ = make2_str(mm_strdup(":"), $2); }
 
146
                | /*EMPTY*/     { $$ = EMPTY; }
 
147
                ;
 
148
 
 
149
opt_connection_name: AS connection_object       { $$ = $2; }
 
150
                | /*EMPTY*/                     { $$ = mm_strdup("NULL"); }
 
151
                ;
 
152
 
 
153
opt_user: USER ora_user         { $$ = $2; }
 
154
                | /*EMPTY*/                     { $$ = mm_strdup("NULL, NULL"); }
 
155
                ;
 
156
 
 
157
ora_user: user_name
 
158
                        { $$ = cat2_str($1, mm_strdup(", NULL")); }
 
159
                | user_name '/' user_name
 
160
                        { $$ = cat_str(3, $1, mm_strdup(","), $3); }
 
161
                | user_name SQL_IDENTIFIED BY user_name
 
162
                        { $$ = cat_str(3, $1, mm_strdup(","), $4); }
 
163
                | user_name USING user_name
 
164
                        { $$ = cat_str(3, $1, mm_strdup(","), $3); }
 
165
                ;
 
166
 
 
167
user_name: RoleId
 
168
                {
 
169
                        if ($1[0] == '\"')
 
170
                                $$ = $1;
 
171
                        else
 
172
                                $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\""));
 
173
                }
 
174
                | ecpg_sconst
 
175
                {
 
176
                        if ($1[0] == '\"')
 
177
                                $$ = $1;
 
178
                        else
 
179
                                $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\""));
 
180
                }
 
181
                | civar
 
182
                {
 
183
                        enum ECPGttype type = argsinsert->variable->type->type;
 
184
 
 
185
                        /* if array see what's inside */
 
186
                        if (type == ECPGt_array)
 
187
                                type = argsinsert->variable->type->u.element->type;
 
188
 
 
189
                        /* handle varchars */
 
190
                        if (type == ECPGt_varchar)
 
191
                                $$ = make2_str(mm_strdup(argsinsert->variable->name), mm_strdup(".arr"));
 
192
                        else
 
193
                                $$ = mm_strdup(argsinsert->variable->name);
 
194
                }
 
195
                ;
 
196
 
 
197
char_variable: cvariable
 
198
                {
 
199
                        /* check if we have a string variable */
 
200
                        struct variable *p = find_variable($1);
 
201
                        enum ECPGttype type = p->type->type;
 
202
 
 
203
                        /* If we have just one character this is not a string */
 
204
                        if (atol(p->type->size) == 1)
 
205
                                        mmerror(PARSE_ERROR, ET_ERROR, "invalid data type");
 
206
                        else
 
207
                        {
 
208
                                /* if array see what's inside */
 
209
                                if (type == ECPGt_array)
 
210
                                        type = p->type->u.element->type;
 
211
 
 
212
                                switch (type)
 
213
                                {
 
214
                                        case ECPGt_char:
 
215
                                        case ECPGt_unsigned_char:
 
216
                                        case ECPGt_string:
 
217
                                                $$ = $1;
 
218
                                                break;
 
219
                                        case ECPGt_varchar:
 
220
                                                $$ = make2_str($1, mm_strdup(".arr"));
 
221
                                                break;
 
222
                                        default:
 
223
                                                mmerror(PARSE_ERROR, ET_ERROR, "invalid data type");
 
224
                                                $$ = $1;
 
225
                                                break;
 
226
                                }
 
227
                        }
 
228
                }
 
229
                ;
 
230
 
 
231
opt_options: Op connect_options
 
232
                {
 
233
                        if (strlen($1) == 0)
 
234
                                mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement");
 
235
 
 
236
                        if (strcmp($1, "?") != 0)
 
237
                                mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", $1);
 
238
 
 
239
                        $$ = make2_str(mm_strdup("?"), $2);
 
240
                }
 
241
                | /*EMPTY*/     { $$ = EMPTY; }
 
242
                ;
 
243
 
 
244
connect_options:  ColId opt_opt_value
 
245
                        { $$ = make2_str($1, $2); }
 
246
        | ColId opt_opt_value Op connect_options
 
247
                        {
 
248
                                if (strlen($3) == 0)
 
249
                                        mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement");
 
250
 
 
251
                                if (strcmp($3, "&") != 0)
 
252
                                        mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", $3);
 
253
 
 
254
                                $$ = cat_str(3, make2_str($1, $2), $3, $4);
 
255
                        }
 
256
        ;
 
257
 
 
258
opt_opt_value: /*EMPTY*/
 
259
                        { $$ = EMPTY; }
 
260
                | '=' Iconst
 
261
                        { $$ = make2_str(mm_strdup("="), $2); }
 
262
                | '=' ecpg_ident
 
263
                        { $$ = make2_str(mm_strdup("="), $2); }
 
264
                | '=' civar
 
265
                        { $$ = make2_str(mm_strdup("="), $2); }
 
266
                ;
 
267
 
 
268
prepared_name: name             {
 
269
                                        if ($1[0] == '\"' && $1[strlen($1)-1] == '\"') /* already quoted? */
 
270
                                                $$ = $1;
 
271
                                        else /* not quoted => convert to lowercase */
 
272
                                        {
 
273
                                                size_t i;
 
274
 
 
275
                                                for (i = 0; i< strlen($1); i++)
 
276
                                                        $1[i] = tolower((unsigned char) $1[i]);
 
277
 
 
278
                                                $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\""));
 
279
                                        }
 
280
                                }
 
281
                | char_variable { $$ = $1; }
 
282
                ;
 
283
 
 
284
/*
 
285
 * Declare a prepared cursor. The syntax is different from the standard
 
286
 * declare statement, so we create a new rule.
 
287
 */
 
288
ECPGCursorStmt:  DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared_name
 
289
                {
 
290
                        struct cursor *ptr, *this;
 
291
                        char *cursor_marker = $2[0] == ':' ? mm_strdup("$0") : mm_strdup($2);
 
292
                        int (* strcmp_fn)(const char *, const char *) = ($2[0] == ':' ? strcmp : pg_strcasecmp);
 
293
                        struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
 
294
                        const char *con = connection ? connection : "NULL";
 
295
                        char *comment;
 
296
 
 
297
                        for (ptr = cur; ptr != NULL; ptr = ptr->next)
 
298
                        {
 
299
                                if (strcmp_fn($2, ptr->name) == 0)
 
300
                                {
 
301
                                        /* re-definition is a bug */
 
302
                                        if ($2[0] == ':')
 
303
                                                mmerror(PARSE_ERROR, ET_ERROR, "using variable \"%s\" in different declare statements is not supported", $2+1);
 
304
                                        else
 
305
                                                mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" is already defined", $2);
 
306
                                }
 
307
                        }
 
308
 
 
309
                        this = (struct cursor *) mm_alloc(sizeof(struct cursor));
 
310
 
 
311
                        /* initial definition */
 
312
                        this->next = cur;
 
313
                        this->name = $2;
 
314
                        this->function = (current_function ? mm_strdup(current_function) : NULL);
 
315
                        this->connection = connection;
 
316
                        this->command =  cat_str(6, mm_strdup("declare"), cursor_marker, $3, mm_strdup("cursor"), $5, mm_strdup("for $1"));
 
317
                        this->argsresult = NULL;
 
318
                        this->argsresult_oos = NULL;
 
319
 
 
320
                        thisquery->type = &ecpg_query;
 
321
                        thisquery->brace_level = 0;
 
322
                        thisquery->next = NULL;
 
323
                        thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement(, , __LINE__)") + strlen(con) + strlen($7));
 
324
                        sprintf(thisquery->name, "ECPGprepared_statement(%s, %s, __LINE__)", con, $7);
 
325
 
 
326
                        this->argsinsert = NULL;
 
327
                        this->argsinsert_oos = NULL;
 
328
                        if ($2[0] == ':')
 
329
                        {
 
330
                                struct variable *var = find_variable($2 + 1);
 
331
                                remove_variable_from_list(&argsinsert, var);
 
332
                                add_variable_to_head(&(this->argsinsert), var, &no_indicator);
 
333
                        }
 
334
                        add_variable_to_head(&(this->argsinsert), thisquery, &no_indicator);
 
335
 
 
336
                        cur = this;
 
337
 
 
338
                        comment = cat_str(3, mm_strdup("/*"), mm_strdup(this->command), mm_strdup("*/"));
 
339
 
 
340
                        if ((braces_open > 0) && INFORMIX_MODE) /* we're in a function */
 
341
                                $$ = cat_str(3, adjust_outofscope_cursor_vars(this),
 
342
                                        mm_strdup("ECPG_informix_reset_sqlca();"),
 
343
                                        comment);
 
344
                        else
 
345
                                $$ = cat2_str(adjust_outofscope_cursor_vars(this), comment);
 
346
                }
 
347
                ;
 
348
 
 
349
ECPGExecuteImmediateStmt: EXECUTE IMMEDIATE execstring
 
350
                        {
 
351
                          /* execute immediate means prepare the statement and
 
352
                           * immediately execute it */
 
353
                          $$ = $3;
 
354
                        };
 
355
/*
 
356
 * variable decalartion outside exec sql declare block
 
357
 */
 
358
ECPGVarDeclaration: single_vt_declaration;
 
359
 
 
360
single_vt_declaration: type_declaration         { $$ = $1; }
 
361
                | var_declaration               { $$ = $1; }
 
362
                ;
 
363
 
 
364
precision:      NumericOnly     { $$ = $1; };
 
365
 
 
366
opt_scale:      ',' NumericOnly { $$ = $2; }
 
367
                | /* EMPTY */   { $$ = EMPTY; }
 
368
                ;
 
369
 
 
370
ecpg_interval:  opt_interval    { $$ = $1; }
 
371
                | YEAR_P TO MINUTE_P    { $$ = mm_strdup("year to minute"); }
 
372
                | YEAR_P TO SECOND_P    { $$ = mm_strdup("year to second"); }
 
373
                | DAY_P TO DAY_P                { $$ = mm_strdup("day to day"); }
 
374
                | MONTH_P TO MONTH_P    { $$ = mm_strdup("month to month"); }
 
375
                ;
 
376
 
 
377
/*
 
378
 * variable declaration inside exec sql declare block
 
379
 */
 
380
ECPGDeclaration: sql_startdeclare
 
381
                { fputs("/* exec sql begin declare section */", yyout); }
 
382
                var_type_declarations sql_enddeclare
 
383
                {
 
384
                        fprintf(yyout, "%s/* exec sql end declare section */", $3);
 
385
                        free($3);
 
386
                        output_line_number();
 
387
                }
 
388
                ;
 
389
 
 
390
sql_startdeclare: ecpgstart BEGIN_P DECLARE SQL_SECTION ';' {};
 
391
 
 
392
sql_enddeclare: ecpgstart END_P DECLARE SQL_SECTION ';' {};
 
393
 
 
394
var_type_declarations:  /*EMPTY*/                       { $$ = EMPTY; }
 
395
                | vt_declarations                       { $$ = $1; }
 
396
                ;
 
397
 
 
398
vt_declarations:  single_vt_declaration                 { $$ = $1; }
 
399
                | CPP_LINE                              { $$ = $1; }
 
400
                | vt_declarations single_vt_declaration { $$ = cat2_str($1, $2); }
 
401
                | vt_declarations CPP_LINE              { $$ = cat2_str($1, $2); }
 
402
                ;
 
403
 
 
404
variable_declarations:  var_declaration         { $$ = $1; }
 
405
                | variable_declarations var_declaration         { $$ = cat2_str($1, $2); }
 
406
                ;
 
407
 
 
408
type_declaration: S_TYPEDEF
 
409
        {
 
410
                /* reset this variable so we see if there was */
 
411
                /* an initializer specified */
 
412
                initializer = 0;
 
413
        }
 
414
        var_type opt_pointer ECPGColLabelCommon opt_array_bounds ';'
 
415
        {
 
416
                add_typedef($5, $6.index1, $6.index2, $3.type_enum, $3.type_dimension, $3.type_index, initializer, *$4 ? 1 : 0);
 
417
 
 
418
                fprintf(yyout, "typedef %s %s %s %s;\n", $3.type_str, *$4 ? "*" : "", $5, $6.str);
 
419
                output_line_number();
 
420
                $$ = mm_strdup("");
 
421
        };
 
422
 
 
423
var_declaration: storage_declaration
 
424
                var_type
 
425
                {
 
426
                        actual_type[struct_level].type_enum = $2.type_enum;
 
427
                        actual_type[struct_level].type_str = $2.type_str;
 
428
                        actual_type[struct_level].type_dimension = $2.type_dimension;
 
429
                        actual_type[struct_level].type_index = $2.type_index;
 
430
                        actual_type[struct_level].type_sizeof = $2.type_sizeof;
 
431
 
 
432
                        actual_startline[struct_level] = hashline_number();
 
433
                }
 
434
                variable_list ';'
 
435
                {
 
436
                        $$ = cat_str(5, actual_startline[struct_level], $1, $2.type_str, $4, mm_strdup(";\n"));
 
437
                }
 
438
                | var_type
 
439
                {
 
440
                        actual_type[struct_level].type_enum = $1.type_enum;
 
441
                        actual_type[struct_level].type_str = $1.type_str;
 
442
                        actual_type[struct_level].type_dimension = $1.type_dimension;
 
443
                        actual_type[struct_level].type_index = $1.type_index;
 
444
                        actual_type[struct_level].type_sizeof = $1.type_sizeof;
 
445
 
 
446
                        actual_startline[struct_level] = hashline_number();
 
447
                }
 
448
                variable_list ';'
 
449
                {
 
450
                        $$ = cat_str(4, actual_startline[struct_level], $1.type_str, $3, mm_strdup(";\n"));
 
451
                }
 
452
                | struct_union_type_with_symbol ';'
 
453
                {
 
454
                        $$ = cat2_str($1, mm_strdup(";"));
 
455
                }
 
456
                ;
 
457
 
 
458
opt_bit_field:  ':' Iconst      { $$ =cat2_str(mm_strdup(":"), $2); }
 
459
                | /* EMPTY */   { $$ = EMPTY; }
 
460
                ;
 
461
 
 
462
storage_declaration: storage_clause storage_modifier
 
463
                        {$$ = cat2_str ($1, $2); }
 
464
                | storage_clause                {$$ = $1; }
 
465
                | storage_modifier              {$$ = $1; }
 
466
                ;
 
467
 
 
468
storage_clause : S_EXTERN       { $$ = mm_strdup("extern"); }
 
469
                | S_STATIC                      { $$ = mm_strdup("static"); }
 
470
                | S_REGISTER            { $$ = mm_strdup("register"); }
 
471
                | S_AUTO                        { $$ = mm_strdup("auto"); }
 
472
                ;
 
473
 
 
474
storage_modifier : S_CONST      { $$ = mm_strdup("const"); }
 
475
                | S_VOLATILE            { $$ = mm_strdup("volatile"); }
 
476
                ;
 
477
 
 
478
var_type:       simple_type
 
479
                {
 
480
                        $$.type_enum = $1;
 
481
                        $$.type_str = mm_strdup(ecpg_type_name($1));
 
482
                        $$.type_dimension = mm_strdup("-1");
 
483
                        $$.type_index = mm_strdup("-1");
 
484
                        $$.type_sizeof = NULL;
 
485
                }
 
486
                | struct_union_type
 
487
                {
 
488
                        $$.type_str = $1;
 
489
                        $$.type_dimension = mm_strdup("-1");
 
490
                        $$.type_index = mm_strdup("-1");
 
491
 
 
492
                        if (strncmp($1, "struct", sizeof("struct")-1) == 0)
 
493
                        {
 
494
                                $$.type_enum = ECPGt_struct;
 
495
                                $$.type_sizeof = ECPGstruct_sizeof;
 
496
                        }
 
497
                        else
 
498
                        {
 
499
                                $$.type_enum = ECPGt_union;
 
500
                                $$.type_sizeof = NULL;
 
501
                        }
 
502
                }
 
503
                | enum_type
 
504
                {
 
505
                        $$.type_str = $1;
 
506
                        $$.type_enum = ECPGt_int;
 
507
                        $$.type_dimension = mm_strdup("-1");
 
508
                        $$.type_index = mm_strdup("-1");
 
509
                        $$.type_sizeof = NULL;
 
510
                }
 
511
                | ECPGColLabelCommon '(' precision opt_scale ')'
 
512
                {
 
513
                        if (strcmp($1, "numeric") == 0)
 
514
                        {
 
515
                                $$.type_enum = ECPGt_numeric;
 
516
                                $$.type_str = mm_strdup("numeric");
 
517
                        }
 
518
                        else if (strcmp($1, "decimal") == 0)
 
519
                        {
 
520
                                $$.type_enum = ECPGt_decimal;
 
521
                                $$.type_str = mm_strdup("decimal");
 
522
                        }
 
523
                        else
 
524
                        {
 
525
                                mmerror(PARSE_ERROR, ET_ERROR, "only data types numeric and decimal have precision/scale argument");
 
526
                                $$.type_enum = ECPGt_numeric;
 
527
                                $$.type_str = mm_strdup("numeric");
 
528
                        }
 
529
 
 
530
                        $$.type_dimension = mm_strdup("-1");
 
531
                        $$.type_index = mm_strdup("-1");
 
532
                        $$.type_sizeof = NULL;
 
533
                }
 
534
                | ECPGColLabelCommon ecpg_interval
 
535
                {
 
536
                        if (strlen($2) != 0 && strcmp ($1, "datetime") != 0 && strcmp ($1, "interval") != 0)
 
537
                                mmerror (PARSE_ERROR, ET_ERROR, "interval specification not allowed here");
 
538
 
 
539
                        /*
 
540
                         * Check for type names that the SQL grammar treats as
 
541
                         * unreserved keywords
 
542
                         */
 
543
                        if (strcmp($1, "varchar") == 0)
 
544
                        {
 
545
                                $$.type_enum = ECPGt_varchar;
 
546
                                $$.type_str = EMPTY; /*mm_strdup("varchar");*/
 
547
                                $$.type_dimension = mm_strdup("-1");
 
548
                                $$.type_index = mm_strdup("-1");
 
549
                                $$.type_sizeof = NULL;
 
550
                        }
 
551
                        else if (strcmp($1, "float") == 0)
 
552
                        {
 
553
                                $$.type_enum = ECPGt_float;
 
554
                                $$.type_str = mm_strdup("float");
 
555
                                $$.type_dimension = mm_strdup("-1");
 
556
                                $$.type_index = mm_strdup("-1");
 
557
                                $$.type_sizeof = NULL;
 
558
                        }
 
559
                        else if (strcmp($1, "double") == 0)
 
560
                        {
 
561
                                $$.type_enum = ECPGt_double;
 
562
                                $$.type_str = mm_strdup("double");
 
563
                                $$.type_dimension = mm_strdup("-1");
 
564
                                $$.type_index = mm_strdup("-1");
 
565
                                $$.type_sizeof = NULL;
 
566
                        }
 
567
                        else if (strcmp($1, "numeric") == 0)
 
568
                        {
 
569
                                $$.type_enum = ECPGt_numeric;
 
570
                                $$.type_str = mm_strdup("numeric");
 
571
                                $$.type_dimension = mm_strdup("-1");
 
572
                                $$.type_index = mm_strdup("-1");
 
573
                                $$.type_sizeof = NULL;
 
574
                        }
 
575
                        else if (strcmp($1, "decimal") == 0)
 
576
                        {
 
577
                                $$.type_enum = ECPGt_decimal;
 
578
                                $$.type_str = mm_strdup("decimal");
 
579
                                $$.type_dimension = mm_strdup("-1");
 
580
                                $$.type_index = mm_strdup("-1");
 
581
                                $$.type_sizeof = NULL;
 
582
                        }
 
583
                        else if (strcmp($1, "date") == 0)
 
584
                        {
 
585
                                $$.type_enum = ECPGt_date;
 
586
                                $$.type_str = mm_strdup("date");
 
587
                                $$.type_dimension = mm_strdup("-1");
 
588
                                $$.type_index = mm_strdup("-1");
 
589
                                $$.type_sizeof = NULL;
 
590
                        }
 
591
                        else if (strcmp($1, "timestamp") == 0)
 
592
                        {
 
593
                                $$.type_enum = ECPGt_timestamp;
 
594
                                $$.type_str = mm_strdup("timestamp");
 
595
                                $$.type_dimension = mm_strdup("-1");
 
596
                                $$.type_index = mm_strdup("-1");
 
597
                                $$.type_sizeof = NULL;
 
598
                        }
 
599
                        else if (strcmp($1, "interval") == 0)
 
600
                        {
 
601
                                $$.type_enum = ECPGt_interval;
 
602
                                $$.type_str = mm_strdup("interval");
 
603
                                $$.type_dimension = mm_strdup("-1");
 
604
                                $$.type_index = mm_strdup("-1");
 
605
                                $$.type_sizeof = NULL;
 
606
                        }
 
607
                        else if (strcmp($1, "datetime") == 0)
 
608
                        {
 
609
                                $$.type_enum = ECPGt_timestamp;
 
610
                                $$.type_str = mm_strdup("timestamp");
 
611
                                $$.type_dimension = mm_strdup("-1");
 
612
                                $$.type_index = mm_strdup("-1");
 
613
                                $$.type_sizeof = NULL;
 
614
                        }
 
615
                        else if ((strcmp($1, "string") == 0) && INFORMIX_MODE)
 
616
                        {
 
617
                                $$.type_enum = ECPGt_string;
 
618
                                $$.type_str = mm_strdup("char");
 
619
                                $$.type_dimension = mm_strdup("-1");
 
620
                                $$.type_index = mm_strdup("-1");
 
621
                                $$.type_sizeof = NULL;
 
622
                        }
 
623
                        else
 
624
                        {
 
625
                                /* this is for typedef'ed types */
 
626
                                struct typedefs *this = get_typedef($1);
 
627
 
 
628
                                $$.type_str = (this->type->type_enum == ECPGt_varchar) ? EMPTY : mm_strdup(this->name);
 
629
                                $$.type_enum = this->type->type_enum;
 
630
                                $$.type_dimension = this->type->type_dimension;
 
631
                                $$.type_index = this->type->type_index;
 
632
                                if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0)
 
633
                                        $$.type_sizeof = this->type->type_sizeof;
 
634
                                else
 
635
                                        $$.type_sizeof = cat_str(3, mm_strdup("sizeof("), mm_strdup(this->name), mm_strdup(")"));
 
636
 
 
637
                                struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
 
638
                        }
 
639
                }
 
640
                | s_struct_union_symbol
 
641
                {
 
642
                        /* this is for named structs/unions */
 
643
                        char *name;
 
644
                        struct typedefs *this;
 
645
                        bool forward = (forward_name != NULL && strcmp($1.symbol, forward_name) == 0 && strcmp($1.su, "struct") == 0);
 
646
 
 
647
                        name = cat2_str($1.su, $1.symbol);
 
648
                        /* Do we have a forward definition? */
 
649
                        if (!forward)
 
650
                        {
 
651
                                /* No */
 
652
 
 
653
                                this = get_typedef(name);
 
654
                                $$.type_str = mm_strdup(this->name);
 
655
                                $$.type_enum = this->type->type_enum;
 
656
                                $$.type_dimension = this->type->type_dimension;
 
657
                                $$.type_index = this->type->type_index;
 
658
                                $$.type_sizeof = this->type->type_sizeof;
 
659
                                struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
 
660
                                free(name);
 
661
                        }
 
662
                        else
 
663
                        {
 
664
                                $$.type_str = name;
 
665
                                $$.type_enum = ECPGt_long;
 
666
                                $$.type_dimension = mm_strdup("-1");
 
667
                                $$.type_index = mm_strdup("-1");
 
668
                                $$.type_sizeof = mm_strdup("");
 
669
                                struct_member_list[struct_level] = NULL;
 
670
                        }
 
671
                }
 
672
                ;
 
673
 
 
674
enum_type: ENUM_P symbol enum_definition
 
675
                        { $$ = cat_str(3, mm_strdup("enum"), $2, $3); }
 
676
                | ENUM_P enum_definition
 
677
                        { $$ = cat2_str(mm_strdup("enum"), $2); }
 
678
                | ENUM_P symbol
 
679
                        { $$ = cat2_str(mm_strdup("enum"), $2); }
 
680
                ;
 
681
 
 
682
enum_definition: '{' c_list '}'
 
683
                        { $$ = cat_str(3, mm_strdup("{"), $2, mm_strdup("}")); };
 
684
 
 
685
struct_union_type_with_symbol: s_struct_union_symbol
 
686
                {
 
687
                        struct_member_list[struct_level++] = NULL;
 
688
                        if (struct_level >= STRUCT_DEPTH)
 
689
                                 mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition");
 
690
                        forward_name = mm_strdup($1.symbol);
 
691
                }
 
692
                '{' variable_declarations '}'
 
693
                {
 
694
                        struct typedefs *ptr, *this;
 
695
                        struct this_type su_type;
 
696
 
 
697
                        ECPGfree_struct_member(struct_member_list[struct_level]);
 
698
                        struct_member_list[struct_level] = NULL;
 
699
                        struct_level--;
 
700
                        if (strncmp($1.su, "struct", sizeof("struct")-1) == 0)
 
701
                                su_type.type_enum = ECPGt_struct;
 
702
                        else
 
703
                                su_type.type_enum = ECPGt_union;
 
704
                        su_type.type_str = cat2_str($1.su, $1.symbol);
 
705
                        free(forward_name);
 
706
                        forward_name = NULL;
 
707
 
 
708
                        /* This is essantially a typedef but needs the keyword struct/union as well.
 
709
                         * So we create the typedef for each struct definition with symbol */
 
710
                        for (ptr = types; ptr != NULL; ptr = ptr->next)
 
711
                        {
 
712
                                        if (strcmp(su_type.type_str, ptr->name) == 0)
 
713
                                                        /* re-definition is a bug */
 
714
                                                        mmerror(PARSE_ERROR, ET_ERROR, "type \"%s\" is already defined", su_type.type_str);
 
715
                        }
 
716
 
 
717
                        this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
 
718
 
 
719
                        /* initial definition */
 
720
                        this->next = types;
 
721
                        this->name = mm_strdup(su_type.type_str);
 
722
                        this->brace_level = braces_open;
 
723
                        this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
 
724
                        this->type->type_enum = su_type.type_enum;
 
725
                        this->type->type_str = mm_strdup(su_type.type_str);
 
726
                        this->type->type_dimension = mm_strdup("-1"); /* dimension of array */
 
727
                        this->type->type_index = mm_strdup("-1");       /* length of string */
 
728
                        this->type->type_sizeof = ECPGstruct_sizeof;
 
729
                        this->struct_member_list = struct_member_list[struct_level];
 
730
 
 
731
                        types = this;
 
732
                        $$ = cat_str(4, su_type.type_str, mm_strdup("{"), $4, mm_strdup("}"));
 
733
                }
 
734
                ;
 
735
 
 
736
struct_union_type: struct_union_type_with_symbol        { $$ = $1; }
 
737
                | s_struct_union
 
738
                {
 
739
                        struct_member_list[struct_level++] = NULL;
 
740
                        if (struct_level >= STRUCT_DEPTH)
 
741
                                 mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition");
 
742
                }
 
743
                '{' variable_declarations '}'
 
744
                {
 
745
                        ECPGfree_struct_member(struct_member_list[struct_level]);
 
746
                        struct_member_list[struct_level] = NULL;
 
747
                        struct_level--;
 
748
                        $$ = cat_str(4, $1, mm_strdup("{"), $4, mm_strdup("}"));
 
749
                }
 
750
                ;
 
751
 
 
752
s_struct_union_symbol: SQL_STRUCT symbol
 
753
                {
 
754
                        $$.su = mm_strdup("struct");
 
755
                        $$.symbol = $2;
 
756
                        ECPGstruct_sizeof = cat_str(3, mm_strdup("sizeof("), cat2_str(mm_strdup($$.su), mm_strdup($$.symbol)), mm_strdup(")"));
 
757
                }
 
758
                | UNION symbol
 
759
                {
 
760
                        $$.su = mm_strdup("union");
 
761
                        $$.symbol = $2;
 
762
                }
 
763
                ;
 
764
 
 
765
s_struct_union: SQL_STRUCT
 
766
                {
 
767
                        ECPGstruct_sizeof = mm_strdup(""); /* This must not be NULL to distinguish from simple types. */
 
768
                        $$ = mm_strdup("struct");
 
769
                }
 
770
                | UNION         { $$ = mm_strdup("union"); }
 
771
                ;
 
772
 
 
773
simple_type: unsigned_type                                      { $$=$1; }
 
774
                |       opt_signed signed_type                  { $$=$2; }
 
775
                ;
 
776
 
 
777
unsigned_type: SQL_UNSIGNED SQL_SHORT           { $$ = ECPGt_unsigned_short; }
 
778
                | SQL_UNSIGNED SQL_SHORT INT_P  { $$ = ECPGt_unsigned_short; }
 
779
                | SQL_UNSIGNED                                          { $$ = ECPGt_unsigned_int; }
 
780
                | SQL_UNSIGNED INT_P                            { $$ = ECPGt_unsigned_int; }
 
781
                | SQL_UNSIGNED SQL_LONG                         { $$ = ECPGt_unsigned_long; }
 
782
                | SQL_UNSIGNED SQL_LONG INT_P           { $$ = ECPGt_unsigned_long; }
 
783
                | SQL_UNSIGNED SQL_LONG SQL_LONG
 
784
                {
 
785
#ifdef HAVE_LONG_LONG_INT
 
786
                        $$ = ECPGt_unsigned_long_long;
 
787
#else
 
788
                        $$ = ECPGt_unsigned_long;
 
789
#endif
 
790
                }
 
791
                | SQL_UNSIGNED SQL_LONG SQL_LONG INT_P
 
792
                {
 
793
#ifdef HAVE_LONG_LONG_INT
 
794
                        $$ = ECPGt_unsigned_long_long;
 
795
#else
 
796
                        $$ = ECPGt_unsigned_long;
 
797
#endif
 
798
                }
 
799
                | SQL_UNSIGNED CHAR_P                   { $$ = ECPGt_unsigned_char; }
 
800
                ;
 
801
 
 
802
signed_type: SQL_SHORT                          { $$ = ECPGt_short; }
 
803
                | SQL_SHORT INT_P                       { $$ = ECPGt_short; }
 
804
                | INT_P                                         { $$ = ECPGt_int; }
 
805
                | SQL_LONG                                      { $$ = ECPGt_long; }
 
806
                | SQL_LONG INT_P                        { $$ = ECPGt_long; }
 
807
                | SQL_LONG SQL_LONG
 
808
                {
 
809
#ifdef HAVE_LONG_LONG_INT
 
810
                        $$ = ECPGt_long_long;
 
811
#else
 
812
                        $$ = ECPGt_long;
 
813
#endif
 
814
                }
 
815
                | SQL_LONG SQL_LONG INT_P
 
816
                {
 
817
#ifdef HAVE_LONG_LONG_INT
 
818
                        $$ = ECPGt_long_long;
 
819
#else
 
820
                        $$ = ECPGt_long;
 
821
#endif
 
822
                }
 
823
                | SQL_BOOL                                      { $$ = ECPGt_bool; }
 
824
                | CHAR_P                                        { $$ = ECPGt_char; }
 
825
                | DOUBLE_P                                      { $$ = ECPGt_double; }
 
826
                ;
 
827
 
 
828
opt_signed: SQL_SIGNED
 
829
                |       /* EMPTY */
 
830
                ;
 
831
 
 
832
variable_list: variable
 
833
                        { $$ = $1; }
 
834
                | variable_list ',' variable
 
835
                        { $$ = cat_str(3, $1, mm_strdup(","), $3); }
 
836
                ;
 
837
 
 
838
variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initializer
 
839
                {
 
840
                        struct ECPGtype * type;
 
841
                        char *dimension = $3.index1; /* dimension of array */
 
842
                        char *length = $3.index2;    /* length of string */
 
843
                        char *dim_str;
 
844
                        char *vcn;
 
845
 
 
846
                        adjust_array(actual_type[struct_level].type_enum, &dimension, &length, actual_type[struct_level].type_dimension, actual_type[struct_level].type_index, strlen($1), false);
 
847
 
 
848
                        switch (actual_type[struct_level].type_enum)
 
849
                        {
 
850
                                case ECPGt_struct:
 
851
                                case ECPGt_union:
 
852
                                        if (atoi(dimension) < 0)
 
853
                                                type = ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_str, actual_type[struct_level].type_sizeof);
 
854
                                        else
 
855
                                                type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_str, actual_type[struct_level].type_sizeof), dimension);
 
856
 
 
857
                                        $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5);
 
858
                                        break;
 
859
 
 
860
                                case ECPGt_varchar:
 
861
                                        if (atoi(dimension) < 0)
 
862
                                                type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, varchar_counter);
 
863
                                        else
 
864
                                                type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, varchar_counter), dimension);
 
865
 
 
866
                                        if (strcmp(dimension, "0") == 0 || abs(atoi(dimension)) == 1)
 
867
                                                        dim_str=mm_strdup("");
 
868
                                        else
 
869
                                                        dim_str=cat_str(3, mm_strdup("["), mm_strdup(dimension), mm_strdup("]"));
 
870
                                        /* cannot check for atoi <= 0 because a defined constant will yield 0 here as well */
 
871
                                        if (atoi(length) < 0 || strcmp(length, "0") == 0)
 
872
                                                mmerror(PARSE_ERROR, ET_ERROR, "pointers to varchar are not implemented");
 
873
 
 
874
                                        /* make sure varchar struct name is unique by adding a unique counter to its definition */
 
875
                                        vcn = (char *) mm_alloc(strlen($2) + sizeof(int) * CHAR_BIT * 10 / 3);
 
876
                                        sprintf(vcn, "%s_%d", $2, varchar_counter);
 
877
                                        if (strcmp(dimension, "0") == 0)
 
878
                                                $$ = cat_str(7, make2_str(mm_strdup(" struct varchar_"), vcn), mm_strdup(" { int len; char arr["), mm_strdup(length), mm_strdup("]; } *"), mm_strdup($2), $4, $5);
 
879
                                        else
 
880
                                                $$ = cat_str(8, make2_str(mm_strdup(" struct varchar_"), vcn), mm_strdup(" { int len; char arr["), mm_strdup(length), mm_strdup("]; } "), mm_strdup($2), dim_str, $4, $5);
 
881
                                        varchar_counter++;
 
882
                                        break;
 
883
 
 
884
                                case ECPGt_char:
 
885
                                case ECPGt_unsigned_char:
 
886
                                case ECPGt_string:
 
887
                                        if (atoi(dimension) == -1)
 
888
                                        {
 
889
                                                int i = strlen($5);
 
890
 
 
891
                                                if (atoi(length) == -1 && i > 0) /* char <var>[] = "string" */
 
892
                                                {
 
893
                                                        /* if we have an initializer but no string size set, let's use the initializer's length */
 
894
                                                        free(length);
 
895
                                                        length = mm_alloc(i+sizeof("sizeof()"));
 
896
                                                        sprintf(length, "sizeof(%s)", $5+2);
 
897
                                                }
 
898
                                                type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0);
 
899
                                        }
 
900
                                        else
 
901
                                                type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0), dimension);
 
902
 
 
903
                                        $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5);
 
904
                                        break;
 
905
 
 
906
                                default:
 
907
                                        if (atoi(dimension) < 0)
 
908
                                                type = ECPGmake_simple_type(actual_type[struct_level].type_enum, mm_strdup("1"), 0);
 
909
                                        else
 
910
                                                type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, mm_strdup("1"), 0), dimension);
 
911
 
 
912
                                        $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5);
 
913
                                        break;
 
914
                        }
 
915
 
 
916
                        if (struct_level == 0)
 
917
                                new_variable($2, type, braces_open);
 
918
                        else
 
919
                                ECPGmake_struct_member($2, type, &(struct_member_list[struct_level - 1]));
 
920
 
 
921
                        free($2);
 
922
                }
 
923
                ;
 
924
 
 
925
opt_initializer: /*EMPTY*/
 
926
                        { $$ = EMPTY; }
 
927
                | '=' c_term
 
928
                {
 
929
                        initializer = 1;
 
930
                        $$ = cat2_str(mm_strdup("="), $2);
 
931
                }
 
932
                ;
 
933
 
 
934
opt_pointer: /*EMPTY*/                          { $$ = EMPTY; }
 
935
                | '*'                                           { $$ = mm_strdup("*"); }
 
936
                | '*' '*'                                       { $$ = mm_strdup("**"); }
 
937
                ;
 
938
 
 
939
/*
 
940
 * We try to simulate the correct DECLARE syntax here so we get dynamic SQL
 
941
 */
 
942
ECPGDeclare: DECLARE STATEMENT ecpg_ident
 
943
                {
 
944
                        /* this is only supported for compatibility */
 
945
                        $$ = cat_str(3, mm_strdup("/* declare statement"), $3, mm_strdup("*/"));
 
946
                }
 
947
                ;
 
948
/*
 
949
 * the exec sql disconnect statement: disconnect from the given database
 
950
 */
 
951
ECPGDisconnect: SQL_DISCONNECT dis_name { $$ = $2; }
 
952
                ;
 
953
 
 
954
dis_name: connection_object                     { $$ = $1; }
 
955
                | CURRENT_P                     { $$ = mm_strdup("\"CURRENT\""); }
 
956
                | ALL                           { $$ = mm_strdup("\"ALL\""); }
 
957
                | /* EMPTY */                   { $$ = mm_strdup("\"CURRENT\""); }
 
958
                ;
 
959
 
 
960
connection_object: database_name                { $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\"")); }
 
961
                | DEFAULT                       { $$ = mm_strdup("\"DEFAULT\""); }
 
962
                | char_variable                 { $$ = $1; }
 
963
                ;
 
964
 
 
965
execstring: char_variable
 
966
                        { $$ = $1; }
 
967
                |       CSTRING
 
968
                        { $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\"")); }
 
969
                ;
 
970
 
 
971
/*
 
972
 * the exec sql free command to deallocate a previously
 
973
 * prepared statement
 
974
 */
 
975
ECPGFree:       SQL_FREE cursor_name    { $$ = $2; }
 
976
                | SQL_FREE ALL  { $$ = mm_strdup("all"); }
 
977
                ;
 
978
 
 
979
/*
 
980
 * open is an open cursor, at the moment this has to be removed
 
981
 */
 
982
ECPGOpen: SQL_OPEN cursor_name opt_ecpg_using
 
983
                {
 
984
                        if ($2[0] == ':')
 
985
                                remove_variable_from_list(&argsinsert, find_variable($2 + 1));
 
986
                        $$ = $2;
 
987
                }
 
988
                ;
 
989
 
 
990
opt_ecpg_using: /*EMPTY*/       { $$ = EMPTY; }
 
991
                | ecpg_using            { $$ = $1; }
 
992
                ;
 
993
 
 
994
ecpg_using:     USING using_list        { $$ = EMPTY; }
 
995
                | using_descriptor      { $$ = $1; }
 
996
                ;
 
997
 
 
998
using_descriptor: USING SQL_SQL SQL_DESCRIPTOR quoted_ident_stringvar
 
999
                {
 
1000
                        add_variable_to_head(&argsinsert, descriptor_variable($4,0), &no_indicator);
 
1001
                        $$ = EMPTY;
 
1002
                }
 
1003
                | USING SQL_DESCRIPTOR name
 
1004
                {
 
1005
                        add_variable_to_head(&argsinsert, sqlda_variable($3), &no_indicator);
 
1006
                        $$ = EMPTY;
 
1007
                }
 
1008
                ;
 
1009
 
 
1010
into_descriptor: INTO SQL_SQL SQL_DESCRIPTOR quoted_ident_stringvar
 
1011
                {
 
1012
                        add_variable_to_head(&argsresult, descriptor_variable($4,1), &no_indicator);
 
1013
                        $$ = EMPTY;
 
1014
                }
 
1015
                | INTO SQL_DESCRIPTOR name
 
1016
                {
 
1017
                        add_variable_to_head(&argsresult, sqlda_variable($3), &no_indicator);
 
1018
                        $$ = EMPTY;
 
1019
                }
 
1020
                ;
 
1021
 
 
1022
into_sqlda: INTO name
 
1023
                {
 
1024
                        add_variable_to_head(&argsresult, sqlda_variable($2), &no_indicator);
 
1025
                        $$ = EMPTY;
 
1026
                }
 
1027
                ;
 
1028
 
 
1029
using_list: UsingValue | UsingValue ',' using_list;
 
1030
 
 
1031
UsingValue: UsingConst
 
1032
                {
 
1033
                        char *length = mm_alloc(32);
 
1034
 
 
1035
                        sprintf(length, "%d", (int) strlen($1));
 
1036
                        add_variable_to_head(&argsinsert, new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0), &no_indicator);
 
1037
                }
 
1038
                | civar { $$ = EMPTY; }
 
1039
                | civarind { $$ = EMPTY; }
 
1040
                ;
 
1041
 
 
1042
UsingConst: Iconst                      { $$ = $1; }
 
1043
                | '+' Iconst            { $$ = cat_str(2, mm_strdup("+"), $2); }
 
1044
                | '-' Iconst            { $$ = cat_str(2, mm_strdup("-"), $2); }
 
1045
                | ecpg_fconst           { $$ = $1; }
 
1046
                | '+' ecpg_fconst       { $$ = cat_str(2, mm_strdup("+"), $2); }
 
1047
                | '-' ecpg_fconst       { $$ = cat_str(2, mm_strdup("-"), $2); }
 
1048
                | ecpg_sconst           { $$ = $1; }
 
1049
                | ecpg_bconst           { $$ = $1; }
 
1050
                | ecpg_xconst           { $$ = $1; }
 
1051
                ;
 
1052
 
 
1053
/*
 
1054
 * We accept DESCRIBE [OUTPUT] but do nothing with DESCRIBE INPUT so far.
 
1055
 */
 
1056
ECPGDescribe: SQL_DESCRIBE INPUT_P prepared_name using_descriptor
 
1057
        {
 
1058
                const char *con = connection ? connection : "NULL";
 
1059
                mmerror(PARSE_ERROR, ET_WARNING, "using unsupported DESCRIBE statement");
 
1060
                $$ = (char *) mm_alloc(sizeof("1, , ") + strlen(con) + strlen($3));
 
1061
                sprintf($$, "1, %s, %s", con, $3);
 
1062
        }
 
1063
        | SQL_DESCRIBE opt_output prepared_name using_descriptor
 
1064
        {
 
1065
                const char *con = connection ? connection : "NULL";
 
1066
                struct variable *var;
 
1067
 
 
1068
                var = argsinsert->variable;
 
1069
                remove_variable_from_list(&argsinsert, var);
 
1070
                add_variable_to_head(&argsresult, var, &no_indicator);
 
1071
 
 
1072
                $$ = (char *) mm_alloc(sizeof("0, , ") + strlen(con) + strlen($3));
 
1073
                sprintf($$, "0, %s, %s", con, $3);
 
1074
        }
 
1075
        | SQL_DESCRIBE opt_output prepared_name into_descriptor
 
1076
        {
 
1077
                const char *con = connection ? connection : "NULL";
 
1078
                $$ = (char *) mm_alloc(sizeof("0, , ") + strlen(con) + strlen($3));
 
1079
                sprintf($$, "0, %s, %s", con, $3);
 
1080
        }
 
1081
        | SQL_DESCRIBE INPUT_P prepared_name into_sqlda
 
1082
        {
 
1083
                const char *con = connection ? connection : "NULL";
 
1084
                mmerror(PARSE_ERROR, ET_WARNING, "using unsupported DESCRIBE statement");
 
1085
                $$ = (char *) mm_alloc(sizeof("1, , ") + strlen(con) + strlen($3));
 
1086
                sprintf($$, "1, %s, %s", con, $3);
 
1087
        }
 
1088
        | SQL_DESCRIBE opt_output prepared_name into_sqlda
 
1089
        {
 
1090
                const char *con = connection ? connection : "NULL";
 
1091
                $$ = (char *) mm_alloc(sizeof("0, , ") + strlen(con) + strlen($3));
 
1092
                sprintf($$, "0, %s, %s", con, $3);
 
1093
        }
 
1094
        ;
 
1095
 
 
1096
opt_output:     SQL_OUTPUT      { $$ = mm_strdup("output"); }
 
1097
        |       /* EMPTY */     { $$ = EMPTY; }
 
1098
        ;
 
1099
 
 
1100
/*
 
1101
 * dynamic SQL: descriptor based access
 
1102
 *      originall written by Christof Petig <christof.petig@wtal.de>
 
1103
 *                      and Peter Eisentraut <peter.eisentraut@credativ.de>
 
1104
 */
 
1105
 
 
1106
/*
 
1107
 * allocate a descriptor
 
1108
 */
 
1109
ECPGAllocateDescr:     SQL_ALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
 
1110
                {
 
1111
                        add_descriptor($3,connection);
 
1112
                        $$ = $3;
 
1113
                }
 
1114
                ;
 
1115
 
 
1116
 
 
1117
/*
 
1118
 * deallocate a descriptor
 
1119
 */
 
1120
ECPGDeallocateDescr:    DEALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
 
1121
                {
 
1122
                        drop_descriptor($3,connection);
 
1123
                        $$ = $3;
 
1124
                }
 
1125
                ;
 
1126
 
 
1127
/*
 
1128
 * manipulate a descriptor header
 
1129
 */
 
1130
 
 
1131
ECPGGetDescriptorHeader: SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar ECPGGetDescHeaderItems
 
1132
                        {  $$ = $3; }
 
1133
                ;
 
1134
 
 
1135
ECPGGetDescHeaderItems: ECPGGetDescHeaderItem
 
1136
                | ECPGGetDescHeaderItems ',' ECPGGetDescHeaderItem
 
1137
                ;
 
1138
 
 
1139
ECPGGetDescHeaderItem: cvariable '=' desc_header_item
 
1140
                        { push_assignment($1, $3); }
 
1141
                ;
 
1142
 
 
1143
 
 
1144
ECPGSetDescriptorHeader: SET SQL_DESCRIPTOR quoted_ident_stringvar ECPGSetDescHeaderItems
 
1145
                        { $$ = $3; }
 
1146
                ;
 
1147
 
 
1148
ECPGSetDescHeaderItems: ECPGSetDescHeaderItem
 
1149
                | ECPGSetDescHeaderItems ',' ECPGSetDescHeaderItem
 
1150
                ;
 
1151
 
 
1152
ECPGSetDescHeaderItem: desc_header_item '=' IntConstVar
 
1153
                {
 
1154
                        push_assignment($3, $1);
 
1155
                }
 
1156
                ;
 
1157
 
 
1158
IntConstVar:    Iconst
 
1159
                {
 
1160
                        char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
 
1161
 
 
1162
                        sprintf(length, "%d", (int) strlen($1));
 
1163
                        new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
 
1164
                        $$ = $1;
 
1165
                }
 
1166
                | cvariable     { $$ = $1; }
 
1167
                ;
 
1168
 
 
1169
desc_header_item:       SQL_COUNT                       { $$ = ECPGd_count; }
 
1170
                ;
 
1171
 
 
1172
/*
 
1173
 * manipulate a descriptor
 
1174
 */
 
1175
 
 
1176
ECPGGetDescriptor:      SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGGetDescItems
 
1177
                        {  $$.str = $5; $$.name = $3; }
 
1178
                ;
 
1179
 
 
1180
ECPGGetDescItems: ECPGGetDescItem
 
1181
                | ECPGGetDescItems ',' ECPGGetDescItem
 
1182
                ;
 
1183
 
 
1184
ECPGGetDescItem: cvariable '=' descriptor_item  { push_assignment($1, $3); };
 
1185
 
 
1186
 
 
1187
ECPGSetDescriptor:      SET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGSetDescItems
 
1188
                        {  $$.str = $5; $$.name = $3; }
 
1189
                ;
 
1190
 
 
1191
ECPGSetDescItems: ECPGSetDescItem
 
1192
                | ECPGSetDescItems ',' ECPGSetDescItem
 
1193
                ;
 
1194
 
 
1195
ECPGSetDescItem: descriptor_item '=' AllConstVar
 
1196
                {
 
1197
                        push_assignment($3, $1);
 
1198
                }
 
1199
                ;
 
1200
 
 
1201
AllConstVar:    ecpg_fconst
 
1202
                {
 
1203
                        char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
 
1204
 
 
1205
                        sprintf(length, "%d", (int) strlen($1));
 
1206
                        new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
 
1207
                        $$ = $1;
 
1208
                }
 
1209
                | IntConstVar           { $$ = $1; }
 
1210
                | '-' ecpg_fconst
 
1211
                {
 
1212
                        char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
 
1213
                        char *var = cat2_str(mm_strdup("-"), $2);
 
1214
 
 
1215
                        sprintf(length, "%d", (int) strlen(var));
 
1216
                        new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
 
1217
                        $$ = var;
 
1218
                }
 
1219
                | '-' Iconst
 
1220
                {
 
1221
                        char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
 
1222
                        char *var = cat2_str(mm_strdup("-"), $2);
 
1223
 
 
1224
                        sprintf(length, "%d", (int) strlen(var));
 
1225
                        new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
 
1226
                        $$ = var;
 
1227
                }
 
1228
                | ecpg_sconst
 
1229
                {
 
1230
                        char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
 
1231
                        char *var = $1 + 1;
 
1232
 
 
1233
                        var[strlen(var) - 1] = '\0';
 
1234
                        sprintf(length, "%d", (int) strlen(var));
 
1235
                        new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
 
1236
                        $$ = var;
 
1237
                }
 
1238
                ;
 
1239
 
 
1240
descriptor_item:        SQL_CARDINALITY                 { $$ = ECPGd_cardinality; }
 
1241
                | DATA_P                                { $$ = ECPGd_data; }
 
1242
                | SQL_DATETIME_INTERVAL_CODE            { $$ = ECPGd_di_code; }
 
1243
                | SQL_DATETIME_INTERVAL_PRECISION       { $$ = ECPGd_di_precision; }
 
1244
                | SQL_INDICATOR                         { $$ = ECPGd_indicator; }
 
1245
                | SQL_KEY_MEMBER                        { $$ = ECPGd_key_member; }
 
1246
                | SQL_LENGTH                            { $$ = ECPGd_length; }
 
1247
                | NAME_P                                { $$ = ECPGd_name; }
 
1248
                | SQL_NULLABLE                          { $$ = ECPGd_nullable; }
 
1249
                | SQL_OCTET_LENGTH                      { $$ = ECPGd_octet; }
 
1250
                | PRECISION                             { $$ = ECPGd_precision; }
 
1251
                | SQL_RETURNED_LENGTH                   { $$ = ECPGd_length; }
 
1252
                | SQL_RETURNED_OCTET_LENGTH             { $$ = ECPGd_ret_octet; }
 
1253
                | SQL_SCALE                             { $$ = ECPGd_scale; }
 
1254
                | TYPE_P                                { $$ = ECPGd_type; }
 
1255
                ;
 
1256
 
 
1257
/*
 
1258
 * set/reset the automatic transaction mode, this needs a differnet handling
 
1259
 * as the other set commands
 
1260
 */
 
1261
ECPGSetAutocommit:      SET SQL_AUTOCOMMIT '=' on_off   { $$ = $4; }
 
1262
                |  SET SQL_AUTOCOMMIT TO on_off   { $$ = $4; }
 
1263
                ;
 
1264
 
 
1265
on_off: ON                              { $$ = mm_strdup("on"); }
 
1266
                | OFF                   { $$ = mm_strdup("off"); }
 
1267
                ;
 
1268
 
 
1269
/*
 
1270
 * set the actual connection, this needs a differnet handling as the other
 
1271
 * set commands
 
1272
 */
 
1273
ECPGSetConnection:      SET CONNECTION TO connection_object { $$ = $4; }
 
1274
                | SET CONNECTION '=' connection_object { $$ = $4; }
 
1275
                | SET CONNECTION  connection_object { $$ = $3; }
 
1276
                ;
 
1277
 
 
1278
/*
 
1279
 * define a new type for embedded SQL
 
1280
 */
 
1281
ECPGTypedef: TYPE_P
 
1282
                {
 
1283
                        /* reset this variable so we see if there was */
 
1284
                        /* an initializer specified */
 
1285
                        initializer = 0;
 
1286
                }
 
1287
                ECPGColLabelCommon IS var_type opt_array_bounds opt_reference
 
1288
                {
 
1289
                        add_typedef($3, $6.index1, $6.index2, $5.type_enum, $5.type_dimension, $5.type_index, initializer, *$7 ? 1 : 0);
 
1290
 
 
1291
                        if (auto_create_c == false)
 
1292
                                $$ = cat_str(7, mm_strdup("/* exec sql type"), mm_strdup($3), mm_strdup("is"), mm_strdup($5.type_str), mm_strdup($6.str), $7, mm_strdup("*/"));
 
1293
                        else
 
1294
                                $$ = cat_str(6, mm_strdup("typedef "), mm_strdup($5.type_str), *$7?mm_strdup("*"):mm_strdup(""), mm_strdup($6.str), mm_strdup($3), mm_strdup(";"));
 
1295
                }
 
1296
                ;
 
1297
 
 
1298
opt_reference: SQL_REFERENCE            { $$ = mm_strdup("reference"); }
 
1299
                | /*EMPTY*/                                     { $$ = EMPTY; }
 
1300
                ;
 
1301
 
 
1302
/*
 
1303
 * define the type of one variable for embedded SQL
 
1304
 */
 
1305
ECPGVar: SQL_VAR
 
1306
                {
 
1307
                        /* reset this variable so we see if there was */
 
1308
                        /* an initializer specified */
 
1309
                        initializer = 0;
 
1310
                }
 
1311
                ColLabel IS var_type opt_array_bounds opt_reference
 
1312
                {
 
1313
                        struct variable *p = find_variable($3);
 
1314
                        char *dimension = $6.index1;
 
1315
                        char *length = $6.index2;
 
1316
                        struct ECPGtype * type;
 
1317
 
 
1318
                        if (($5.type_enum == ECPGt_struct ||
 
1319
                                 $5.type_enum == ECPGt_union) &&
 
1320
                                initializer == 1)
 
1321
                                mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in EXEC SQL VAR command");
 
1322
                        else
 
1323
                        {
 
1324
                                adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7?1:0, false);
 
1325
 
 
1326
                                switch ($5.type_enum)
 
1327
                                {
 
1328
                                        case ECPGt_struct:
 
1329
                                        case ECPGt_union:
 
1330
                                                if (atoi(dimension) < 0)
 
1331
                                                        type = ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, $5.type_str, $5.type_sizeof);
 
1332
                                                else
 
1333
                                                        type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, $5.type_str, $5.type_sizeof), dimension);
 
1334
                                                break;
 
1335
 
 
1336
                                        case ECPGt_varchar:
 
1337
                                                if (atoi(dimension) == -1)
 
1338
                                                        type = ECPGmake_simple_type($5.type_enum, length, 0);
 
1339
                                                else
 
1340
                                                        type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length, 0), dimension);
 
1341
                                                break;
 
1342
 
 
1343
                                        case ECPGt_char:
 
1344
                                        case ECPGt_unsigned_char:
 
1345
                                        case ECPGt_string:
 
1346
                                                if (atoi(dimension) == -1)
 
1347
                                                        type = ECPGmake_simple_type($5.type_enum, length, 0);
 
1348
                                                else
 
1349
                                                        type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length, 0), dimension);
 
1350
                                                break;
 
1351
 
 
1352
                                        default:
 
1353
                                                if (atoi(length) >= 0)
 
1354
                                                        mmerror(PARSE_ERROR, ET_ERROR, "multidimensional arrays for simple data types are not supported");
 
1355
 
 
1356
                                                if (atoi(dimension) < 0)
 
1357
                                                        type = ECPGmake_simple_type($5.type_enum, mm_strdup("1"), 0);
 
1358
                                                else
 
1359
                                                        type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, mm_strdup("1"), 0), dimension);
 
1360
                                                break;
 
1361
                                }
 
1362
 
 
1363
                                ECPGfree_type(p->type);
 
1364
                                p->type = type;
 
1365
                        }
 
1366
 
 
1367
                        $$ = cat_str(7, mm_strdup("/* exec sql var"), mm_strdup($3), mm_strdup("is"), mm_strdup($5.type_str), mm_strdup($6.str), $7, mm_strdup("*/"));
 
1368
                }
 
1369
                ;
 
1370
 
 
1371
/*
 
1372
 * whenever statement: decide what to do in case of error/no data found
 
1373
 * according to SQL standards we lack: SQLSTATE, CONSTRAINT and SQLEXCEPTION
 
1374
 */
 
1375
ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action
 
1376
                {
 
1377
                        when_error.code = $<action>3.code;
 
1378
                        when_error.command = $<action>3.command;
 
1379
                        $$ = cat_str(3, mm_strdup("/* exec sql whenever sqlerror "), $3.str, mm_strdup("; */"));
 
1380
                }
 
1381
                | SQL_WHENEVER NOT SQL_FOUND action
 
1382
                {
 
1383
                        when_nf.code = $<action>4.code;
 
1384
                        when_nf.command = $<action>4.command;
 
1385
                        $$ = cat_str(3, mm_strdup("/* exec sql whenever not found "), $4.str, mm_strdup("; */"));
 
1386
                }
 
1387
                | SQL_WHENEVER SQL_SQLWARNING action
 
1388
                {
 
1389
                        when_warn.code = $<action>3.code;
 
1390
                        when_warn.command = $<action>3.command;
 
1391
                        $$ = cat_str(3, mm_strdup("/* exec sql whenever sql_warning "), $3.str, mm_strdup("; */"));
 
1392
                }
 
1393
                ;
 
1394
 
 
1395
action : CONTINUE_P
 
1396
                {
 
1397
                        $<action>$.code = W_NOTHING;
 
1398
                        $<action>$.command = NULL;
 
1399
                        $<action>$.str = mm_strdup("continue");
 
1400
                }
 
1401
                | SQL_SQLPRINT
 
1402
                {
 
1403
                        $<action>$.code = W_SQLPRINT;
 
1404
                        $<action>$.command = NULL;
 
1405
                        $<action>$.str = mm_strdup("sqlprint");
 
1406
                }
 
1407
                | SQL_STOP
 
1408
                {
 
1409
                        $<action>$.code = W_STOP;
 
1410
                        $<action>$.command = NULL;
 
1411
                        $<action>$.str = mm_strdup("stop");
 
1412
                }
 
1413
                | SQL_GOTO name
 
1414
                {
 
1415
                        $<action>$.code = W_GOTO;
 
1416
                        $<action>$.command = strdup($2);
 
1417
                        $<action>$.str = cat2_str(mm_strdup("goto "), $2);
 
1418
                }
 
1419
                | SQL_GO TO name
 
1420
                {
 
1421
                        $<action>$.code = W_GOTO;
 
1422
                        $<action>$.command = strdup($3);
 
1423
                        $<action>$.str = cat2_str(mm_strdup("goto "), $3);
 
1424
                }
 
1425
                | DO name '(' c_args ')'
 
1426
                {
 
1427
                        $<action>$.code = W_DO;
 
1428
                        $<action>$.command = cat_str(4, $2, mm_strdup("("), $4, mm_strdup(")"));
 
1429
                        $<action>$.str = cat2_str(mm_strdup("do"), mm_strdup($<action>$.command));
 
1430
                }
 
1431
                | DO SQL_BREAK
 
1432
                {
 
1433
                        $<action>$.code = W_BREAK;
 
1434
                        $<action>$.command = NULL;
 
1435
                        $<action>$.str = mm_strdup("break");
 
1436
                }
 
1437
                | SQL_CALL name '(' c_args ')'
 
1438
                {
 
1439
                        $<action>$.code = W_DO;
 
1440
                        $<action>$.command = cat_str(4, $2, mm_strdup("("), $4, mm_strdup(")"));
 
1441
                        $<action>$.str = cat2_str(mm_strdup("call"), mm_strdup($<action>$.command));
 
1442
                }
 
1443
                | SQL_CALL name
 
1444
                {
 
1445
                        $<action>$.code = W_DO;
 
1446
                        $<action>$.command = cat2_str($2, mm_strdup("()"));
 
1447
                        $<action>$.str = cat2_str(mm_strdup("call"), mm_strdup($<action>$.command));
 
1448
                }
 
1449
                ;
 
1450
 
 
1451
/* some other stuff for ecpg */
 
1452
 
 
1453
/* additional unreserved keywords */
 
1454
ECPGKeywords: ECPGKeywords_vanames      { $$ = $1; }
 
1455
                | ECPGKeywords_rest     { $$ = $1; }
 
1456
                ;
 
1457
 
 
1458
ECPGKeywords_vanames:  SQL_BREAK                { $$ = mm_strdup("break"); }
 
1459
                | SQL_CALL                                              { $$ = mm_strdup("call"); }
 
1460
                | SQL_CARDINALITY                               { $$ = mm_strdup("cardinality"); }
 
1461
                | SQL_COUNT                                             { $$ = mm_strdup("count"); }
 
1462
                | SQL_DATETIME_INTERVAL_CODE    { $$ = mm_strdup("datetime_interval_code"); }
 
1463
                | SQL_DATETIME_INTERVAL_PRECISION       { $$ = mm_strdup("datetime_interval_precision"); }
 
1464
                | SQL_FOUND                                             { $$ = mm_strdup("found"); }
 
1465
                | SQL_GO                                                { $$ = mm_strdup("go"); }
 
1466
                | SQL_GOTO                                              { $$ = mm_strdup("goto"); }
 
1467
                | SQL_IDENTIFIED                                { $$ = mm_strdup("identified"); }
 
1468
                | SQL_INDICATOR                         { $$ = mm_strdup("indicator"); }
 
1469
                | SQL_KEY_MEMBER                        { $$ = mm_strdup("key_member"); }
 
1470
                | SQL_LENGTH                            { $$ = mm_strdup("length"); }
 
1471
                | SQL_NULLABLE                          { $$ = mm_strdup("nullable"); }
 
1472
                | SQL_OCTET_LENGTH                      { $$ = mm_strdup("octet_length"); }
 
1473
                | SQL_RETURNED_LENGTH           { $$ = mm_strdup("returned_length"); }
 
1474
                | SQL_RETURNED_OCTET_LENGTH     { $$ = mm_strdup("returned_octet_length"); }
 
1475
                | SQL_SCALE                                     { $$ = mm_strdup("scale"); }
 
1476
                | SQL_SECTION                           { $$ = mm_strdup("section"); }
 
1477
                | SQL_SQL                               { $$ = mm_strdup("sql"); }
 
1478
                | SQL_SQLERROR                          { $$ = mm_strdup("sqlerror"); }
 
1479
                | SQL_SQLPRINT                          { $$ = mm_strdup("sqlprint"); }
 
1480
                | SQL_SQLWARNING                        { $$ = mm_strdup("sqlwarning"); }
 
1481
                | SQL_STOP                                      { $$ = mm_strdup("stop"); }
 
1482
                ;
 
1483
 
 
1484
ECPGKeywords_rest:  SQL_CONNECT         { $$ = mm_strdup("connect"); }
 
1485
                | SQL_DESCRIBE                          { $$ = mm_strdup("describe"); }
 
1486
                | SQL_DISCONNECT                        { $$ = mm_strdup("disconnect"); }
 
1487
                | SQL_OPEN                                      { $$ = mm_strdup("open"); }
 
1488
                | SQL_VAR                                       { $$ = mm_strdup("var"); }
 
1489
                | SQL_WHENEVER                          { $$ = mm_strdup("whenever"); }
 
1490
                ;
 
1491
 
 
1492
/* additional keywords that can be SQL type names (but not ECPGColLabels) */
 
1493
ECPGTypeName:  SQL_BOOL                         { $$ = mm_strdup("bool"); }
 
1494
                | SQL_LONG                                      { $$ = mm_strdup("long"); }
 
1495
                | SQL_OUTPUT                            { $$ = mm_strdup("output"); }
 
1496
                | SQL_SHORT                                     { $$ = mm_strdup("short"); }
 
1497
                | SQL_STRUCT                            { $$ = mm_strdup("struct"); }
 
1498
                | SQL_SIGNED                            { $$ = mm_strdup("signed"); }
 
1499
                | SQL_UNSIGNED                          { $$ = mm_strdup("unsigned"); }
 
1500
                ;
 
1501
 
 
1502
symbol: ColLabel                                        { $$ = $1; }
 
1503
                ;
 
1504
 
 
1505
ECPGColId: ecpg_ident                           { $$ = $1; }
 
1506
                | unreserved_keyword            { $$ = $1; }
 
1507
                | col_name_keyword                      { $$ = $1; }
 
1508
                | ECPGunreserved_interval       { $$ = $1; }
 
1509
                | ECPGKeywords                          { $$ = $1; }
 
1510
                | ECPGCKeywords                         { $$ = $1; }
 
1511
                | CHAR_P                                        { $$ = mm_strdup("char"); }
 
1512
                | VALUES                                        { $$ = mm_strdup("values"); }
 
1513
                ;
 
1514
 
 
1515
/*
 
1516
 * Name classification hierarchy.
 
1517
 *
 
1518
 * These productions should match those in the core grammar, except that
 
1519
 * we use all_unreserved_keyword instead of unreserved_keyword, and
 
1520
 * where possible include ECPG keywords as well as core keywords.
 
1521
 */
 
1522
 
 
1523
/* Column identifier --- names that can be column, table, etc names.
 
1524
 */
 
1525
ColId:  ecpg_ident                                      { $$ = $1; }
 
1526
                | all_unreserved_keyword        { $$ = $1; }
 
1527
                | col_name_keyword                      { $$ = $1; }
 
1528
                | ECPGKeywords                          { $$ = $1; }
 
1529
                | ECPGCKeywords                         { $$ = $1; }
 
1530
                | CHAR_P                                        { $$ = mm_strdup("char"); }
 
1531
                | VALUES                                        { $$ = mm_strdup("values"); }
 
1532
                ;
 
1533
 
 
1534
/* Type/function identifier --- names that can be type or function names.
 
1535
 */
 
1536
type_function_name:     ecpg_ident              { $$ = $1; }
 
1537
                | all_unreserved_keyword        { $$ = $1; }
 
1538
                | type_func_name_keyword        { $$ = $1; }
 
1539
                | ECPGKeywords                          { $$ = $1; }
 
1540
                | ECPGCKeywords                         { $$ = $1; }
 
1541
                | ECPGTypeName                          { $$ = $1; }
 
1542
                ;
 
1543
 
 
1544
/* Column label --- allowed labels in "AS" clauses.
 
1545
 * This presently includes *all* Postgres keywords.
 
1546
 */
 
1547
ColLabel:  ECPGColLabel                         { $$ = $1; }
 
1548
                | ECPGTypeName                          { $$ = $1; }
 
1549
                | CHAR_P                                        { $$ = mm_strdup("char"); }
 
1550
                | CURRENT_P                                     { $$ = mm_strdup("current"); }
 
1551
                | INPUT_P                                       { $$ = mm_strdup("input"); }
 
1552
                | INT_P                                         { $$ = mm_strdup("int"); }
 
1553
                | TO                                            { $$ = mm_strdup("to"); }
 
1554
                | UNION                                         { $$ = mm_strdup("union"); }
 
1555
                | VALUES                                        { $$ = mm_strdup("values"); }
 
1556
                | ECPGCKeywords                         { $$ = $1; }
 
1557
                | ECPGunreserved_interval       { $$ = $1; }
 
1558
                ;
 
1559
 
 
1560
ECPGColLabel:  ECPGColLabelCommon       { $$ = $1; }
 
1561
                | unreserved_keyword            { $$ = $1; }
 
1562
                | reserved_keyword                      { $$ = $1; }
 
1563
                | ECPGKeywords_rest                     { $$ = $1; }
 
1564
                | CONNECTION                            { $$ = mm_strdup("connection"); }
 
1565
                ;
 
1566
 
 
1567
ECPGColLabelCommon:  ecpg_ident         { $$ = $1; }
 
1568
                | col_name_keyword                      { $$ = $1; }
 
1569
                | type_func_name_keyword        { $$ = $1; }
 
1570
                | ECPGKeywords_vanames          { $$ = $1; }
 
1571
                ;
 
1572
 
 
1573
ECPGCKeywords: S_AUTO                           { $$ = mm_strdup("auto"); }
 
1574
                | S_CONST                                       { $$ = mm_strdup("const"); }
 
1575
                | S_EXTERN                                      { $$ = mm_strdup("extern"); }
 
1576
                | S_REGISTER                            { $$ = mm_strdup("register"); }
 
1577
                | S_STATIC                                      { $$ = mm_strdup("static"); }
 
1578
                | S_TYPEDEF                                     { $$ = mm_strdup("typedef"); }
 
1579
                | S_VOLATILE                            { $$ = mm_strdup("volatile"); }
 
1580
                ;
 
1581
 
 
1582
/* "Unreserved" keywords --- available for use as any kind of name.
 
1583
 */
 
1584
 
 
1585
/*
 
1586
 * The following symbols must be excluded from ECPGColLabel and directly
 
1587
 * included into ColLabel to enable C variables to get names from ECPGColLabel:
 
1588
 * DAY_P, HOUR_P, MINUTE_P, MONTH_P, SECOND_P, YEAR_P.
 
1589
 *
 
1590
 * We also have to exclude CONNECTION, CURRENT, and INPUT for various reasons.
 
1591
 * CONNECTION can be added back in all_unreserved_keyword, but CURRENT and
 
1592
 * INPUT are reserved for ecpg purposes.
 
1593
 *
 
1594
 * The mentioned exclusions are done by $replace_line settings in parse2.pl.
 
1595
 */
 
1596
all_unreserved_keyword: unreserved_keyword      { $$ = $1; }
 
1597
                | ECPGunreserved_interval                       { $$ = $1; }
 
1598
                | CONNECTION                                            { $$ = mm_strdup("connection"); }
 
1599
                ;
 
1600
 
 
1601
ECPGunreserved_interval: DAY_P                          { $$ = mm_strdup("day"); }
 
1602
                | HOUR_P                                                        { $$ = mm_strdup("hour"); }
 
1603
                | MINUTE_P                                                      { $$ = mm_strdup("minute"); }
 
1604
                | MONTH_P                                                       { $$ = mm_strdup("month"); }
 
1605
                | SECOND_P                                                      { $$ = mm_strdup("second"); }
 
1606
                | YEAR_P                                                        { $$ = mm_strdup("year"); }
 
1607
                ;
 
1608
 
 
1609
 
 
1610
into_list : coutputvariable | into_list ',' coutputvariable
 
1611
                ;
 
1612
 
 
1613
ecpgstart: SQL_START    {
 
1614
                                reset_variables();
 
1615
                                pacounter = 1;
 
1616
                        }
 
1617
                ;
 
1618
 
 
1619
c_args: /*EMPTY*/               { $$ = EMPTY; }
 
1620
                | c_list                { $$ = $1; }
 
1621
                ;
 
1622
 
 
1623
coutputvariable: cvariable indicator
 
1624
                        { add_variable_to_head(&argsresult, find_variable($1), find_variable($2)); }
 
1625
                | cvariable
 
1626
                        { add_variable_to_head(&argsresult, find_variable($1), &no_indicator); }
 
1627
                ;
 
1628
 
 
1629
 
 
1630
civarind: cvariable indicator
 
1631
                {
 
1632
                        if (find_variable($2)->type->type == ECPGt_array)
 
1633
                                mmerror(PARSE_ERROR, ET_ERROR, "arrays of indicators are not allowed on input");
 
1634
 
 
1635
                        add_variable_to_head(&argsinsert, find_variable($1), find_variable($2));
 
1636
                        $$ = create_questionmarks($1, false);
 
1637
                }
 
1638
                ;
 
1639
 
 
1640
char_civar: char_variable
 
1641
                {
 
1642
                        char *ptr = strstr($1, ".arr");
 
1643
 
 
1644
                        if (ptr) /* varchar, we need the struct name here, not the struct element */
 
1645
                                *ptr = '\0';
 
1646
                        add_variable_to_head(&argsinsert, find_variable($1), &no_indicator);
 
1647
                        $$ = $1;
 
1648
                }
 
1649
                ;
 
1650
 
 
1651
civar: cvariable
 
1652
                {
 
1653
                        add_variable_to_head(&argsinsert, find_variable($1), &no_indicator);
 
1654
                        $$ = create_questionmarks($1, false);
 
1655
                }
 
1656
                ;
 
1657
 
 
1658
indicator: cvariable                            { check_indicator((find_variable($1))->type); $$ = $1; }
 
1659
                | SQL_INDICATOR cvariable       { check_indicator((find_variable($2))->type); $$ = $2; }
 
1660
                | SQL_INDICATOR name            { check_indicator((find_variable($2))->type); $$ = $2; }
 
1661
                ;
 
1662
 
 
1663
cvariable:      CVARIABLE
 
1664
                {
 
1665
                        /* As long as multidimensional arrays are not implemented we have to check for those here */
 
1666
                        char *ptr = $1;
 
1667
                        int brace_open=0, brace = false;
 
1668
 
 
1669
                        for (; *ptr; ptr++)
 
1670
                        {
 
1671
                                switch (*ptr)
 
1672
                                {
 
1673
                                        case '[':
 
1674
                                                        if (brace)
 
1675
                                                                mmerror(PARSE_ERROR, ET_FATAL, "multidimensional arrays for simple data types are not supported");
 
1676
                                                        brace_open++;
 
1677
                                                        break;
 
1678
                                        case ']':
 
1679
                                                        brace_open--;
 
1680
                                                        if (brace_open == 0)
 
1681
                                                                brace = true;
 
1682
                                                        break;
 
1683
                                        case '\t':
 
1684
                                        case ' ':
 
1685
                                                        break;
 
1686
                                        default:
 
1687
                                                        if (brace_open == 0)
 
1688
                                                                brace = false;
 
1689
                                                        break;
 
1690
                                }
 
1691
                        }
 
1692
                        $$ = $1;
 
1693
                }
 
1694
                ;
 
1695
 
 
1696
ecpg_param:     PARAM           { $$ = make_name(); } ;
 
1697
 
 
1698
ecpg_bconst:    BCONST          { $$ = make_name(); } ;
 
1699
 
 
1700
ecpg_fconst:    FCONST          { $$ = make_name(); } ;
 
1701
 
 
1702
ecpg_sconst:
 
1703
                SCONST
 
1704
                {
 
1705
                        /* could have been input as '' or $$ */
 
1706
                        $$ = (char *)mm_alloc(strlen($1) + 3);
 
1707
                        $$[0]='\'';
 
1708
                        strcpy($$+1, $1);
 
1709
                        $$[strlen($1)+1]='\'';
 
1710
                        $$[strlen($1)+2]='\0';
 
1711
                        free($1);
 
1712
                }
 
1713
                | ECONST
 
1714
                {
 
1715
                        $$ = (char *)mm_alloc(strlen($1) + 4);
 
1716
                        $$[0]='E';
 
1717
                        $$[1]='\'';
 
1718
                        strcpy($$+2, $1);
 
1719
                        $$[strlen($1)+2]='\'';
 
1720
                        $$[strlen($1)+3]='\0';
 
1721
                        free($1);
 
1722
                }
 
1723
                | NCONST
 
1724
                {
 
1725
                        $$ = (char *)mm_alloc(strlen($1) + 4);
 
1726
                        $$[0]='N';
 
1727
                        $$[1]='\'';
 
1728
                        strcpy($$+2, $1);
 
1729
                        $$[strlen($1)+2]='\'';
 
1730
                        $$[strlen($1)+3]='\0';
 
1731
                        free($1);
 
1732
                }
 
1733
                | UCONST        { $$ = $1; }
 
1734
                | DOLCONST      { $$ = $1; }
 
1735
                ;
 
1736
 
 
1737
ecpg_xconst:    XCONST          { $$ = make_name(); } ;
 
1738
 
 
1739
ecpg_ident:     IDENT           { $$ = make_name(); }
 
1740
                | CSTRING       { $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\"")); }
 
1741
                | UIDENT        { $$ = $1; }
 
1742
                ;
 
1743
 
 
1744
quoted_ident_stringvar: name
 
1745
                        { $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\"")); }
 
1746
                | char_variable
 
1747
                        { $$ = make3_str(mm_strdup("("), $1, mm_strdup(")")); }
 
1748
                ;
 
1749
 
 
1750
/*
 
1751
 * C stuff
 
1752
 */
 
1753
 
 
1754
c_stuff_item: c_anything                        { $$ = $1; }
 
1755
                | '(' ')'                       { $$ = mm_strdup("()"); }
 
1756
                | '(' c_stuff ')'
 
1757
                        { $$ = cat_str(3, mm_strdup("("), $2, mm_strdup(")")); }
 
1758
                ;
 
1759
 
 
1760
c_stuff: c_stuff_item                   { $$ = $1; }
 
1761
                | c_stuff c_stuff_item
 
1762
                        { $$ = cat2_str($1, $2); }
 
1763
                ;
 
1764
 
 
1765
c_list: c_term                          { $$ = $1; }
 
1766
                | c_list ',' c_term     { $$ = cat_str(3, $1, mm_strdup(","), $3); }
 
1767
                ;
 
1768
 
 
1769
c_term:  c_stuff                        { $$ = $1; }
 
1770
                | '{' c_list '}'        { $$ = cat_str(3, mm_strdup("{"), $2, mm_strdup("}")); }
 
1771
                ;
 
1772
 
 
1773
c_thing:        c_anything              { $$ = $1; }
 
1774
                |       '('             { $$ = mm_strdup("("); }
 
1775
                |       ')'             { $$ = mm_strdup(")"); }
 
1776
                |       ','             { $$ = mm_strdup(","); }
 
1777
                |       ';'             { $$ = mm_strdup(";"); }
 
1778
                ;
 
1779
 
 
1780
c_anything:  ecpg_ident                         { $$ = $1; }
 
1781
                | Iconst                        { $$ = $1; }
 
1782
                | ecpg_fconst                   { $$ = $1; }
 
1783
                | ecpg_sconst                   { $$ = $1; }
 
1784
                | '*'                           { $$ = mm_strdup("*"); }
 
1785
                | '+'                           { $$ = mm_strdup("+"); }
 
1786
                | '-'                           { $$ = mm_strdup("-"); }
 
1787
                | '/'                           { $$ = mm_strdup("/"); }
 
1788
                | '%'                           { $$ = mm_strdup("%"); }
 
1789
                | NULL_P                        { $$ = mm_strdup("NULL"); }
 
1790
                | S_ADD                         { $$ = mm_strdup("+="); }
 
1791
                | S_AND                         { $$ = mm_strdup("&&"); }
 
1792
                | S_ANYTHING                    { $$ = make_name(); }
 
1793
                | S_AUTO                        { $$ = mm_strdup("auto"); }
 
1794
                | S_CONST                       { $$ = mm_strdup("const"); }
 
1795
                | S_DEC                         { $$ = mm_strdup("--"); }
 
1796
                | S_DIV                         { $$ = mm_strdup("/="); }
 
1797
                | S_DOTPOINT                    { $$ = mm_strdup(".*"); }
 
1798
                | S_EQUAL                       { $$ = mm_strdup("=="); }
 
1799
                | S_EXTERN                      { $$ = mm_strdup("extern"); }
 
1800
                | S_INC                         { $$ = mm_strdup("++"); }
 
1801
                | S_LSHIFT                      { $$ = mm_strdup("<<"); }
 
1802
                | S_MEMBER                      { $$ = mm_strdup("->"); }
 
1803
                | S_MEMPOINT                    { $$ = mm_strdup("->*"); }
 
1804
                | S_MOD                         { $$ = mm_strdup("%="); }
 
1805
                | S_MUL                         { $$ = mm_strdup("*="); }
 
1806
                | S_NEQUAL                      { $$ = mm_strdup("!="); }
 
1807
                | S_OR                          { $$ = mm_strdup("||"); }
 
1808
                | S_REGISTER                    { $$ = mm_strdup("register"); }
 
1809
                | S_RSHIFT                      { $$ = mm_strdup(">>"); }
 
1810
                | S_STATIC                      { $$ = mm_strdup("static"); }
 
1811
                | S_SUB                         { $$ = mm_strdup("-="); }
 
1812
                | S_TYPEDEF                     { $$ = mm_strdup("typedef"); }
 
1813
                | S_VOLATILE                    { $$ = mm_strdup("volatile"); }
 
1814
                | SQL_BOOL                      { $$ = mm_strdup("bool"); }
 
1815
                | ENUM_P                        { $$ = mm_strdup("enum"); }
 
1816
                | HOUR_P                        { $$ = mm_strdup("hour"); }
 
1817
                | INT_P                         { $$ = mm_strdup("int"); }
 
1818
                | SQL_LONG                      { $$ = mm_strdup("long"); }
 
1819
                | MINUTE_P                      { $$ = mm_strdup("minute"); }
 
1820
                | MONTH_P                       { $$ = mm_strdup("month"); }
 
1821
                | SECOND_P                      { $$ = mm_strdup("second"); }
 
1822
                | SQL_SHORT                     { $$ = mm_strdup("short"); }
 
1823
                | SQL_SIGNED                    { $$ = mm_strdup("signed"); }
 
1824
                | SQL_STRUCT                    { $$ = mm_strdup("struct"); }
 
1825
                | SQL_UNSIGNED                  { $$ = mm_strdup("unsigned"); }
 
1826
                | YEAR_P                        { $$ = mm_strdup("year"); }
 
1827
                | CHAR_P                        { $$ = mm_strdup("char"); }
 
1828
                | FLOAT_P                       { $$ = mm_strdup("float"); }
 
1829
                | TO                            { $$ = mm_strdup("to"); }
 
1830
                | UNION                         { $$ = mm_strdup("union"); }
 
1831
                | VARCHAR                       { $$ = mm_strdup("varchar"); }
 
1832
                | '['                           { $$ = mm_strdup("["); }
 
1833
                | ']'                           { $$ = mm_strdup("]"); }
 
1834
                | '='                           { $$ = mm_strdup("="); }
 
1835
                | ':'                           { $$ = mm_strdup(":"); }
 
1836
                ;
 
1837
 
 
1838
DeallocateStmt: DEALLOCATE prepared_name                { $$ = $2; }
 
1839
                | DEALLOCATE PREPARE prepared_name      { $$ = $3; }
 
1840
                | DEALLOCATE ALL                        { $$ = mm_strdup("all"); }
 
1841
                | DEALLOCATE PREPARE ALL                { $$ = mm_strdup("all"); }
 
1842
                ;
 
1843
 
 
1844
Iresult:        Iconst                  { $$ = $1; }
 
1845
                | '(' Iresult ')'       { $$ = cat_str(3, mm_strdup("("), $2, mm_strdup(")")); }
 
1846
                | Iresult '+' Iresult   { $$ = cat_str(3, $1, mm_strdup("+"), $3); }
 
1847
                | Iresult '-' Iresult   { $$ = cat_str(3, $1, mm_strdup("-"), $3); }
 
1848
                | Iresult '*' Iresult   { $$ = cat_str(3, $1, mm_strdup("*"), $3); }
 
1849
                | Iresult '/' Iresult   { $$ = cat_str(3, $1, mm_strdup("/"), $3); }
 
1850
                | Iresult '%' Iresult   { $$ = cat_str(3, $1, mm_strdup("%"), $3); }
 
1851
                | ecpg_sconst           { $$ = $1; }
 
1852
                | ColId                 { $$ = $1; }
 
1853
                ;
 
1854
 
 
1855
execute_rest: /* EMPTY */       { $$ = EMPTY; }
 
1856
        | ecpg_using ecpg_into  { $$ = EMPTY; }
 
1857
        | ecpg_into ecpg_using  { $$ = EMPTY; }
 
1858
        | ecpg_using            { $$ = EMPTY; }
 
1859
        | ecpg_into             { $$ = EMPTY; }
 
1860
        ;
 
1861
 
 
1862
ecpg_into: INTO into_list       { $$ = EMPTY; }
 
1863
        | into_descriptor       { $$ = $1; }
 
1864
        ;
 
1865
 
 
1866
ecpg_fetch_into: ecpg_into      { $$ = $1; }
 
1867
        | using_descriptor
 
1868
        {
 
1869
                struct variable *var;
 
1870
 
 
1871
                var = argsinsert->variable;
 
1872
                remove_variable_from_list(&argsinsert, var);
 
1873
                add_variable_to_head(&argsresult, var, &no_indicator);
 
1874
                $$ = $1;
 
1875
        }
 
1876
        ;
 
1877
 
 
1878
opt_ecpg_fetch_into:    /* EMPTY */     { $$ = EMPTY; }
 
1879
        | ecpg_fetch_into               { $$ = $1; }
 
1880
        ;
 
1881
 
 
1882
%%
 
1883
 
 
1884
void base_yyerror(const char *error)
 
1885
{
 
1886
        /* translator: %s is typically the translation of "syntax error" */
 
1887
        mmerror(PARSE_ERROR, ET_ERROR, "%s at or near \"%s\"",
 
1888
                        _(error), token_start ? token_start : yytext);
 
1889
}
 
1890
 
 
1891
void parser_init(void)
 
1892
{
 
1893
 /* This function is empty. It only exists for compatibility with the backend parser right now. */
 
1894
}
 
1895
 
 
1896
/*
 
1897
 * Must undefine base_yylex before including pgc.c, since we want it
 
1898
 * to create the function base_yylex not filtered_base_yylex.
 
1899
 */
 
1900
#undef base_yylex
 
1901
 
 
1902
#include "pgc.c"