]> granicus.if.org Git - postgresql/blob - src/interfaces/ecpg/preproc/ecpg.trailer
Added files containing changes between gram.y and preproc.y.
[postgresql] / src / interfaces / ecpg / preproc / ecpg.trailer
1 /* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.trailer,v 1.1 2008/11/14 10:03:33 meskes Exp $ */
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                 | '}'                   { remove_typedefs(braces_open); remove_variables(braces_open--); fputs("}", yyout); }
20                 ;
21
22 CreateAsStmt: CREATE OptTemp TABLE create_as_target AS {FoundInto = 0;} SelectStmt opt_with_data
23                 {
24                         if (FoundInto == 1)
25                                 mmerror(PARSE_ERROR, ET_ERROR, "CREATE TABLE / AS SELECT cannot specify INTO\n");
26
27                         $$ = cat_str(6, make_str("create"), $2, make_str("table"), $4, make_str("as"), $7);
28                 }
29         ;
30
31 RuleStmt: CREATE opt_or_replace RULE name AS
32                 {QueryIsRule = 1;}
33                 ON event TO qualified_name where_clause
34                 DO opt_instead RuleActionList
35                 {
36                         QueryIsRule=0;
37                         $$ = cat_str(12, make_str("create"), $2, make_str("rule"), $4, make_str("as on"), $8, make_str("to"), $10, $11, make_str("do"), $13, $14);
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, make_str(","), $5, make_str(","), $4); }
59                 | SQL_CONNECT TO DEFAULT
60                         { $$ = make_str("NULL, NULL, NULL, \"DEFAULT\""); }
61                   /* also allow ORACLE syntax */
62                 | SQL_CONNECT ora_user
63                         { $$ = cat_str(3, make_str("NULL,"), $2, make_str(", NULL")); }
64                 | DATABASE connection_target
65                         { $$ = cat2_str($2, make_str(", 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(make_str("\""), make3_str($1, $2, $3), make_str("\""));
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(make_str("\""), $1, make_str(":")), $3, make3_str(make3_str($4, make_str("/"), $6),    $7, make_str("\"")));
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, "illegal connection type %s", $1);
122
123                         $$ = make3_str($1, make_str(":"), $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, make_str("."), $3); }
142                 | IP                                            { $$ = make_name(); }
143                 ;
144
145 opt_port: ':' Iconst            { $$ = make2_str(make_str(":"), $2); }
146                 | /*EMPTY*/     { $$ = EMPTY; }
147                 ;
148
149 opt_connection_name: AS connection_object       { $$ = $2; }
150                 | /*EMPTY*/                     { $$ = make_str("NULL"); }
151                 ;
152
153 opt_user: USER ora_user         { $$ = $2; }
154                 | /*EMPTY*/                     { $$ = make_str("NULL, NULL"); }
155                 ;
156
157 ora_user: user_name
158                         { $$ = cat2_str($1, make_str(", NULL")); }
159                 | user_name '/' user_name
160                         { $$ = cat_str(3, $1, make_str(","), $3); }
161                 | user_name SQL_IDENTIFIED BY user_name
162                         { $$ = cat_str(3, $1, make_str(","), $4); }
163                 | user_name USING user_name
164                         { $$ = cat_str(3, $1, make_str(","), $3); }
165                 ;
166
167 user_name: RoleId
168                 {
169                         if ($1[0] == '\"')
170                                 $$ = $1;
171                         else
172                                 $$ = make3_str(make_str("\""), $1, make_str("\""));
173                 }
174                 | ecpg_sconst
175                 {
176                         if ($1[0] == '\"')
177                                 $$ = $1;
178                         else
179                                 $$ = make3_str(make_str("\""), $1, make_str("\""));
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), make_str(".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 datatype");
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                                                 $$ = $1;
217                                                 break;
218                                         case ECPGt_varchar:
219                                                 $$ = make2_str($1, make_str(".arr"));
220                                                 break;
221                                         default:
222                                                 mmerror(PARSE_ERROR, ET_ERROR, "invalid datatype");
223                                                 $$ = $1;
224                                                 break;
225                                 }
226                         }
227                 }
228                 ;
229
230 opt_options: Op connect_options
231                 {
232                         if (strlen($1) == 0)
233                                 mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement");
234
235                         if (strcmp($1, "?") != 0)
236                                 mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", $1);
237
238                         $$ = make2_str(make_str("?"), $2);
239                 }
240                 | /*EMPTY*/     { $$ = EMPTY; }
241                 ;
242
243 connect_options:  ColId opt_opt_value 
244                         { $$ = make2_str($1, $2); }
245         | ColId opt_opt_value Op connect_options
246                         {
247                                 if (strlen($3) == 0)
248                                         mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement");
249
250                                 if (strcmp($3, "&") != 0)
251                                         mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", $3);
252
253                                 $$ = cat_str(3, make2_str($1, $2), $3, $4);
254                         }
255         ;
256
257 opt_opt_value: /*EMPTY*/
258                         { $$ = EMPTY; }
259                 | '=' Iconst
260                         { $$ = make2_str(make_str("="), $2); }
261                 | '=' ecpg_ident
262                         { $$ = make2_str(make_str("="), $2); }
263                 | '=' civar
264                         { $$ = make2_str(make_str("="), $2); }
265                 ;
266
267 prepared_name: name             {
268                                         if ($1[0] == '\"' && $1[strlen($1)-1] == '\"') /* already quoted? */
269                                                 $$ = $1;
270                                         else /* not quoted => convert to lowercase */
271                                         {
272                                                 int i;
273
274                                                 for (i = 0; i< strlen($1); i++)
275                                                         $1[i] = tolower((unsigned char) $1[i]);
276
277                                                 $$ = make3_str(make_str("\""), $1, make_str("\""));
278                                         }
279                                 }
280                 | char_variable { $$ = $1; }
281                 ;
282
283 /*
284  * Declare a prepared cursor. The syntax is different from the standard
285  * declare statement, so we create a new rule.
286  */
287 ECPGCursorStmt:  DECLARE name cursor_options CURSOR opt_hold FOR prepared_name
288                 {
289                         struct cursor *ptr, *this;
290                         struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
291                         const char *con = connection ? connection : "NULL";
292
293                         for (ptr = cur; ptr != NULL; ptr = ptr->next)
294                         {
295                                 if (strcmp($2, ptr->name) == 0)
296                                         /* re-definition is a bug */
297                                         mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" already defined", $2);
298                         }
299
300                         this = (struct cursor *) mm_alloc(sizeof(struct cursor));
301
302                         /* initial definition */
303                         this->next = cur;
304                         this->name = $2;
305                         this->connection = connection;
306                         this->command =  cat_str(6, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for $1"));
307                         this->argsresult = NULL;
308
309                         thisquery->type = &ecpg_query;
310                         thisquery->brace_level = 0;
311                         thisquery->next = NULL;
312                         thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement(, , __LINE__)") + strlen(con) + strlen($7));
313                         sprintf(thisquery->name, "ECPGprepared_statement(%s, %s, __LINE__)", con, $7);
314
315                         this->argsinsert = NULL;
316                         add_variable_to_head(&(this->argsinsert), thisquery, &no_indicator);
317
318                         cur = this;
319
320                         $$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
321                 }
322                 ;
323
324 ECPGExecuteImmediateStmt: EXECUTE IMMEDIATE execstring
325                         { 
326                           /* execute immediate means prepare the statement and
327                            * immediately execute it */
328                           $$ = $3;
329                         };
330 /*
331  * variable decalartion outside exec sql declare block
332  */
333 ECPGVarDeclaration: single_vt_declaration;
334
335 single_vt_declaration: type_declaration         { $$ = $1; }
336                 | var_declaration               { $$ = $1; }
337                 ;
338
339 precision:      NumericOnly     { $$ = $1; };
340
341 opt_scale:      ',' NumericOnly { $$ = $2; }
342                 | /* EMPTY */   { $$ = EMPTY; }
343                 ;
344
345 ecpg_interval:  opt_interval    { $$ = $1; }
346                 | YEAR_P TO MINUTE_P    { $$ = make_str("year to minute"); }
347                 | YEAR_P TO SECOND_P    { $$ = make_str("year to second"); }
348                 | DAY_P TO DAY_P                { $$ = make_str("day to day"); }
349                 | MONTH_P TO MONTH_P    { $$ = make_str("month to month"); }
350                 ;
351
352 /*
353  * variable declaration inside exec sql declare block
354  */
355 ECPGDeclaration: sql_startdeclare
356                 { fputs("/* exec sql begin declare section */", yyout); }
357                 var_type_declarations sql_enddeclare
358                 {
359                         fprintf(yyout, "%s/* exec sql end declare section */", $3);
360                         free($3);
361                         output_line_number();
362                 }
363                 ;
364
365 sql_startdeclare: ecpgstart BEGIN_P DECLARE SQL_SECTION ';' {};
366
367 sql_enddeclare: ecpgstart END_P DECLARE SQL_SECTION ';' {};
368
369 var_type_declarations:  /*EMPTY*/                       { $$ = EMPTY; }
370                 | vt_declarations                       { $$ = $1; }
371                 | CPP_LINE                              { $$ = $1; }
372                 ;
373
374 vt_declarations:  var_declaration                       { $$ = $1; }
375                 | type_declaration                      { $$ = $1; }
376                 | vt_declarations var_declaration       { $$ = cat2_str($1, $2); }
377                 | vt_declarations type_declaration      { $$ = cat2_str($1, $2); }
378                 | vt_declarations CPP_LINE              { $$ = cat2_str($1, $2); }
379                 ;
380
381 variable_declarations:  var_declaration         { $$ = $1; }
382                 | variable_declarations var_declaration         { $$ = cat2_str($1, $2); }
383                 ;
384
385 type_declaration: S_TYPEDEF
386         {
387                 /* reset this variable so we see if there was */
388                 /* an initializer specified */
389                 initializer = 0;
390         }
391         var_type opt_pointer ECPGColLabelCommon opt_array_bounds ';'
392         {
393                 add_typedef($5, $6.index1, $6.index2, $3.type_enum, $3.type_dimension, $3.type_index, initializer, *$4 ? 1 : 0);
394
395                 fprintf(yyout, "typedef %s %s %s %s;\n", $3.type_str, *$4 ? "*" : "", $5, $6.str);
396                 output_line_number();
397                 $$ = make_str("");
398         };
399
400 var_declaration: storage_declaration
401                 var_type
402                 {
403                         actual_type[struct_level].type_enum = $2.type_enum;
404                         actual_type[struct_level].type_dimension = $2.type_dimension;
405                         actual_type[struct_level].type_index = $2.type_index;
406                         actual_type[struct_level].type_sizeof = $2.type_sizeof;
407
408                         actual_startline[struct_level] = hashline_number();
409                 }
410                 variable_list ';'
411                 {
412                         $$ = cat_str(5, actual_startline[struct_level], $1, $2.type_str, $4, make_str(";\n"));
413                 }
414                 | var_type
415                 {
416                         actual_type[struct_level].type_enum = $1.type_enum;
417                         actual_type[struct_level].type_dimension = $1.type_dimension;
418                         actual_type[struct_level].type_index = $1.type_index;
419                         actual_type[struct_level].type_sizeof = $1.type_sizeof;
420
421                         actual_startline[struct_level] = hashline_number();
422                 }
423                 variable_list ';'
424                 {
425                         $$ = cat_str(4, actual_startline[struct_level], $1.type_str, $3, make_str(";\n"));
426                 }
427                 | struct_union_type_with_symbol ';'
428                 {
429                         $$ = cat2_str($1, make_str(";"));
430                 }
431                 ;
432
433 opt_bit_field:  ':' Iconst      { $$ =cat2_str(make_str(":"), $2); }
434                 | /* EMPTY */   { $$ = EMPTY; }
435                 ;
436
437 storage_declaration: storage_clause storage_modifier
438                         {$$ = cat2_str ($1, $2); }
439                 | storage_clause                {$$ = $1; }
440                 | storage_modifier              {$$ = $1; }
441                 ;
442
443 storage_clause : S_EXTERN       { $$ = make_str("extern"); }
444                 | S_STATIC                      { $$ = make_str("static"); }
445                 | S_REGISTER            { $$ = make_str("register"); }
446                 | S_AUTO                        { $$ = make_str("auto"); }
447                 ;
448
449 storage_modifier : S_CONST      { $$ = make_str("const"); }
450                 | S_VOLATILE            { $$ = make_str("volatile"); }
451                 ;
452
453 var_type:       simple_type
454                 {
455                         $$.type_enum = $1;
456                         $$.type_str = mm_strdup(ecpg_type_name($1));
457                         $$.type_dimension = make_str("-1");
458                         $$.type_index = make_str("-1");
459                         $$.type_sizeof = NULL;
460                 }
461                 | struct_union_type
462                 {
463                         $$.type_str = $1;
464                         $$.type_dimension = make_str("-1");
465                         $$.type_index = make_str("-1");
466
467                         if (strncmp($1, "struct", sizeof("struct")-1) == 0)
468                         {
469                                 $$.type_enum = ECPGt_struct;
470                                 $$.type_sizeof = ECPGstruct_sizeof;
471                         }
472                         else
473                         {
474                                 $$.type_enum = ECPGt_union;
475                                 $$.type_sizeof = NULL;
476                         }
477                 }
478                 | enum_type
479                 {
480                         $$.type_str = $1;
481                         $$.type_enum = ECPGt_int;
482                         $$.type_dimension = make_str("-1");
483                         $$.type_index = make_str("-1");
484                         $$.type_sizeof = NULL;
485                 }
486                 | ECPGColLabelCommon '(' precision opt_scale ')'
487                 {
488                         if (strcmp($1, "numeric") == 0)
489                         {
490                                 $$.type_enum = ECPGt_numeric;
491                                 $$.type_str = make_str("numeric");
492                         }
493                         else if (strcmp($1, "decimal") == 0)
494                         {
495                                 $$.type_enum = ECPGt_decimal;
496                                 $$.type_str = make_str("decimal");
497                         }
498                         else
499                         {
500                                 mmerror(PARSE_ERROR, ET_ERROR, "only numeric/decimal have precision/scale argument");
501                                 $$.type_enum = ECPGt_numeric;
502                                 $$.type_str = make_str("numeric");
503                         }
504
505                         $$.type_dimension = make_str("-1");
506                         $$.type_index = make_str("-1");
507                         $$.type_sizeof = NULL;
508                 }
509                 | ECPGColLabelCommon ecpg_interval
510                 {
511                         if (strlen($2) != 0 && strcmp ($1, "datetime") != 0 && strcmp ($1, "interval") != 0)
512                                 mmerror (PARSE_ERROR, ET_ERROR, "interval specification not allowed here");
513
514                         /*
515                          * Check for type names that the SQL grammar treats as
516                          * unreserved keywords
517                          */
518                         if (strcmp($1, "varchar") == 0)
519                         {
520                                 $$.type_enum = ECPGt_varchar;
521                                 $$.type_str = EMPTY; /*make_str("varchar");*/
522                                 $$.type_dimension = make_str("-1");
523                                 $$.type_index = make_str("-1");
524                                 $$.type_sizeof = NULL;
525                         }
526                         else if (strcmp($1, "float") == 0)
527                         {
528                                 $$.type_enum = ECPGt_float;
529                                 $$.type_str = make_str("float");
530                                 $$.type_dimension = make_str("-1");
531                                 $$.type_index = make_str("-1");
532                                 $$.type_sizeof = NULL;
533                         }
534                         else if (strcmp($1, "double") == 0)
535                         {
536                                 $$.type_enum = ECPGt_double;
537                                 $$.type_str = make_str("double");
538                                 $$.type_dimension = make_str("-1");
539                                 $$.type_index = make_str("-1");
540                                 $$.type_sizeof = NULL;
541                         }
542                         else if (strcmp($1, "numeric") == 0)
543                         {
544                                 $$.type_enum = ECPGt_numeric;
545                                 $$.type_str = make_str("numeric");
546                                 $$.type_dimension = make_str("-1");
547                                 $$.type_index = make_str("-1");
548                                 $$.type_sizeof = NULL;
549                         }
550                         else if (strcmp($1, "decimal") == 0)
551                         {
552                                 $$.type_enum = ECPGt_decimal;
553                                 $$.type_str = make_str("decimal");
554                                 $$.type_dimension = make_str("-1");
555                                 $$.type_index = make_str("-1");
556                                 $$.type_sizeof = NULL;
557                         }
558                         else if (strcmp($1, "date") == 0)
559                         {
560                                 $$.type_enum = ECPGt_date;
561                                 $$.type_str = make_str("date");
562                                 $$.type_dimension = make_str("-1");
563                                 $$.type_index = make_str("-1");
564                                 $$.type_sizeof = NULL;
565                         }
566                         else if (strcmp($1, "timestamp") == 0)
567                         {
568                                 $$.type_enum = ECPGt_timestamp;
569                                 $$.type_str = make_str("timestamp");
570                                 $$.type_dimension = make_str("-1");
571                                 $$.type_index = make_str("-1");
572                                 $$.type_sizeof = NULL;
573                         }
574                         else if (strcmp($1, "interval") == 0)
575                         {
576                                 $$.type_enum = ECPGt_interval;
577                                 $$.type_str = make_str("interval");
578                                 $$.type_dimension = make_str("-1");
579                                 $$.type_index = make_str("-1");
580                                 $$.type_sizeof = NULL;
581                         }
582                         else if (strcmp($1, "datetime") == 0)
583                         {
584                                 $$.type_enum = ECPGt_timestamp;
585                                 $$.type_str = make_str("timestamp");
586                                 $$.type_dimension = make_str("-1");
587                                 $$.type_index = make_str("-1");
588                                 $$.type_sizeof = NULL;
589                         }
590                         else
591                         {
592                                 /* this is for typedef'ed types */
593                                 struct typedefs *this = get_typedef($1);
594
595                                 $$.type_str = (this->type->type_enum == ECPGt_varchar) ? EMPTY : mm_strdup(this->name);
596                                 $$.type_enum = this->type->type_enum;
597                                 $$.type_dimension = this->type->type_dimension;
598                                 $$.type_index = this->type->type_index;
599                                 if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0)
600                                         $$.type_sizeof = this->type->type_sizeof;
601                                 else 
602                                         $$.type_sizeof = cat_str(3, make_str("sizeof("), mm_strdup(this->name), make_str(")"));
603
604                                 struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
605                         }
606                 }
607                 | s_struct_union_symbol
608                 {
609                         /* this is for named structs/unions */
610                         char *name;
611                         struct typedefs *this;
612                         bool forward = (forward_name != NULL && strcmp($1.symbol, forward_name) == 0 && strcmp($1.su, "struct") == 0);
613
614                         name = cat2_str($1.su, $1.symbol);
615                         /* Do we have a forward definition? */
616                         if (!forward)
617                         {
618                                 /* No */
619
620                                 this = get_typedef(name);
621                                 $$.type_str = mm_strdup(this->name);
622                                 $$.type_enum = this->type->type_enum;
623                                 $$.type_dimension = this->type->type_dimension;
624                                 $$.type_index = this->type->type_index;
625                                 $$.type_sizeof = this->type->type_sizeof;
626                                 struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
627                                 free(name);
628                         }
629                         else
630                         {
631                                 $$.type_str = name;
632                                 $$.type_enum = ECPGt_long;
633                                 $$.type_dimension = make_str("-1");
634                                 $$.type_index = make_str("-1");
635                                 $$.type_sizeof = make_str("");
636                                 struct_member_list[struct_level] = NULL;
637                         }
638                 }
639                 ;
640
641 enum_type: ENUM_P symbol enum_definition
642                         { $$ = cat_str(3, make_str("enum"), $2, $3); }
643                 | ENUM_P enum_definition
644                         { $$ = cat2_str(make_str("enum"), $2); }
645                 | ENUM_P symbol
646                         { $$ = cat2_str(make_str("enum"), $2); }
647                 ;
648
649 enum_definition: '{' c_list '}'
650                         { $$ = cat_str(3, make_str("{"), $2, make_str("}")); };
651
652 struct_union_type_with_symbol: s_struct_union_symbol
653                 {
654                         struct_member_list[struct_level++] = NULL;
655                         if (struct_level >= STRUCT_DEPTH)
656                                  mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition");
657                         forward_name = mm_strdup($1.symbol);
658                 }
659                 '{' variable_declarations '}'
660                 {
661                         struct typedefs *ptr, *this;
662                         struct this_type su_type;
663
664                         ECPGfree_struct_member(struct_member_list[struct_level]);
665                         struct_member_list[struct_level] = NULL;
666                         struct_level--;
667                         if (strncmp($1.su, "struct", sizeof("struct")-1) == 0)
668                                 su_type.type_enum = ECPGt_struct;
669                         else
670                                 su_type.type_enum = ECPGt_union;
671                         su_type.type_str = cat2_str($1.su, $1.symbol);
672                         free(forward_name);
673                         forward_name = NULL;
674
675                         /* This is essantially a typedef but needs the keyword struct/union as well.
676                          * So we create the typedef for each struct definition with symbol */
677                         for (ptr = types; ptr != NULL; ptr = ptr->next)
678                         {
679                                         if (strcmp(su_type.type_str, ptr->name) == 0)
680                                                         /* re-definition is a bug */
681                                                         mmerror(PARSE_ERROR, ET_ERROR, "type \"%s\" already defined", su_type.type_str);
682                         }
683
684                         this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
685
686                         /* initial definition */
687                         this->next = types;
688                         this->name = mm_strdup(su_type.type_str);
689                         this->brace_level = braces_open;
690                         this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
691                         this->type->type_enum = su_type.type_enum;
692                         this->type->type_str = mm_strdup(su_type.type_str);
693                         this->type->type_dimension = make_str("-1"); /* dimension of array */
694                         this->type->type_index = make_str("-1");        /* length of string */
695                         this->type->type_sizeof = ECPGstruct_sizeof;
696                         this->struct_member_list = struct_member_list[struct_level];
697
698                         types = this;
699                         $$ = cat_str(4, su_type.type_str, make_str("{"), $4, make_str("}"));
700                 }
701                 ;
702
703 struct_union_type: struct_union_type_with_symbol        { $$ = $1; }
704                 | s_struct_union
705                 {
706                         struct_member_list[struct_level++] = NULL;
707                         if (struct_level >= STRUCT_DEPTH)
708                                  mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition");
709                 }
710                 '{' variable_declarations '}'
711                 {
712                         ECPGfree_struct_member(struct_member_list[struct_level]);
713                         struct_member_list[struct_level] = NULL;
714                         struct_level--;
715                         $$ = cat_str(4, $1, make_str("{"), $4, make_str("}"));
716                 }
717                 ;
718
719 s_struct_union_symbol: SQL_STRUCT symbol
720                 {
721                         $$.su = make_str("struct");
722                         $$.symbol = $2;
723                         ECPGstruct_sizeof = cat_str(3, make_str("sizeof("), cat2_str(mm_strdup($$.su), mm_strdup($$.symbol)), make_str(")"));
724                 }
725                 | UNION symbol
726                 {
727                         $$.su = make_str("union");
728                         $$.symbol = $2;
729                 }
730                 ;
731
732 s_struct_union: SQL_STRUCT
733                 {
734                         ECPGstruct_sizeof = make_str(""); /* This must not be NULL to distinguish from simple types. */
735                         $$ = make_str("struct");
736                 }
737                 | UNION         { $$ = make_str("union"); }
738                 ;
739
740 simple_type: unsigned_type                                      { $$=$1; }
741                 |       opt_signed signed_type                  { $$=$2; }
742                 ;
743
744 unsigned_type: SQL_UNSIGNED SQL_SHORT           { $$ = ECPGt_unsigned_short; }
745                 | SQL_UNSIGNED SQL_SHORT INT_P  { $$ = ECPGt_unsigned_short; }
746                 | SQL_UNSIGNED                                          { $$ = ECPGt_unsigned_int; }
747                 | SQL_UNSIGNED INT_P                            { $$ = ECPGt_unsigned_int; }
748                 | SQL_UNSIGNED SQL_LONG                         { $$ = ECPGt_unsigned_long; }
749                 | SQL_UNSIGNED SQL_LONG INT_P           { $$ = ECPGt_unsigned_long; }
750                 | SQL_UNSIGNED SQL_LONG SQL_LONG
751                 {
752 #ifdef HAVE_LONG_LONG_INT_64
753                         $$ = ECPGt_unsigned_long_long;
754 #else
755                         $$ = ECPGt_unsigned_long;
756 #endif
757                 }
758                 | SQL_UNSIGNED SQL_LONG SQL_LONG INT_P
759                 {
760 #ifdef HAVE_LONG_LONG_INT_64
761                         $$ = ECPGt_unsigned_long_long;
762 #else
763                         $$ = ECPGt_unsigned_long;
764 #endif
765                 }
766                 | SQL_UNSIGNED CHAR_P                   { $$ = ECPGt_unsigned_char; }
767                 ;
768
769 signed_type: SQL_SHORT                          { $$ = ECPGt_short; }
770                 | SQL_SHORT INT_P                       { $$ = ECPGt_short; }
771                 | INT_P                                         { $$ = ECPGt_int; }
772                 | SQL_LONG                                      { $$ = ECPGt_long; }
773                 | SQL_LONG INT_P                        { $$ = ECPGt_long; }
774                 | SQL_LONG SQL_LONG
775                 {
776 #ifdef HAVE_LONG_LONG_INT_64
777                         $$ = ECPGt_long_long;
778 #else
779                         $$ = ECPGt_long;
780 #endif
781                 }
782                 | SQL_LONG SQL_LONG INT_P
783                 {
784 #ifdef HAVE_LONG_LONG_INT_64
785                         $$ = ECPGt_long_long;
786 #else
787                         $$ = ECPGt_long;
788 #endif
789                 }
790                 | SQL_BOOL                                      { $$ = ECPGt_bool; }
791                 | CHAR_P                                        { $$ = ECPGt_char; }
792                 | DOUBLE_P                                      { $$ = ECPGt_double; }
793                 ;
794
795 opt_signed: SQL_SIGNED
796                 |       /* EMPTY */
797                 ;
798
799 variable_list: variable
800                         { $$ = $1; }
801                 | variable_list ',' variable
802                         { $$ = cat_str(3, $1, make_str(","), $3); }
803                 ;
804
805 variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initializer
806                 {
807                         struct ECPGtype * type;
808                         char *dimension = $3.index1; /* dimension of array */
809                         char *length = $3.index2;    /* length of string */
810                         char dim[14L];
811                         char *vcn;
812
813                         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);
814
815                         switch (actual_type[struct_level].type_enum)
816                         {
817                                 case ECPGt_struct:
818                                 case ECPGt_union:
819                                         if (atoi(dimension) < 0)
820                                                 type = ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_sizeof);
821                                         else
822                                                 type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_sizeof), dimension);
823
824                                         $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5);
825                                         break;
826
827                                 case ECPGt_varchar:
828                                         if (atoi(dimension) < 0)
829                                                 type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, yylineno);
830                                         else
831                                                 type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, yylineno), dimension);
832                                         
833                                         if (strcmp(dimension, "0") == 0 || abs(atoi(dimension)) == 1)
834                                                         *dim = '\0';
835                                         else
836                                                         sprintf(dim, "[%s]", dimension);
837                                         /* cannot check for atoi <= 0 because a defined constant will yield 0 here as well */
838                                         if (atoi(length) < 0 || strcmp(length, "0") == 0)
839                                                 mmerror(PARSE_ERROR, ET_ERROR, "pointer to varchar are not implemented");
840
841                                         /* make sure varchar struct name is unique by adding linenumer of its definition */
842                                         vcn = (char *) mm_alloc(strlen($2) + sizeof(int) * CHAR_BIT * 10 / 3);
843                                         sprintf(vcn, "%s_%d", $2, yylineno);
844                                         if (strcmp(dimension, "0") == 0)
845                                                 $$ = cat_str(7, make2_str(make_str(" struct varchar_"), vcn), make_str(" { int len; char arr["), mm_strdup(length), make_str("]; } *"), mm_strdup($2), $4, $5);
846                                         else
847                                                 $$ = cat_str(8, make2_str(make_str(" struct varchar_"), vcn), make_str(" { int len; char arr["), mm_strdup(length), make_str("]; } "), mm_strdup($2), mm_strdup(dim), $4, $5);
848                                         break;
849
850                                 case ECPGt_char:
851                                 case ECPGt_unsigned_char:
852                                         if (atoi(dimension) == -1)
853                                         {
854                                                 int i = strlen($5);
855
856                                                 if (atoi(length) == -1 && i > 0) /* char <var>[] = "string" */
857                                                 {
858                                                         /* if we have an initializer but no string size set, let's use the initializer's length */
859                                                         free(length);
860                                                         length = mm_alloc(i+sizeof("sizeof()"));
861                                                         sprintf(length, "sizeof(%s)", $5+2);
862                                                 }
863                                                 type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0);
864                                         }
865                                         else
866                                                 type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0), dimension);
867
868                                         $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5);
869                                         break;
870
871                                 default:
872                                         if (atoi(dimension) < 0)
873                                                 type = ECPGmake_simple_type(actual_type[struct_level].type_enum, make_str("1"), 0);
874                                         else
875                                                 type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, make_str("1"), 0), dimension);
876
877                                         $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5);
878                                         break;
879                         }
880
881                         if (struct_level == 0)
882                                 new_variable($2, type, braces_open);
883                         else
884                                 ECPGmake_struct_member($2, type, &(struct_member_list[struct_level - 1]));
885
886                         free($2);
887                 }
888                 ;
889
890 opt_initializer: /*EMPTY*/
891                         { $$ = EMPTY; }
892                 | '=' c_term
893                 {
894                         initializer = 1;
895                         $$ = cat2_str(make_str("="), $2);
896                 }
897                 ;
898
899 opt_pointer: /*EMPTY*/                          { $$ = EMPTY; }
900                 | '*'                                           { $$ = make_str("*"); }
901                 | '*' '*'                                       { $$ = make_str("**"); }
902                 ;
903
904 /*
905  * We try to simulate the correct DECLARE syntax here so we get dynamic SQL
906  */
907 ECPGDeclare: DECLARE STATEMENT ecpg_ident
908                 {
909                         /* this is only supported for compatibility */
910                         $$ = cat_str(3, make_str("/* declare statement"), $3, make_str("*/"));
911                 }
912                 ;
913 /*
914  * the exec sql disconnect statement: disconnect from the given database
915  */
916 ECPGDisconnect: SQL_DISCONNECT dis_name { $$ = $2; }
917                 ;
918
919 dis_name: connection_object                     { $$ = $1; }
920                 | CURRENT_P                     { $$ = make_str("\"CURRENT\""); }
921                 | ALL                           { $$ = make_str("\"ALL\""); }
922                 | /* EMPTY */                   { $$ = make_str("\"CURRENT\""); }
923                 ;
924
925 connection_object: database_name                { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
926                 | DEFAULT                       { $$ = make_str("\"DEFAULT\""); }
927                 | char_variable                 { $$ = $1; }
928                 ;
929
930 execstring: char_variable
931                         { $$ = $1; }
932                 |       CSTRING
933                         { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
934                 ;
935
936 /*
937  * the exec sql free command to deallocate a previously
938  * prepared statement
939  */
940 ECPGFree:       SQL_FREE name   { $$ = $2; }
941                 | SQL_FREE ALL  { $$ = make_str("all"); }
942                 ;
943
944 /*
945  * open is an open cursor, at the moment this has to be removed
946  */
947 ECPGOpen: SQL_OPEN name opt_ecpg_using { $$ = $2; };
948
949 opt_ecpg_using: /*EMPTY*/       { $$ = EMPTY; }
950                 | ecpg_using            { $$ = $1; }
951                 ;
952
953 ecpg_using:     USING using_list        { $$ = EMPTY; }
954                 | using_descriptor      { $$ = $1; }
955                 ;
956
957 using_descriptor: USING opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
958                 {
959                         add_variable_to_head(&argsinsert, descriptor_variable($4,0), &no_indicator);
960                         $$ = EMPTY;
961                 }
962                 ;
963
964 into_descriptor: INTO opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
965                 {
966                         add_variable_to_head(&argsresult, descriptor_variable($4,1), &no_indicator);
967                         $$ = EMPTY;
968                 }
969                 ;
970
971 opt_sql: /*EMPTY*/ | SQL_SQL;
972
973 using_list: UsingValue | UsingValue ',' using_list;
974
975 UsingValue: UsingConst
976                 {
977                         char *length = mm_alloc(32);
978
979                         sprintf(length, "%d", (int) strlen($1));
980                         add_variable_to_head(&argsinsert, new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0), &no_indicator);
981                 }
982                 | civar { $$ = EMPTY; }
983                 | civarind { $$ = EMPTY; }
984                 ; 
985
986 UsingConst: Iconst                      { $$ = $1; }
987                 | ecpg_fconst           { $$ = $1; }
988                 | ecpg_sconst           { $$ = $1; }
989                 | ecpg_bconst           { $$ = $1; }
990                 | ecpg_xconst           { $$ = $1; }
991                 ;
992
993 /*
994  * We accept descibe but do nothing with it so far.
995  */
996 ECPGDescribe: SQL_DESCRIBE INPUT_P name using_descriptor
997         {
998                 const char *con = connection ? connection : "NULL";
999                 mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement\n");
1000                 $$ = (char *) mm_alloc(sizeof("1, ECPGprepared_statement(, \"\", __LINE__)") + strlen(con) + strlen($3));
1001                 sprintf($$, "1, ECPGprepared_statement(%s, \"%s\", __LINE__)", con, $3);
1002         }
1003         | SQL_DESCRIBE opt_output name using_descriptor
1004         {
1005                 const char *con = connection ? connection : "NULL";
1006                 mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement\n");
1007                 $$ = (char *) mm_alloc(sizeof("0, ECPGprepared_statement(, \"\", __LINE__)") + strlen(con) + strlen($3));
1008                 sprintf($$, "0, ECPGprepared_statement(%s, \"%s\", __LINE__)", con, $3);
1009         }
1010         | SQL_DESCRIBE opt_output name into_descriptor
1011         {
1012                 const char *con = connection ? connection : "NULL";
1013                 mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement\n");
1014                 $$ = (char *) mm_alloc(sizeof("0, ECPGprepared_statement(, \"\", __LINE__)") + strlen(con) + strlen($3));
1015                 sprintf($$, "0, ECPGprepared_statement(%s, \"%s\", __LINE__)", con, $3);
1016         }
1017         ;
1018
1019 opt_output:     SQL_OUTPUT      { $$ = make_str("output"); }
1020         |       /* EMPTY */     { $$ = EMPTY; }
1021         ;
1022
1023 /*
1024  * dynamic SQL: descriptor based access
1025  *      originall written by Christof Petig <christof.petig@wtal.de>
1026  *                      and Peter Eisentraut <peter.eisentraut@credativ.de>
1027  */
1028
1029 /*
1030  * allocate a descriptor
1031  */
1032 ECPGAllocateDescr:     SQL_ALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
1033                 {
1034                         add_descriptor($3,connection);
1035                         $$ = $3;
1036                 }
1037                 ;
1038
1039
1040 /*
1041  * deallocate a descriptor
1042  */
1043 ECPGDeallocateDescr:    DEALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
1044                 {
1045                         drop_descriptor($3,connection);
1046                         $$ = $3;
1047                 }
1048                 ;
1049
1050 /*
1051  * manipulate a descriptor header
1052  */
1053
1054 ECPGGetDescriptorHeader: SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar ECPGGetDescHeaderItems
1055                         {  $$ = $3; }
1056                 ;
1057
1058 ECPGGetDescHeaderItems: ECPGGetDescHeaderItem
1059                 | ECPGGetDescHeaderItems ',' ECPGGetDescHeaderItem
1060                 ;
1061
1062 ECPGGetDescHeaderItem: cvariable '=' desc_header_item
1063                         { push_assignment($1, $3); }
1064                 ;
1065
1066
1067 ECPGSetDescriptorHeader: SET SQL_DESCRIPTOR quoted_ident_stringvar ECPGSetDescHeaderItems
1068                         { $$ = $3; }
1069                 ;
1070
1071 ECPGSetDescHeaderItems: ECPGSetDescHeaderItem
1072                 | ECPGSetDescHeaderItems ',' ECPGSetDescHeaderItem
1073                 ;
1074
1075 ECPGSetDescHeaderItem: desc_header_item '=' IntConstVar
1076                 {
1077                         push_assignment($3, $1);
1078                 }
1079                 ;
1080
1081 IntConstVar:    Iconst
1082                 {
1083                         char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
1084
1085                         sprintf(length, "%d", (int) strlen($1));
1086                         new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
1087                         $$ = $1;
1088                 }
1089                 | cvariable     { $$ = $1; }
1090                 ;
1091
1092 desc_header_item:       SQL_COUNT                       { $$ = ECPGd_count; }
1093                 ;
1094
1095 /*
1096  * manipulate a descriptor
1097  */
1098
1099 ECPGGetDescriptor:      SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGGetDescItems
1100                         {  $$.str = $5; $$.name = $3; }
1101                 ;
1102
1103 ECPGGetDescItems: ECPGGetDescItem
1104                 | ECPGGetDescItems ',' ECPGGetDescItem
1105                 ;
1106
1107 ECPGGetDescItem: cvariable '=' descriptor_item  { push_assignment($1, $3); };
1108
1109
1110 ECPGSetDescriptor:      SET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGSetDescItems
1111                         {  $$.str = $5; $$.name = $3; }
1112                 ;
1113
1114 ECPGSetDescItems: ECPGSetDescItem
1115                 | ECPGSetDescItems ',' ECPGSetDescItem
1116                 ;
1117
1118 ECPGSetDescItem: descriptor_item '=' AllConstVar
1119                 {
1120                         push_assignment($3, $1);
1121                 }
1122                 ;
1123
1124 AllConstVar:    ecpg_fconst
1125                 {
1126                         char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
1127
1128                         sprintf(length, "%d", (int) strlen($1));
1129                         new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
1130                         $$ = $1;
1131                 }
1132                 | IntConstVar           { $$ = $1; }
1133                 | '-' ecpg_fconst
1134                 {
1135                         char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
1136                         char *var = cat2_str(make_str("-"), $2);
1137
1138                         sprintf(length, "%d", (int) strlen(var));
1139                         new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
1140                         $$ = var;
1141                 }
1142                 | '-' Iconst
1143                 {
1144                         char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
1145                         char *var = cat2_str(make_str("-"), $2);
1146
1147                         sprintf(length, "%d", (int) strlen(var));
1148                         new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
1149                         $$ = var;
1150                 }
1151                 | ecpg_sconst
1152                 {
1153                         char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
1154                         char *var = $1 + 1;
1155
1156                         var[strlen(var) - 1] = '\0';
1157                         sprintf(length, "%d", (int) strlen(var));
1158                         new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
1159                         $$ = var;
1160                 }
1161                 ;
1162
1163 descriptor_item:        SQL_CARDINALITY                 { $$ = ECPGd_cardinality; }
1164                 | DATA_P                                { $$ = ECPGd_data; }
1165                 | SQL_DATETIME_INTERVAL_CODE            { $$ = ECPGd_di_code; }
1166                 | SQL_DATETIME_INTERVAL_PRECISION       { $$ = ECPGd_di_precision; }
1167                 | SQL_INDICATOR                         { $$ = ECPGd_indicator; }
1168                 | SQL_KEY_MEMBER                        { $$ = ECPGd_key_member; }
1169                 | SQL_LENGTH                            { $$ = ECPGd_length; }
1170                 | NAME_P                                { $$ = ECPGd_name; }
1171                 | SQL_NULLABLE                          { $$ = ECPGd_nullable; }
1172                 | SQL_OCTET_LENGTH                      { $$ = ECPGd_octet; }
1173                 | PRECISION                             { $$ = ECPGd_precision; }
1174                 | SQL_RETURNED_LENGTH                   { $$ = ECPGd_length; }
1175                 | SQL_RETURNED_OCTET_LENGTH             { $$ = ECPGd_ret_octet; }
1176                 | SQL_SCALE                             { $$ = ECPGd_scale; }
1177                 | TYPE_P                                { $$ = ECPGd_type; }
1178                 ;
1179
1180 /*
1181  * set/reset the automatic transaction mode, this needs a differnet handling
1182  * as the other set commands
1183  */
1184 ECPGSetAutocommit:      SET SQL_AUTOCOMMIT '=' on_off   { $$ = $4; }
1185                 |  SET SQL_AUTOCOMMIT TO on_off   { $$ = $4; }
1186                 ;
1187
1188 on_off: ON                              { $$ = make_str("on"); }
1189                 | OFF                   { $$ = make_str("off"); }
1190                 ;
1191
1192 /*
1193  * set the actual connection, this needs a differnet handling as the other
1194  * set commands
1195  */
1196 ECPGSetConnection:      SET CONNECTION TO connection_object { $$ = $4; }
1197                 | SET CONNECTION '=' connection_object { $$ = $4; }
1198                 | SET CONNECTION  connection_object { $$ = $3; }
1199                 ;
1200
1201 /*
1202  * define a new type for embedded SQL
1203  */
1204 ECPGTypedef: TYPE_P
1205                 {
1206                         /* reset this variable so we see if there was */
1207                         /* an initializer specified */
1208                         initializer = 0;
1209                 }
1210                 ECPGColLabelCommon IS var_type opt_array_bounds opt_reference
1211                 {
1212                         add_typedef($3, $6.index1, $6.index2, $5.type_enum, $5.type_dimension, $5.type_index, initializer, *$7 ? 1 : 0);
1213
1214                         if (auto_create_c == false)
1215                                 $$ = cat_str(7, make_str("/* exec sql type"), mm_strdup($3), make_str("is"), mm_strdup($5.type_str), mm_strdup($6.str), $7, make_str("*/"));
1216                         else
1217                                 $$ = cat_str(6, make_str("typedef "), mm_strdup($5.type_str), *$7?make_str("*"):make_str(""), mm_strdup($6.str), mm_strdup($3), make_str(";"));
1218                 }
1219                 ;
1220
1221 opt_reference: SQL_REFERENCE            { $$ = make_str("reference"); }
1222                 | /*EMPTY*/                                     { $$ = EMPTY; }
1223                 ;
1224
1225 /*
1226  * define the type of one variable for embedded SQL
1227  */
1228 ECPGVar: SQL_VAR
1229                 {
1230                         /* reset this variable so we see if there was */
1231                         /* an initializer specified */
1232                         initializer = 0;
1233                 }
1234                 ColLabel IS var_type opt_array_bounds opt_reference
1235                 {
1236                         struct variable *p = find_variable($3);
1237                         char *dimension = $6.index1;
1238                         char *length = $6.index2;
1239                         struct ECPGtype * type;
1240
1241                         if (($5.type_enum == ECPGt_struct ||
1242                                  $5.type_enum == ECPGt_union) &&
1243                                 initializer == 1)
1244                                 mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in EXEC SQL VAR command");
1245                         else
1246                         {
1247                                 adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7?1:0, false);
1248
1249                                 switch ($5.type_enum)
1250                                 {
1251                                         case ECPGt_struct:
1252                                         case ECPGt_union:
1253                                                 if (atoi(dimension) < 0)
1254                                                         type = ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, $5.type_sizeof);
1255                                                 else
1256                                                         type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum,$5.type_sizeof), dimension);
1257                                                 break;
1258
1259                                         case ECPGt_varchar:
1260                                                 if (atoi(dimension) == -1)
1261                                                         type = ECPGmake_simple_type($5.type_enum, length, 0);
1262                                                 else
1263                                                         type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length, 0), dimension);
1264                                                 break;
1265
1266                                         case ECPGt_char:
1267                                         case ECPGt_unsigned_char:
1268                                                 if (atoi(dimension) == -1)
1269                                                         type = ECPGmake_simple_type($5.type_enum, length, 0);
1270                                                 else
1271                                                         type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length, 0), dimension);
1272                                                 break;
1273
1274                                         default:
1275                                                 if (atoi(length) >= 0)
1276                                                         mmerror(PARSE_ERROR, ET_ERROR, "no multidimensional array support for simple data types");
1277
1278                                                 if (atoi(dimension) < 0)
1279                                                         type = ECPGmake_simple_type($5.type_enum, make_str("1"), 0);
1280                                                 else
1281                                                         type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, make_str("1"), 0), dimension);
1282                                                 break;
1283                                 }
1284
1285                                 ECPGfree_type(p->type);
1286                                 p->type = type;
1287                         }
1288
1289                         $$ = cat_str(7, make_str("/* exec sql var"), mm_strdup($3), make_str("is"), mm_strdup($5.type_str), mm_strdup($6.str), $7, make_str("*/"));
1290                 }
1291                 ;
1292
1293 /*
1294  * whenever statement: decide what to do in case of error/no data found
1295  * according to SQL standards we lack: SQLSTATE, CONSTRAINT and SQLEXCEPTION
1296  */
1297 ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action
1298                 {
1299                         when_error.code = $<action>3.code;
1300                         when_error.command = $<action>3.command;
1301                         $$ = cat_str(3, make_str("/* exec sql whenever sqlerror "), $3.str, make_str("; */"));
1302                 }
1303                 | SQL_WHENEVER NOT SQL_FOUND action
1304                 {
1305                         when_nf.code = $<action>4.code;
1306                         when_nf.command = $<action>4.command;
1307                         $$ = cat_str(3, make_str("/* exec sql whenever not found "), $4.str, make_str("; */"));
1308                 }
1309                 | SQL_WHENEVER SQL_SQLWARNING action
1310                 {
1311                         when_warn.code = $<action>3.code;
1312                         when_warn.command = $<action>3.command;
1313                         $$ = cat_str(3, make_str("/* exec sql whenever sql_warning "), $3.str, make_str("; */"));
1314                 }
1315                 ;
1316
1317 action : CONTINUE_P
1318                 {
1319                         $<action>$.code = W_NOTHING;
1320                         $<action>$.command = NULL;
1321                         $<action>$.str = make_str("continue");
1322                 }
1323                 | SQL_SQLPRINT
1324                 {
1325                         $<action>$.code = W_SQLPRINT;
1326                         $<action>$.command = NULL;
1327                         $<action>$.str = make_str("sqlprint");
1328                 }
1329                 | SQL_STOP
1330                 {
1331                         $<action>$.code = W_STOP;
1332                         $<action>$.command = NULL;
1333                         $<action>$.str = make_str("stop");
1334                 }
1335                 | SQL_GOTO name
1336                 {
1337                         $<action>$.code = W_GOTO;
1338                         $<action>$.command = strdup($2);
1339                         $<action>$.str = cat2_str(make_str("goto "), $2);
1340                 }
1341                 | SQL_GO TO name
1342                 {
1343                         $<action>$.code = W_GOTO;
1344                         $<action>$.command = strdup($3);
1345                         $<action>$.str = cat2_str(make_str("goto "), $3);
1346                 }
1347                 | DO name '(' c_args ')'
1348                 {
1349                         $<action>$.code = W_DO;
1350                         $<action>$.command = cat_str(4, $2, make_str("("), $4, make_str(")"));
1351                         $<action>$.str = cat2_str(make_str("do"), mm_strdup($<action>$.command));
1352                 }
1353                 | DO SQL_BREAK
1354                 {
1355                         $<action>$.code = W_BREAK;
1356                         $<action>$.command = NULL;
1357                         $<action>$.str = make_str("break");
1358                 }
1359                 | SQL_CALL name '(' c_args ')'
1360                 {
1361                         $<action>$.code = W_DO;
1362                         $<action>$.command = cat_str(4, $2, make_str("("), $4, make_str(")"));
1363                         $<action>$.str = cat2_str(make_str("call"), mm_strdup($<action>$.command));
1364                 }
1365                 | SQL_CALL name
1366                 {
1367                         $<action>$.code = W_DO;
1368                         $<action>$.command = cat2_str($2, make_str("()"));
1369                         $<action>$.str = cat2_str(make_str("call"), mm_strdup($<action>$.command));
1370                 }
1371                 ;
1372
1373 /* some other stuff for ecpg */
1374
1375 /* additional unreserved keywords */
1376 ECPGKeywords: ECPGKeywords_vanames      { $$ = $1; }
1377                 | ECPGKeywords_rest     { $$ = $1; }
1378                 ;
1379
1380 ECPGKeywords_vanames:  SQL_BREAK                { $$ = make_str("break"); }
1381                 | SQL_CALL                                              { $$ = make_str("call"); }
1382                 | SQL_CARDINALITY                               { $$ = make_str("cardinality"); }
1383                 | SQL_COUNT                                             { $$ = make_str("count"); }
1384                 | SQL_DATETIME_INTERVAL_CODE    { $$ = make_str("datetime_interval_code"); }
1385                 | SQL_DATETIME_INTERVAL_PRECISION       { $$ = make_str("datetime_interval_precision"); }
1386                 | SQL_FOUND                                             { $$ = make_str("found"); }
1387                 | SQL_GO                                                { $$ = make_str("go"); }
1388                 | SQL_GOTO                                              { $$ = make_str("goto"); }
1389                 | SQL_IDENTIFIED                                { $$ = make_str("identified"); }
1390                 | SQL_INDICATOR                         { $$ = make_str("indicator"); }
1391                 | SQL_KEY_MEMBER                        { $$ = make_str("key_member"); }
1392                 | SQL_LENGTH                            { $$ = make_str("length"); }
1393                 | SQL_NULLABLE                          { $$ = make_str("nullable"); }
1394                 | SQL_OCTET_LENGTH                      { $$ = make_str("octet_length"); }
1395                 | SQL_RETURNED_LENGTH           { $$ = make_str("returned_length"); }
1396                 | SQL_RETURNED_OCTET_LENGTH     { $$ = make_str("returned_octet_length"); }
1397                 | SQL_SCALE                                     { $$ = make_str("scale"); }
1398                 | SQL_SECTION                           { $$ = make_str("section"); }
1399                 | SQL_SQL                               { $$ = make_str("sql"); }
1400                 | SQL_SQLERROR                          { $$ = make_str("sqlerror"); }
1401                 | SQL_SQLPRINT                          { $$ = make_str("sqlprint"); }
1402                 | SQL_SQLWARNING                        { $$ = make_str("sqlwarning"); }
1403                 | SQL_STOP                                      { $$ = make_str("stop"); }
1404                 ;
1405
1406 ECPGKeywords_rest:  SQL_CONNECT         { $$ = make_str("connect"); }
1407                 | SQL_DESCRIBE                          { $$ = make_str("describe"); }
1408                 | SQL_DISCONNECT                        { $$ = make_str("disconnect"); }
1409                 | SQL_OPEN                                      { $$ = make_str("open"); }
1410                 | SQL_VAR                                       { $$ = make_str("var"); }
1411                 | SQL_WHENEVER                          { $$ = make_str("whenever"); }
1412                 ;
1413
1414 /* additional keywords that can be SQL type names (but not ECPGColLabels) */
1415 ECPGTypeName:  SQL_BOOL                         { $$ = make_str("bool"); }
1416                 | SQL_LONG                                      { $$ = make_str("long"); }
1417                 | SQL_OUTPUT                            { $$ = make_str("output"); }
1418                 | SQL_SHORT                                     { $$ = make_str("short"); }
1419                 | SQL_STRUCT                            { $$ = make_str("struct"); }
1420                 | SQL_SIGNED                            { $$ = make_str("signed"); }
1421                 | SQL_UNSIGNED                          { $$ = make_str("unsigned"); }
1422                 ;
1423
1424 symbol: ColLabel                                        { $$ = $1; }
1425                 ;
1426
1427 ECPGColId: ecpg_ident                           { $$ = $1; }
1428                 | ECPGunreserved_interval       { $$ = $1; }
1429                 | ECPGunreserved_con            { $$ = $1; }
1430                 | col_name_keyword              { $$ = $1; }
1431                 | ECPGKeywords                  { $$ = $1; }
1432                 | ECPGCKeywords                 { $$ = $1; }
1433                 | CHAR_P                        { $$ = make_str("char"); }
1434                 | VALUES                        { $$ = make_str("values"); }
1435                 ;
1436 /* Column label --- allowed labels in "AS" clauses.
1437  * This presently includes *all* Postgres keywords.
1438  */
1439 ColLabel:  ECPGColLabel                         { $$ = $1; }
1440                 | ECPGTypeName                  { $$ = $1; }
1441                 | CHAR_P                        { $$ = make_str("char"); }
1442                 | INPUT_P                       { $$ = make_str("input"); }
1443                 | INT_P                         { $$ = make_str("int"); }
1444                 | UNION                         { $$ = make_str("union"); }
1445                 | TO                            { $$ = make_str("to"); }
1446                 | ECPGCKeywords                 { $$ = $1; }
1447                 | ECPGunreserved_interval       { $$ = $1; }
1448                 ;
1449
1450 ECPGColLabelCommon:  ecpg_ident                 { $$ = $1; }
1451                 | col_name_keyword              { $$ = $1; }
1452                 | type_func_name_keyword        { $$ = $1; }
1453                 | ECPGKeywords_vanames          { $$ = $1; }
1454                 ;
1455
1456 ECPGColLabel:  ECPGColLabelCommon       { $$ = $1; }
1457                 | reserved_keyword              { $$ = $1; }
1458                 | ECPGunreserved                { $$ = $1; }
1459                 | ECPGKeywords_rest             { $$ = $1; }
1460                 ;
1461
1462 ECPGCKeywords: S_AUTO                   { $$ = make_str("auto"); }
1463                 | S_CONST                               { $$ = make_str("const"); }
1464                 | S_EXTERN                              { $$ = make_str("extern"); }
1465                 | S_REGISTER                    { $$ = make_str("register"); }
1466                 | S_STATIC                              { $$ = make_str("static"); }
1467                 | S_TYPEDEF                             { $$ = make_str("typedef"); }
1468                 | S_VOLATILE                    { $$ = make_str("volatile"); }
1469                 ;
1470
1471 /*
1472  * Keyword classification lists.  Generally, every keyword present in
1473  * the Postgres grammar should appear in exactly one of these lists.
1474  *
1475  * Put a new keyword into the first list that it can go into without causing
1476  * shift or reduce conflicts.  The earlier lists define "less reserved"
1477  * categories of keywords.
1478  */
1479
1480 /* "Unreserved" keywords --- available for use as any kind of name.
1481  */
1482 /* The following symbols must be excluded from ECPGColLabel and directly included into ColLabel
1483    to enable C variables to get names from ECPGColLabel:
1484    DAY_P, HOUR_P, MINUTE_P, MONTH_P, SECOND_P, YEAR_P
1485  */
1486 unreserved_keyword: ECPGunreserved_interval | ECPGunreserved;
1487
1488 ECPGunreserved_interval: DAY_P                  { $$ = make_str("day"); }
1489                 | HOUR_P                        { $$ = make_str("hour"); }
1490                 | MINUTE_P                      { $$ = make_str("minute"); }
1491                 | MONTH_P                       { $$ = make_str("month"); }
1492                 | SECOND_P                      { $$ = make_str("second"); }
1493                 | YEAR_P                        { $$ = make_str("year"); }
1494                 ;
1495
1496 /* The following symbol must be excluded from var_name but still included in ColId
1497    to enable ecpg special postgresql variables with this name:  CONNECTION
1498  */
1499 ECPGunreserved: ECPGunreserved_con              { $$ = $1; }
1500                 | CONNECTION                    { $$ = make_str("connection"); }
1501                 ;
1502
1503 ECPGunreserved_con:       ABORT_P                       { $$ = make_str("abort"); }
1504                 | ABSOLUTE_P            { $$ = make_str("absolute"); }
1505                 | ACCESS                        { $$ = make_str("access"); }
1506                 | ACTION                        { $$ = make_str("action"); }
1507                 | ADD_P                         { $$ = make_str("add"); }
1508                 | ADMIN                         { $$ = make_str("admin"); }
1509                 | AFTER                         { $$ = make_str("after"); }
1510                 | AGGREGATE                     { $$ = make_str("aggregate"); }
1511                 | ALSO                          { $$ = make_str("also"); }
1512                 | ALTER                         { $$ = make_str("alter"); }
1513                 | ALWAYS                        { $$ = make_str("always"); }
1514                 | ASSERTION                     { $$ = make_str("assertion"); }
1515                 | ASSIGNMENT            { $$ = make_str("assignment"); }
1516                 | AT                            { $$ = make_str("at"); }
1517                 | BACKWARD                      { $$ = make_str("backward"); }
1518                 | BEFORE                        { $$ = make_str("before"); }
1519                 | BEGIN_P                       { $$ = make_str("begin"); }
1520                 | BY                            { $$ = make_str("by"); }
1521                 | CACHE                         { $$ = make_str("cache"); }
1522                 | CASCADE                       { $$ = make_str("cascade"); }
1523                 | CASCADED                      { $$ = make_str("cascaded"); }
1524                 | CHAIN                         { $$ = make_str("chain"); }
1525                 | CHARACTERISTICS       { $$ = make_str("characteristics"); }
1526                 | CHECKPOINT            { $$ = make_str("checkpoint"); }
1527                 | CLASS                         { $$ = make_str("class"); }
1528                 | CLOSE                         { $$ = make_str("close"); }
1529                 | CLUSTER                       { $$ = make_str("cluster"); }
1530                 | COMMENT                       { $$ = make_str("comment"); }
1531                 | COMMIT                        { $$ = make_str("commit"); }
1532                 | COMMITTED                     { $$ = make_str("committed"); }
1533                 | CONCURRENTLY          { $$ = make_str("concurrently"); }
1534                 | CONFIGURATION         { $$ = make_str("configuration"); }
1535 /*              | CONNECTION            { $$ = make_str("connection"); }*/
1536                 | CONSTRAINTS           { $$ = make_str("constraints"); }
1537                 | CONTENT_P             { $$ = make_str("content"); }
1538                 | CONTINUE_P            { $$ = make_str("continue"); }
1539                 | CONVERSION_P          { $$ = make_str("conversion"); }
1540                 | COPY                          { $$ = make_str("copy"); }
1541                 | COST                          { $$ = make_str("cost"); }
1542                 | CREATEDB                      { $$ = make_str("createdb"); }
1543                 | CREATEROLE            { $$ = make_str("createrole"); }
1544                 | CREATEUSER            { $$ = make_str("createuser"); }
1545                 | CSV                           { $$ = make_str("csv"); }
1546                 | CTYPE                 { $$ = make_str("ctype"); }
1547                 | CURSOR                        { $$ = make_str("cursor"); }
1548                 | CYCLE                         { $$ = make_str("cycle"); }
1549                 | DATA_P                        { $$ = make_str("data"); }
1550                 | DATABASE                      { $$ = make_str("database"); }
1551 /*              | DAY_P                         { $$ = make_str("day"); }*/
1552                 | DEALLOCATE            { $$ = make_str("deallocate"); }
1553                 | DECLARE                       { $$ = make_str("declare"); }
1554                 | DEFAULTS                      { $$ = make_str("defaults"); }
1555                 | DEFERRED                      { $$ = make_str("deferred"); }
1556                 | DELETE_P                      { $$ = make_str("delete"); }
1557                 | DELIMITER                     { $$ = make_str("delimiter"); }
1558                 | DELIMITERS            { $$ = make_str("delimiters"); }
1559                 | DICTIONARY            { $$ = make_str("dictionary"); }
1560                 | DISABLE_P                     { $$ = make_str("disable"); }
1561                 | DISCARD                       { $$ = make_str("discard"); }
1562                 | DOCUMENT_P                    { $$ = make_str("document"); }
1563                 | DOMAIN_P                      { $$ = make_str("domain"); }
1564                 | DOUBLE_P                      { $$ = make_str("double"); }
1565                 | DROP                          { $$ = make_str("drop"); }
1566                 | EACH                          { $$ = make_str("each"); }
1567                 | ENABLE_P                      { $$ = make_str("enable"); }
1568                 | ENCODING                      { $$ = make_str("encoding"); }
1569                 | ENCRYPTED                     { $$ = make_str("encrypted"); }
1570 /*              | ENUM_P                        { $$ = make_str("enum"); }*/
1571                 | ESCAPE                        { $$ = make_str("escape"); }
1572                 | EXCLUDING                     { $$ = make_str("excluding"); }
1573                 | EXCLUSIVE                     { $$ = make_str("exclusive"); }
1574                 | EXECUTE                       { $$ = make_str("execute"); }
1575                 | EXPLAIN                       { $$ = make_str("explain"); }
1576                 | EXTERNAL                      { $$ = make_str("external"); }
1577                 | FAMILY                        { $$ = make_str("family"); }
1578 /*              | FETCH                         { $$ = make_str("fetch"); }*/
1579                 | FIRST_P                       { $$ = make_str("first"); }
1580                 | FORCE                         { $$ = make_str("force"); }
1581                 | FORWARD                       { $$ = make_str("forward"); }
1582                 | FUNCTION                      { $$ = make_str("function"); }
1583                 | GLOBAL                        { $$ = make_str("global"); }
1584                 | GRANTED                       { $$ = make_str("granted"); }
1585                 | HANDLER                       { $$ = make_str("handler"); }
1586                 | HEADER_P                      { $$ = make_str("header"); }
1587                 | HOLD                          { $$ = make_str("hold"); }
1588 /*              | HOUR_P                        { $$ = make_str("hour"); }*/
1589                 | IDENTITY_P                    { $$ = make_str("identity"); }
1590                 | IF_P                          { $$ = make_str("if"); }
1591                 | IMMEDIATE                     { $$ = make_str("immediate"); }
1592                 | IMMUTABLE                     { $$ = make_str("immutable"); }
1593                 | IMPLICIT_P            { $$ = make_str("implicit"); }
1594                 | INCLUDING                     { $$ = make_str("including"); }
1595                 | INCREMENT                     { $$ = make_str("increment"); }
1596                 | INDEX                         { $$ = make_str("index"); }
1597                 | INDEXES                       { $$ = make_str("indexes"); }
1598                 | INHERIT                       { $$ = make_str("inherit"); }
1599                 | INHERITS                      { $$ = make_str("inherits"); }
1600                 | INSENSITIVE           { $$ = make_str("insensitive"); }
1601                 | INSERT                        { $$ = make_str("insert"); }
1602                 | INSTEAD                       { $$ = make_str("instead"); }
1603                 | ISOLATION                     { $$ = make_str("isolation"); }
1604                 | KEY                           { $$ = make_str("key"); }
1605                 | LANCOMPILER           { $$ = make_str("lancompiler"); }
1606                 | LANGUAGE                      { $$ = make_str("language"); }
1607                 | LARGE_P                       { $$ = make_str("large"); }
1608                 | LAST_P                        { $$ = make_str("last"); }
1609                 | LEVEL                         { $$ = make_str("level"); }
1610                 | LISTEN                        { $$ = make_str("listen"); }
1611                 | LOAD                          { $$ = make_str("load"); }
1612                 | LOCAL                         { $$ = make_str("local"); }
1613                 | LOCATION                      { $$ = make_str("location"); }
1614                 | LOCK_P                        { $$ = make_str("lock"); }
1615                 | LOGIN_P                       { $$ = make_str("login"); }
1616                 | MAPPING                       { $$ = make_str("mapping"); }
1617                 | MATCH                         { $$ = make_str("match"); }
1618                 | MAXVALUE                      { $$ = make_str("maxvalue"); }
1619 /*              | MINUTE_P                      { $$ = make_str("minute"); }*/
1620                 | MINVALUE                      { $$ = make_str("minvalue"); }
1621                 | MODE                          { $$ = make_str("mode"); }
1622 /*              | MONTH_P                       { $$ = make_str("month"); }*/
1623                 | MOVE                          { $$ = make_str("move"); }
1624                 | NAME_P                        { $$ = make_str("name"); }
1625                 | NAMES                         { $$ = make_str("names"); }
1626                 | NEXT                          { $$ = make_str("next"); }
1627                 | NO                            { $$ = make_str("no"); }
1628                 | NOCREATEDB            { $$ = make_str("nocreatedb"); }
1629                 | NOCREATEROLE          { $$ = make_str("nocreaterole"); }
1630                 | NOCREATEUSER          { $$ = make_str("nocreateuser"); }
1631                 | NOINHERIT                     { $$ = make_str("noinherit"); }
1632                 | NOLOGIN_P             { $$ = make_str("nologin"); }
1633                 | NOSUPERUSER           { $$ = make_str("nosuperuser"); }
1634                 | NOTHING                       { $$ = make_str("nothing"); }
1635                 | NOTIFY                        { $$ = make_str("notify"); }
1636                 | NOWAIT                        { $$ = make_str("nowait"); }
1637                 | NULLS_P                       { $$ = make_str("nulls"); }
1638                 | OBJECT_P                      { $$ = make_str("object"); }
1639                 | OF                            { $$ = make_str("of"); }
1640                 | OIDS                          { $$ = make_str("oids"); }
1641                 | OPERATOR                      { $$ = make_str("operator"); }
1642                 | OPTION                        { $$ = make_str("option"); }
1643                 | OWNED                         { $$ = make_str("owned"); }
1644                 | OWNER                         { $$ = make_str("owner"); }
1645                 | PARSER                        { $$ = make_str("parser"); }
1646                 | PARTIAL                       { $$ = make_str("partial"); }
1647                 | PASSWORD                      { $$ = make_str("password"); }
1648                 | PLANS                         { $$ = make_str("plans"); }
1649                 | PREPARE                       { $$ = make_str("prepare"); }
1650                 | PREPARED                      { $$ = make_str("prepared"); }
1651                 | PRESERVE                      { $$ = make_str("preserver"); }
1652                 | PRIOR                         { $$ = make_str("prior"); }
1653                 | PRIVILEGES            { $$ = make_str("privileges"); }
1654                 | PROCEDURAL            { $$ = make_str("procedural"); }
1655                 | PROCEDURE                     { $$ = make_str("procedure"); }
1656                 | QUOTE                         { $$ = make_str("quote"); }
1657                 | READ                          { $$ = make_str("read"); }
1658                 | REASSIGN                      { $$ = make_str("reassign"); }
1659                 | RECHECK                       { $$ = make_str("recheck"); }
1660                 | RECURSIVE                     { $$ = make_str("recursive"); }
1661                 | REINDEX                       { $$ = make_str("reindex"); }
1662                 | RELATIVE_P            { $$ = make_str("relative"); }
1663                 | RELEASE                       { $$ = make_str("release"); }
1664                 | RENAME                        { $$ = make_str("rename"); }
1665                 | REPEATABLE            { $$ = make_str("repeatable"); }
1666                 | REPLACE                       { $$ = make_str("replace"); }
1667                 | REPLICA                       { $$ = make_str("replica"); }
1668                 | RESET                         { $$ = make_str("reset"); }
1669                 | RESTART                       { $$ = make_str("restart"); }
1670                 | RESTRICT                      { $$ = make_str("restrict"); }
1671                 | RETURNS                       { $$ = make_str("returns"); }
1672                 | REVOKE                        { $$ = make_str("revoke"); }
1673                 | ROLE                          { $$ = make_str("role"); }
1674                 | ROLLBACK                      { $$ = make_str("rollback"); }
1675                 | ROWS                          { $$ = make_str("rows"); }
1676                 | RULE                          { $$ = make_str("rule"); }
1677                 | SAVEPOINT                     { $$ = make_str("savepoint"); }
1678                 | SCHEMA                        { $$ = make_str("schema"); }
1679                 | SCROLL                        { $$ = make_str("scroll"); }
1680                 | SEARCH                        { $$ = make_str("search"); }
1681 /*              | SECOND_P                      { $$ = make_str("second"); }*/
1682                 | SEQUENCE                      { $$ = make_str("sequence"); }
1683                 | SERIALIZABLE          { $$ = make_str("serializable"); }
1684                 | SESSION                       { $$ = make_str("session"); }
1685                 | SET                           { $$ = make_str("set"); }
1686                 | SHARE                         { $$ = make_str("share"); }
1687                 | SHOW                          { $$ = make_str("show"); }
1688                 | SIMPLE                        { $$ = make_str("simple"); }
1689                 | STABLE                        { $$ = make_str("stable"); }
1690                 | STANDALONE_P                  { $$ = make_str("standalone"); }
1691                 | START                         { $$ = make_str("start"); }
1692                 | STATEMENT                     { $$ = make_str("statement"); }
1693                 | STATISTICS            { $$ = make_str("statistics"); }
1694                 | STDIN                         { $$ = make_str("stdin"); }
1695                 | STDOUT                        { $$ = make_str("stdout"); }
1696                 | STORAGE                       { $$ = make_str("storage"); }
1697                 | STRICT_P                      { $$ = make_str("strict"); }
1698                 | STRIP_P                       { $$ = make_str("strip"); }
1699                 | SUPERUSER_P           { $$ = make_str("superuser"); }
1700                 | SYSTEM_P                      { $$ = make_str("system"); }
1701                 | SYSID                         { $$ = make_str("sysid"); }
1702                 | TABLESPACE            { $$ = make_str("tablespace"); }
1703                 | TEMP                          { $$ = make_str("temp"); }
1704                 | TEMPLATE                      { $$ = make_str("template"); }
1705                 | TEMPORARY                     { $$ = make_str("temporary"); }
1706                 | TEXT_P                        { $$ = make_str("text"); }
1707                 | TRANSACTION           { $$ = make_str("transaction"); }
1708                 | TRIGGER                       { $$ = make_str("trigger"); }
1709                 | TRUNCATE                      { $$ = make_str("truncate"); }
1710                 | TRUSTED                       { $$ = make_str("trusted"); }
1711                 | TYPE_P                        { $$ = make_str("type"); }
1712                 | UNCOMMITTED           { $$ = make_str("uncommitted"); }
1713                 | UNENCRYPTED           { $$ = make_str("unencrypted"); }
1714                 | UNKNOWN                       { $$ = make_str("unknown"); }
1715                 | UNLISTEN                      { $$ = make_str("unlisten"); }
1716                 | UNTIL                         { $$ = make_str("until"); }
1717                 | UPDATE                        { $$ = make_str("update"); }
1718                 | VACUUM                        { $$ = make_str("vacuum"); }
1719                 | VALID                         { $$ = make_str("valid"); }
1720                 | VALIDATOR                     { $$ = make_str("validator"); }
1721                 | VALUE_P                       { $$ = make_str("value"); }
1722                 | VARYING                       { $$ = make_str("varying"); }
1723                 | VERSION_P                     { $$ = make_str("version"); }
1724                 | VIEW                          { $$ = make_str("view"); }
1725                 | VOLATILE                      { $$ = make_str("volatile"); }
1726                 | WHITESPACE_P                  { $$ = make_str("whitespace"); }
1727                 | WITHOUT                       { $$ = make_str("without"); }
1728                 | WORK                          { $$ = make_str("work"); }
1729                 | WRITE                         { $$ = make_str("write"); }
1730                 | XML_P                         { $$ = make_str("xml"); }
1731                 | YES_P                         { $$ = make_str("yes"); }
1732 /*              | YEAR_P                        { $$ = make_str("year"); }*/
1733                 | ZONE                          { $$ = make_str("zone"); }
1734                 ;
1735
1736 into_list : coutputvariable | into_list ',' coutputvariable
1737                 ;
1738
1739 ecpgstart: SQL_START    {
1740                                 reset_variables();
1741                                 pacounter = 1;
1742                         }
1743                 ;
1744
1745 c_args: /*EMPTY*/               { $$ = EMPTY; }
1746                 | c_list                { $$ = $1; }
1747                 ;
1748
1749 coutputvariable: cvariable indicator
1750                         { add_variable_to_head(&argsresult, find_variable($1), find_variable($2)); }
1751                 | cvariable
1752                         { add_variable_to_head(&argsresult, find_variable($1), &no_indicator); }
1753                 ;
1754
1755
1756 civarind: cvariable indicator
1757                 {
1758                         if (find_variable($2)->type->type == ECPGt_array)
1759                                 mmerror(PARSE_ERROR, ET_ERROR, "arrays of indicators are not allowed on input");
1760
1761                         add_variable_to_head(&argsinsert, find_variable($1), find_variable($2));
1762                         $$ = create_questionmarks($1, false);
1763                 }
1764                 ;
1765
1766 civar: cvariable
1767                 {
1768                         add_variable_to_head(&argsinsert, find_variable($1), &no_indicator);
1769                         $$ = create_questionmarks($1, false);
1770                 }
1771                 ;
1772
1773 indicator: cvariable                            { check_indicator((find_variable($1))->type); $$ = $1; }
1774                 | SQL_INDICATOR cvariable       { check_indicator((find_variable($2))->type); $$ = $2; }
1775                 | SQL_INDICATOR name            { check_indicator((find_variable($2))->type); $$ = $2; }
1776                 ;
1777
1778 cvariable:      CVARIABLE
1779                 {
1780                         /* As long as multidimensional arrays are not implemented we have to check for those here */
1781                         char *ptr = $1;
1782                         int brace_open=0, brace = false;
1783
1784                         for (; *ptr; ptr++)
1785                         {
1786                                 switch (*ptr)
1787                                 {
1788                                         case '[':
1789                                                         if (brace)
1790                                                                 mmerror(PARSE_ERROR, ET_FATAL, "no multidimensional array support for simple data types");
1791                                                         brace_open++;
1792                                                         break;
1793                                         case ']':
1794                                                         brace_open--;
1795                                                         if (brace_open == 0)
1796                                                                 brace = true;
1797                                                         break;
1798                                         case '\t':
1799                                         case ' ':
1800                                                         break;
1801                                         default:
1802                                                         if (brace_open == 0)
1803                                                                 brace = false;
1804                                                         break;
1805                                 }
1806                         }
1807                         $$ = $1;
1808                 }
1809                 ;
1810
1811 ecpg_param:     PARAM           { $$ = make_name(); } ;
1812
1813 ecpg_bconst:    BCONST          { $$ = make_name(); } ;
1814
1815 ecpg_fconst:    FCONST          { $$ = make_name(); } ;
1816
1817 ecpg_sconst:
1818                 SCONST
1819                 {
1820                         /* could have been input as '' or $$ */
1821                         $$ = (char *)mm_alloc(strlen($1) + 3);
1822                         $$[0]='\'';
1823                         strcpy($$+1, $1);
1824                         $$[strlen($1)+1]='\'';
1825                         $$[strlen($1)+2]='\0';
1826                         free($1);
1827                 }
1828                 | ECONST
1829                 {
1830                         $$ = (char *)mm_alloc(strlen($1) + 4);
1831                         $$[0]='E';
1832                         $$[1]='\'';
1833                         strcpy($$+2, $1);
1834                         $$[strlen($1)+2]='\'';
1835                         $$[strlen($1)+3]='\0';
1836                         free($1);
1837                 }
1838                 | NCONST
1839                 {
1840                         $$ = (char *)mm_alloc(strlen($1) + 4);
1841                         $$[0]='N';
1842                         $$[1]='\'';
1843                         strcpy($$+2, $1);
1844                         $$[strlen($1)+2]='\'';
1845                         $$[strlen($1)+3]='\0';
1846                         free($1);
1847                 }
1848                 | UCONST        { $$ = $1; }
1849                 | DOLCONST      { $$ = $1; }
1850                 ;
1851
1852 ecpg_xconst:    XCONST          { $$ = make_name(); } ;
1853
1854 ecpg_ident:     IDENT           { $$ = make_name(); }
1855                 | CSTRING       { $$ = make3_str(make_str("\""), $1, make_str("\"")) }
1856                 | UIDENT        { $$ = $1; }
1857                 ;
1858
1859 quoted_ident_stringvar: name
1860                         { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
1861                 | char_variable
1862                         { $$ = make3_str(make_str("("), $1, make_str(")")); }
1863                 ;
1864
1865 /*
1866  * C stuff
1867  */
1868
1869 c_stuff_item: c_anything                        { $$ = $1; }
1870                 | '(' ')'                       { $$ = make_str("()"); }
1871                 | '(' c_stuff ')'
1872                         { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
1873                 ;
1874
1875 c_stuff: c_stuff_item                   { $$ = $1; }
1876                 | c_stuff c_stuff_item
1877                         { $$ = cat2_str($1, $2); }
1878                 ;
1879
1880 c_list: c_term                          { $$ = $1; }
1881                 | c_list ',' c_term     { $$ = cat_str(3, $1, make_str(","), $3); }
1882                 ;
1883
1884 c_term:  c_stuff                        { $$ = $1; }
1885                 | '{' c_list '}'        { $$ = cat_str(3, make_str("{"), $2, make_str("}")); }
1886                 ;
1887
1888 c_thing:        c_anything              { $$ = $1; }
1889                 |       '('             { $$ = make_str("("); }
1890                 |       ')'             { $$ = make_str(")"); }
1891                 |       ','             { $$ = make_str(","); }
1892                 |       ';'             { $$ = make_str(";"); }
1893                 ;
1894
1895 c_anything:  ecpg_ident                         { $$ = $1; }
1896                 | Iconst                        { $$ = $1; }
1897                 | ecpg_fconst                   { $$ = $1; }
1898                 | ecpg_sconst                   { $$ = $1; }
1899                 | '*'                           { $$ = make_str("*"); }
1900                 | '+'                           { $$ = make_str("+"); }
1901                 | '-'                           { $$ = make_str("-"); }
1902                 | '/'                           { $$ = make_str("/"); }
1903                 | '%'                           { $$ = make_str("%"); }
1904                 | NULL_P                        { $$ = make_str("NULL"); }
1905                 | S_ADD                         { $$ = make_str("+="); }
1906                 | S_AND                         { $$ = make_str("&&"); }
1907                 | S_ANYTHING                    { $$ = make_name(); }
1908                 | S_AUTO                        { $$ = make_str("auto"); }
1909                 | S_CONST                       { $$ = make_str("const"); }
1910                 | S_DEC                         { $$ = make_str("--"); }
1911                 | S_DIV                         { $$ = make_str("/="); }
1912                 | S_DOTPOINT                    { $$ = make_str(".*"); }
1913                 | S_EQUAL                       { $$ = make_str("=="); }
1914                 | S_EXTERN                      { $$ = make_str("extern"); }
1915                 | S_INC                         { $$ = make_str("++"); }
1916                 | S_LSHIFT                      { $$ = make_str("<<"); }
1917                 | S_MEMBER                      { $$ = make_str("->"); }
1918                 | S_MEMPOINT                    { $$ = make_str("->*"); }
1919                 | S_MOD                         { $$ = make_str("%="); }
1920                 | S_MUL                         { $$ = make_str("*="); }
1921                 | S_NEQUAL                      { $$ = make_str("!="); }
1922                 | S_OR                          { $$ = make_str("||"); }
1923                 | S_REGISTER                    { $$ = make_str("register"); }
1924                 | S_RSHIFT                      { $$ = make_str(">>"); }
1925                 | S_STATIC                      { $$ = make_str("static"); }
1926                 | S_SUB                         { $$ = make_str("-="); }
1927                 | S_TYPEDEF                     { $$ = make_str("typedef"); }
1928                 | S_VOLATILE                    { $$ = make_str("volatile"); }
1929                 | SQL_BOOL                      { $$ = make_str("bool"); }
1930                 | ENUM_P                        { $$ = make_str("enum"); }
1931                 | HOUR_P                        { $$ = make_str("hour"); }
1932                 | INT_P                         { $$ = make_str("int"); }
1933                 | SQL_LONG                      { $$ = make_str("long"); }
1934                 | MINUTE_P                      { $$ = make_str("minute"); }
1935                 | MONTH_P                       { $$ = make_str("month"); }
1936                 | SECOND_P                      { $$ = make_str("second"); }
1937                 | SQL_SHORT                     { $$ = make_str("short"); }
1938                 | SQL_SIGNED                    { $$ = make_str("signed"); }
1939                 | SQL_STRUCT                    { $$ = make_str("struct"); }
1940                 | SQL_UNSIGNED                  { $$ = make_str("unsigned"); }
1941                 | YEAR_P                        { $$ = make_str("year"); }
1942                 | CHAR_P                        { $$ = make_str("char"); }
1943                 | FLOAT_P                       { $$ = make_str("float"); }
1944                 | TO                            { $$ = make_str("to"); }
1945                 | UNION                         { $$ = make_str("union"); }
1946                 | VARCHAR                       { $$ = make_str("varchar"); }
1947                 | '['                           { $$ = make_str("["); }
1948                 | ']'                           { $$ = make_str("]"); }
1949                 | '='                           { $$ = make_str("="); }
1950                 | ':'                           { $$ = make_str(":"); }
1951                 ;
1952
1953 DeallocateStmt: DEALLOCATE prepared_name                { $$ = $2; }
1954                 | DEALLOCATE PREPARE prepared_name      { $$ = $3; }
1955                 | DEALLOCATE ALL                        { $$ = make_str("all"); }
1956                 | DEALLOCATE PREPARE ALL                { $$ = make_str("all"); }
1957                 ;
1958
1959 Iresult:        Iconst                  { $$ = $1; }
1960                 | '(' Iresult ')'       { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
1961                 | Iresult '+' Iresult   { $$ = cat_str(3, $1, make_str("+"), $3); }
1962                 | Iresult '-' Iresult   { $$ = cat_str(3, $1, make_str("-"), $3); }
1963                 | Iresult '*' Iresult   { $$ = cat_str(3, $1, make_str("*"), $3); }
1964                 | Iresult '/' Iresult   { $$ = cat_str(3, $1, make_str("/"), $3); }
1965                 | Iresult '%' Iresult   { $$ = cat_str(3, $1, make_str("%"), $3); }
1966                 | ecpg_sconst           { $$ = $1; }
1967                 | ColId                 { $$ = $1; }
1968                 ;
1969
1970 execute_rest: /* EMPTY */       { $$ = EMPTY; }
1971         | ecpg_using ecpg_into  { $$ = EMPTY; }
1972         | ecpg_into ecpg_using  { $$ = EMPTY; }
1973         | ecpg_using            { $$ = EMPTY; }
1974         | ecpg_into             { $$ = EMPTY; }
1975         ; 
1976
1977 ecpg_into: INTO into_list       { $$ = EMPTY; }
1978         | into_descriptor       { $$ = $1; }
1979         ;
1980
1981 %%
1982
1983 void base_yyerror(const char * error)
1984 {
1985         char buf[1024];
1986
1987         snprintf(buf,sizeof buf, _("%s at or near \"%s\""), error, token_start ? token_start : yytext);
1988         buf[sizeof(buf)-1]=0;
1989         mmerror(PARSE_ERROR, ET_ERROR, buf);
1990 }
1991
1992 void parser_init(void)
1993 {
1994  /* This function is empty. It only exists for compatibility with the backend parser right now. */
1995 }
1996
1997 /*
1998  * Must undefine base_yylex before including pgc.c, since we want it
1999  * to create the function base_yylex not filtered_base_yylex.
2000  */
2001 #undef base_yylex
2002
2003 #include "pgc.c"