]> granicus.if.org Git - postgresql/commitdiff
Added files containing changes between gram.y and preproc.y.
authorMichael Meskes <meskes@postgresql.org>
Fri, 14 Nov 2008 10:03:33 +0000 (10:03 +0000)
committerMichael Meskes <meskes@postgresql.org>
Fri, 14 Nov 2008 10:03:33 +0000 (10:03 +0000)
src/interfaces/ecpg/preproc/ecpg.addons [new file with mode: 0644]
src/interfaces/ecpg/preproc/ecpg.header [new file with mode: 0644]
src/interfaces/ecpg/preproc/ecpg.tokens [new file with mode: 0644]
src/interfaces/ecpg/preproc/ecpg.trailer [new file with mode: 0644]
src/interfaces/ecpg/preproc/ecpg.type [new file with mode: 0644]

diff --git a/src/interfaces/ecpg/preproc/ecpg.addons b/src/interfaces/ecpg/preproc/ecpg.addons
new file mode 100644 (file)
index 0000000..e060ceb
--- /dev/null
@@ -0,0 +1,382 @@
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.addons,v 1.1 2008/11/14 10:03:33 meskes Exp $ */
+
+ECPG: stmtClosePortalStmt block
+       {
+               if (INFORMIX_MODE)
+               {
+                       if (pg_strcasecmp($1+strlen("close "), "database") == 0)
+                       {
+                               if (connection)
+                                       mmerror(PARSE_ERROR, ET_ERROR, "no at option for close database statement\n");
+
+                               fprintf(yyout, "{ ECPGdisconnect(__LINE__, \"CURRENT\");");
+                               whenever_action(2);
+                               free($1);
+                               break;
+                       }
+               }
+
+               output_statement($1, 0, ECPGst_normal);
+       }
+ECPG: stmtDeallocateStmt block
+       {
+               if (connection)
+                       mmerror(PARSE_ERROR, ET_ERROR, "no at option for deallocate statement\n");
+
+               output_deallocate_prepare_statement($1);
+       }
+ECPG: stmtDeclareCursorStmt block
+       { output_simple_statement($1); }
+ECPG: stmtDeleteStmt block
+ECPG: stmtDiscardStmt block
+ECPG: stmtFetchStmt block
+ECPG: stmtInsertStmt block
+ECPG: stmtSelectStmt block
+ECPG: stmtUpdateStmt block
+       { output_statement($1, 1, ECPGst_normal); }
+ECPG: stmtExecuteStmt block
+       { output_statement($1, 1, ECPGst_execute); }
+ECPG: stmtPrepareStmt block
+       {
+               if ($1.type == NULL || strlen($1.type) == 0)
+                       output_prepare_statement($1.name, $1.stmt);
+               else    
+                       output_statement(cat_str(5, make_str("prepare"), $1.name, $1.type, make_str("as"), $1.stmt), 0, ECPGst_normal);
+       }
+ECPG: stmtTransactionStmt block
+       {
+               fprintf(yyout, "{ ECPGtrans(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1);
+               whenever_action(2);
+               free($1);
+       }
+ECPG: stmtViewStmt rule
+       | ECPGAllocateDescr
+       {
+               fprintf(yyout,"ECPGallocate_desc(__LINE__, %s);",$1);
+               whenever_action(0);
+               free($1);
+       }
+       | ECPGConnect
+       {
+               if (connection)
+                       mmerror(PARSE_ERROR, ET_ERROR, "no at option for connect statement\n");
+
+               fprintf(yyout, "{ ECPGconnect(__LINE__, %d, %s, %d); ", compat, $1, autocommit);
+               reset_variables();
+               whenever_action(2);
+               free($1);
+       }
+       | ECPGCursorStmt
+       {
+               output_simple_statement($1);
+       }
+       | ECPGDeallocateDescr
+       {
+               if (connection)
+                       mmerror(PARSE_ERROR, ET_ERROR, "no at option for deallocate statement\n");
+               fprintf(yyout,"ECPGdeallocate_desc(__LINE__, %s);",$1);
+               whenever_action(0);
+               free($1);
+       }
+       | ECPGDeclare
+       {
+               output_simple_statement($1);
+       }
+       | ECPGDescribe
+       {
+               fprintf(yyout, "{ ECPGdescribe(__LINE__, %s,", $1);
+               dump_variables(argsresult, 1);
+               fputs("ECPGt_EORT);", yyout);
+               fprintf(yyout, "}");
+               output_line_number();
+
+               free($1);
+       }
+       | ECPGDisconnect
+       {
+               if (connection)
+                       mmerror(PARSE_ERROR, ET_ERROR, "no at option for disconnect statement\n");
+
+               fprintf(yyout, "{ ECPGdisconnect(__LINE__, %s);",
+                               $1 ? $1 : "\"CURRENT\"");
+               whenever_action(2);
+               free($1);
+       }
+       | ECPGExecuteImmediateStmt      { output_statement($1, 0, ECPGst_exec_immediate); }
+       | ECPGFree
+       {
+               const char *con = connection ? connection : "NULL";
+               if (strcmp($1, "all"))
+                       fprintf(yyout, "{ ECPGdeallocate(__LINE__, %d, %s, \"%s\");", compat, con, $1);
+               else
+                       fprintf(yyout, "{ ECPGdeallocate_all(__LINE__, %d, %s);", compat, con);
+
+               whenever_action(2);
+               free($1);
+       }
+       | ECPGGetDescriptor
+       {
+               lookup_descriptor($1.name, connection);
+               output_get_descr($1.name, $1.str);
+               free($1.name);
+               free($1.str);
+       }
+       | ECPGGetDescriptorHeader
+       {
+               lookup_descriptor($1, connection);
+               output_get_descr_header($1);
+               free($1);
+       }
+       | ECPGOpen
+       {
+               struct cursor *ptr;
+
+               if ((ptr = add_additional_variables($1, true)) != NULL)
+               {
+                       connection = ptr->connection ? mm_strdup(ptr->connection) : NULL;
+                       output_statement(mm_strdup(ptr->command), 0, 0);
+                       ptr->opened = true;
+               }
+       }
+       | ECPGSetAutocommit
+       {
+               fprintf(yyout, "{ ECPGsetcommit(__LINE__, \"%s\", %s);", $1, connection ? connection : "NULL");
+               whenever_action(2);
+               free($1);
+       }
+       | ECPGSetConnection
+       {
+               if (connection)
+                       mmerror(PARSE_ERROR, ET_ERROR, "no at option for set connection statement\n");
+
+               fprintf(yyout, "{ ECPGsetconn(__LINE__, %s);", $1);
+               whenever_action(2);
+               free($1);
+       }
+       | ECPGSetDescriptor
+       {
+               lookup_descriptor($1.name, connection);
+               output_set_descr($1.name, $1.str);
+               free($1.name);
+               free($1.str);
+       }
+       | ECPGSetDescriptorHeader
+       {
+               lookup_descriptor($1, connection);
+               output_set_descr_header($1);
+               free($1);
+       }
+       | ECPGTypedef
+       {
+               if (connection)
+                       mmerror(PARSE_ERROR, ET_ERROR, "no at option for typedef statement\n");
+
+               fprintf(yyout, "%s", $1);
+               free($1);
+               output_line_number();
+       }
+       | ECPGVar
+       {
+               if (connection)
+                       mmerror(PARSE_ERROR, ET_ERROR, "no at option for var statement\n");
+
+               output_simple_statement($1);
+       }
+       | ECPGWhenever
+       {
+               if (connection)
+                       mmerror(PARSE_ERROR, ET_ERROR, "no at option for whenever statement\n");
+
+               output_simple_statement($1);
+       }
+ECPG: CopyStmtCOPYopt_binaryqualified_nameopt_column_listopt_oidscopy_fromcopy_file_namecopy_delimiteropt_withcopy_opt_list addon
+                       if (strcmp($6, "to") == 0 && strcmp($7, "stdin") == 0)
+                               mmerror(PARSE_ERROR, ET_ERROR, "copy to stdin not possible\n");
+                       else if (strcmp($6, "from") == 0 && strcmp($7, "stdout") == 0)
+                               mmerror(PARSE_ERROR, ET_ERROR, "copy from stdout not possible\n");
+                       else if (strcmp($6, "from") == 0 && strcmp($7, "stdin") == 0)
+                               mmerror(PARSE_ERROR, ET_WARNING, "copy from stdin not implemented\n");
+ECPG: CopyStmtCOPYselect_with_parensTOcopy_file_nameopt_withcopy_opt_list addon
+                       if (strcmp($4, "stdin") == 0)
+                               mmerror(PARSE_ERROR, ET_ERROR, "copy to stdin not possible\n");
+ECPG: ConstraintAttributeSpecConstraintDeferrabilitySpecConstraintTimeSpec addon
+                       if (strcmp($1, "deferrable") != 0 && strcmp($2, "initially deferrable") == 0 )
+                               mmerror(PARSE_ERROR, ET_ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE\n");
+ECPG: ConstraintAttributeSpecConstraintTimeSpecConstraintDeferrabilitySpec addon
+                       if (strcmp($2, "deferrable") != 0 && strcmp($1, "initially deferrable") == 0 )
+                               mmerror(PARSE_ERROR, ET_ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE\n");
+ECPG: var_valueNumericOnly addon
+ECPG: fetch_directionSignedIconst addon
+               if ($1[1] == '$')
+               {
+                       free($1);
+                       $1 = make_str("$0");
+               }
+ECPG: fetch_directionABSOLUTE_PSignedIconst addon
+ECPG: fetch_directionRELATIVE_PSignedIconst addon
+ECPG: fetch_directionFORWARDSignedIconst addon
+ECPG: fetch_directionBACKWARDSignedIconst addon
+               if ($2[1] == '$')
+               {
+                       free($2);
+                       $2 = make_str("$0");
+               }
+ECPG: PrepareStmtPREPAREprepared_nameprep_type_clauseASPreparableStmt block
+       {
+               $$.name = $2;
+               $$.type = $3;
+               $$.stmt = cat_str(3, make_str("\""), $5, make_str("\""));
+       }
+       | PREPARE prepared_name FROM execstring
+       {
+               $$.name = $2;
+               $$.type = NULL;
+               $$.stmt = $4;
+       }
+ECPG: ExecuteStmtEXECUTEprepared_nameexecute_param_clauseexecute_rest block
+       { $$ = $2; }
+ECPG: DeclareCursorStmtDECLAREnamecursor_optionsCURSORopt_holdFORSelectStmt block
+       {
+               struct cursor *ptr, *this;
+
+               for (ptr = cur; ptr != NULL; ptr = ptr->next)
+               {
+                       if (strcmp($2, ptr->name) == 0)
+                               mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" already defined\n", $2);
+               }
+
+               this = (struct cursor *) mm_alloc(sizeof(struct cursor));
+
+               this->next = cur;
+               this->name = $2;
+               this->connection = connection;
+               this->opened = false;
+               this->command =  cat_str(7, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for"), $7);
+               this->argsinsert = argsinsert;
+               this->argsresult = argsresult;
+               argsinsert = argsresult = NULL;
+               cur = this;
+
+               if (INFORMIX_MODE)
+                       $$ = cat_str(5, adjust_informix(this->argsinsert), adjust_informix(this->argsresult), make_str("/*"), mm_strdup(this->command), make_str("*/"));
+               else
+                       $$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
+       }
+ECPG: opt_hold block
+       {
+               if (compat == ECPG_COMPAT_INFORMIX_SE && autocommit == true)
+                       $$ = make_str("with hold");
+               else
+                       $$ = EMPTY;
+       }
+ECPG: into_clauseINTOOptTempTableName block
+                                       {
+                                               FoundInto = 1;
+                                               $$= cat2_str(make_str("into"), $2);
+                                       }
+       | ecpg_into                     { $$ = EMPTY; }
+ECPG: table_refselect_with_parens addon
+               mmerror(PARSE_ERROR, ET_ERROR, "sub-SELECT in FROM must have an alias\n");
+ECPG: TypenameSimpleTypenameopt_array_bounds block
+       {       $$ = cat2_str($1, $2.str); }
+ECPG: TypenameSETOFSimpleTypenameopt_array_bounds block
+       {       $$ = $$ = cat_str(3, make_str("setof"), $2, $3.str); }
+ECPG: opt_array_boundsopt_array_bounds'['']' block
+       {
+               $$.index1 = $1.index1;
+               $$.index2 = $1.index2;
+               if (strcmp($$.index1, "-1") == 0)
+                       $$.index1 = make_str("0");
+               else if (strcmp($1.index2, "-1") == 0)
+                       $$.index2 = make_str("0");
+               $$.str = cat_str(2, $1.str, make_str("[]"));
+       }
+       | opt_array_bounds '[' Iresult ']'
+       {
+               $$.index1 = $1.index1;
+               $$.index2 = $1.index2;
+               if (strcmp($1.index1, "-1") == 0)
+                       $$.index1 = strdup($3);
+               else if (strcmp($1.index2, "-1") == 0)
+                       $$.index2 = strdup($3);
+               $$.str = cat_str(4, $1.str, make_str("["), $3, make_str("]"));
+       }
+ECPG: opt_array_bounds
+       {
+               $$.index1 = make_str("-1");
+               $$.index2 = make_str("-1");
+               $$.str= EMPTY;
+       }
+ECPG: IconstICONST block
+       { $$ = make_name(); }
+ECPG: AexprConstNULL_P rule
+       | civar                 { $$ = $1; }
+       | civarind              { $$ = $1; }
+ECPG: ColIdcol_name_keyword rule
+       | ECPGKeywords                  { $$ = $1; }
+       | ECPGCKeywords                 { $$ = $1; }
+       | CHAR_P                        { $$ = make_str("char"); }
+       | VALUES                        { $$ = make_str("values"); }
+ECPG: type_function_nametype_func_name_keyword rule
+       | ECPGKeywords                          { $$ = $1; }
+       | ECPGTypeName                          { $$ = $1; }
+       | ECPGCKeywords                         { $$ = $1; }
+ECPG: VariableShowStmtSHOWALL block
+       {
+               mmerror(PARSE_ERROR, ET_ERROR, "SHOW ALL not implemented\n");
+               $$ = EMPTY;
+       }
+ECPG: FetchStmtFETCHfetch_directionfrom_inname block 
+       {
+               add_additional_variables($4, false);
+               $$ = cat_str(4, make_str("fetch"), $2, $3, $4);
+       }
+ECPG: FetchStmtFETCHname block
+       {
+               add_additional_variables($2, false);
+               $$ = cat_str(2, make_str("fetch"), $2);
+       }
+ECPG: FetchStmtMOVEname rule
+       | FETCH fetch_direction from_in name ecpg_into
+               {
+                       add_additional_variables($4, false);
+                       $$ = cat_str(4, make_str("fetch"), $2, $3, $4);
+               }
+       | FETCH fetch_direction name ecpg_into
+               {
+                       add_additional_variables($3, false);
+                       $$ = cat_str(4, make_str("fetch"), $2, make_str("from"), $3);
+               }
+       | FETCH from_in name ecpg_into
+               {
+                       add_additional_variables($3, false);
+                       $$ = cat_str(3, make_str("fetch"), $2, $3);
+               }
+       | FETCH name ecpg_into
+               {
+                       add_additional_variables($2, false);
+                       $$ = cat2_str(make_str("fetch"), $2);
+               }
+       | FETCH fetch_direction name
+               {
+                       add_additional_variables($3, false);
+                       $$ = cat_str(4, make_str("fetch"), $2, make_str("from"), $3);
+               }
+       | FETCH from_in name
+               {
+                       add_additional_variables($3, false);
+                       $$ = cat_str(3, make_str("fetch"), $2, $3);
+               }
+ECPG: SpecialRuleRelationOLD addon
+               if (!QueryIsRule)
+                       mmerror(PARSE_ERROR, ET_ERROR, "OLD used in non-rule query\n");
+ECPG: SpecialRuleRelationNEW addon
+               if (!QueryIsRule)
+                       mmerror(PARSE_ERROR, ET_ERROR, "NEW used in non-rule query\n");
+ECPG: select_limitLIMITselect_limit_value','select_offset_value block
+        {
+                mmerror(PARSE_ERROR, ET_WARNING, "no longer supported LIMIT #,# syntax passed to backend");
+                $$ = cat_str(4, make_str("limit"), $2, make_str(","), $4);
+        }
+ECPG: SignedIconstIconst rule
+       | civar { $$ = $1; }
diff --git a/src/interfaces/ecpg/preproc/ecpg.header b/src/interfaces/ecpg/preproc/ecpg.header
new file mode 100644 (file)
index 0000000..6e47fa0
--- /dev/null
@@ -0,0 +1,390 @@
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.header,v 1.1 2008/11/14 10:03:33 meskes Exp $ */
+
+/* Copyright comment */
+%{
+#include "postgres_fe.h"
+
+#include "extern.h"
+#include <unistd.h>
+
+/* Location tracking support --- simpler than bison's default */
+#define YYLLOC_DEFAULT(Current, Rhs, N) \
+       do { \
+                if (N) \
+                       (Current) = (Rhs)[1]; \
+               else \
+                       (Current) = (Rhs)[0]; \
+       } while (0)
+
+/*
+ * The %name-prefix option below will make bison call base_yylex, but we
+ * really want it to call filtered_base_yylex (see parser.c).
+ */
+#define base_yylex filtered_base_yylex
+
+/*
+ * Variables containing simple states.
+ */
+int struct_level = 0;
+int braces_open; /* brace level counter */
+int ecpg_informix_var = 0;
+char   *connection = NULL;
+char   *input_filename = NULL;
+
+static int     QueryIsRule = 0, FoundInto = 0;
+static int     initializer = 0;
+static int     pacounter = 1;
+static char     pacounter_buffer[sizeof(int) * CHAR_BIT * 10 / 3]; /* a rough guess at the size we need */
+static struct this_type actual_type[STRUCT_DEPTH];
+static char *actual_startline[STRUCT_DEPTH];
+
+/* temporarily store struct members while creating the data structure */
+struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH] = { NULL };
+
+/* also store struct type so we can do a sizeof() later */
+static char *ECPGstruct_sizeof = NULL;
+
+/* for forward declarations we have to store some data as well */
+static char *forward_name = NULL;
+
+struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, NULL, NULL, {NULL}, 0};
+struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL};
+
+struct ECPGtype ecpg_query = {ECPGt_char_variable, NULL, NULL, {NULL}, 0};
+
+/*
+ * Handle parsing errors and warnings
+ */
+void
+mmerror(int error_code, enum errortype type, char * error, ...)
+{
+       va_list ap;
+
+       /* internationalize the error message string */
+       error = _(error);
+
+       fprintf(stderr, "%s:%d: ", input_filename, yylineno);
+
+       switch(type)
+       {
+               case ET_WARNING:
+                       fprintf(stderr, _("WARNING: "));
+                       break;
+               case ET_ERROR:
+               case ET_FATAL:
+                       fprintf(stderr, _("ERROR: "));
+                       break;
+       }
+
+       va_start(ap, error);
+       vfprintf(stderr, error, ap);
+       va_end(ap);
+
+       fprintf(stderr, "\n");
+
+       switch(type)
+       {
+               case ET_WARNING:
+                       break;
+               case ET_ERROR:
+                       ret_value = error_code;
+                       break;
+               case ET_FATAL:
+                       if (yyin)
+                               fclose(yyin);
+                       if (yyout)
+                               fclose(yyout);
+                       if (unlink(output_filename) != 0 && *output_filename != '-')
+                               fprintf(stderr, _("could not remove output file \"%s\"\n"), output_filename);
+                       exit(error_code);
+       }
+}
+
+/*
+ * string concatenation
+ */
+
+static char *
+cat2_str(char *str1, char *str2)
+{
+       char * res_str  = (char *)mm_alloc(strlen(str1) + strlen(str2) + 2);
+
+       strcpy(res_str, str1);
+       strcat(res_str, " ");
+       strcat(res_str, str2);
+       free(str1);
+       free(str2);
+       return(res_str);
+}
+
+static char *
+cat_str(int count, ...)
+{
+       va_list         args;
+       int                     i;
+       char            *res_str;
+
+       va_start(args, count);
+
+       res_str = va_arg(args, char *);
+
+       /* now add all other strings */
+       for (i = 1; i < count; i++)
+               res_str = cat2_str(res_str, va_arg(args, char *));
+
+       va_end(args);
+
+       return(res_str);
+}
+
+char *
+make_str(const char *str)
+{
+       char * res_str = (char *)mm_alloc(strlen(str) + 1);
+
+       strcpy(res_str, str);
+       return res_str;
+}
+
+static char *
+make2_str(char *str1, char *str2)
+{
+       char * res_str  = (char *)mm_alloc(strlen(str1) + strlen(str2) + 1);
+
+       strcpy(res_str, str1);
+       strcat(res_str, str2);
+       free(str1);
+       free(str2);
+       return(res_str);
+}
+
+static char *
+make3_str(char *str1, char *str2, char *str3)
+{
+       char * res_str  = (char *)mm_alloc(strlen(str1) + strlen(str2) +strlen(str3) + 1);
+
+       strcpy(res_str, str1);
+       strcat(res_str, str2);
+       strcat(res_str, str3);
+       free(str1);
+       free(str2);
+       free(str3);
+       return(res_str);
+}
+
+/* and the rest */
+static char *
+make_name(void)
+{
+       char * name = (char *)mm_alloc(yyleng + 1);
+
+       strncpy(name, yytext, yyleng);
+       name[yyleng] = '\0';
+       return(name);
+}
+
+static char *
+create_questionmarks(char *name, bool array)
+{
+       struct variable *p = find_variable(name);
+       int count;
+       char *result = EMPTY;
+
+       /* In case we have a struct, we have to print as many "?" as there are attributes in the struct
+        * An array is only allowed together with an element argument
+        * This is essantially only used for inserts, but using a struct as input parameter is an error anywhere else
+        * so we don't have to worry here. */
+
+       if (p->type->type == ECPGt_struct || (array && p->type->type == ECPGt_array && p->type->u.element->type == ECPGt_struct))
+       {
+               struct ECPGstruct_member *m;
+
+               if (p->type->type == ECPGt_struct)
+                       m = p->type->u.members;
+               else
+                       m = p->type->u.element->u.members;
+
+               for (count = 0; m != NULL; m=m->next, count++);
+       }
+       else
+               count = 1;
+
+       for (; count > 0; count --)
+       {
+               sprintf(pacounter_buffer, "$%d", pacounter++);
+               result = cat_str(3, result, strdup(pacounter_buffer), make_str(" , "));
+       }
+
+       /* removed the trailing " ," */
+
+       result[strlen(result)-3] = '\0';
+       return(result);
+}
+
+static char *
+adjust_informix(struct arguments *list)
+{
+       /* Informix accepts DECLARE with variables that are out of scope when OPEN is called.
+        * for instance you can declare variables in a function, and then subsequently use them
+        * {
+        *      declare_vars();
+        *      exec sql ... which uses vars declared in the above function
+        *
+        * This breaks standard and leads to some very dangerous programming.
+        * Since they do, we have to work around and accept their syntax as well.
+        * But we will do so ONLY in Informix mode.
+        * We have to change the variables to our own struct and just store the pointer instead of the variable
+        */
+
+        struct arguments *ptr;
+        char *result = make_str("");
+
+        for (ptr = list; ptr != NULL; ptr = ptr->next)
+        {
+               char temp[20]; /* this should be sufficient unless you have 8 byte integers */
+               char *original_var;
+
+               /* change variable name to "ECPG_informix_get_var(<counter>)" */
+               original_var = ptr->variable->name;
+               sprintf(temp, "%d))", ecpg_informix_var);
+
+               if ((ptr->variable->type->type != ECPGt_varchar && ptr->variable->type->type != ECPGt_char && ptr->variable->type->type != ECPGt_unsigned_char) && atoi(ptr->variable->type->size) > 1)
+               {
+                       ptr->variable = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->variable->type->u.element->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type, make_str("1"), ptr->variable->type->u.element->lineno), ptr->variable->type->size), 0);
+                       sprintf(temp, "%d, (", ecpg_informix_var++);
+               }
+               else if ((ptr->variable->type->type == ECPGt_varchar || ptr->variable->type->type == ECPGt_char || ptr->variable->type->type == ECPGt_unsigned_char) && atoi(ptr->variable->type->size) > 1)
+               {
+                       ptr->variable = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->variable->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->lineno), 0);
+                       sprintf(temp, "%d, (", ecpg_informix_var++);
+               }
+               else
+               {
+                       ptr->variable = new_variable(cat_str(4, make_str("*("), mm_strdup(ecpg_type_name(ptr->variable->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->lineno), 0);
+                       sprintf(temp, "%d, &(", ecpg_informix_var++);
+               }
+
+               /* create call to "ECPG_informix_set_var(<counter>, <pointer>. <linen number>)" */
+               result = cat_str(5, result, make_str("ECPG_informix_set_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n"));
+
+               /* now the indicator if there is one */
+               if (ptr->indicator->type->type != ECPGt_NO_INDICATOR)
+               {
+                       /* change variable name to "ECPG_informix_get_var(<counter>)" */
+                       original_var = ptr->indicator->name;
+                       sprintf(temp, "%d))", ecpg_informix_var);
+
+                       /* create call to "ECPG_informix_set_var(<counter>, <pointer>. <linen number>)" */
+                       if (atoi(ptr->indicator->type->size) > 1)
+                       {
+                               ptr->indicator = new_variable(cat_str(4, make_str("("), mm_strdup(ecpg_type_name(ptr->indicator->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size, ptr->variable->type->lineno), 0);
+                               sprintf(temp, "%d, (", ecpg_informix_var++);
+                       }
+                       else
+                       {
+                               ptr->indicator = new_variable(cat_str(4, make_str("*("), mm_strdup(ecpg_type_name(ptr->indicator->type->type)), make_str(" *)(ECPG_informix_get_var("), mm_strdup(temp)), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size, ptr->variable->type->lineno), 0);
+                               sprintf(temp, "%d, &(", ecpg_informix_var++);
+                       }
+                       result = cat_str(5, result, make_str("ECPG_informix_set_var("), mm_strdup(temp), mm_strdup(original_var), make_str("), __LINE__);\n"));
+               }
+        }
+
+        return result;
+}
+
+static struct cursor *
+add_additional_variables(char *name, bool insert)
+{
+       struct cursor *ptr;
+       struct arguments *p;
+
+       for (ptr = cur; ptr != NULL; ptr=ptr->next)
+       {
+               if (strcmp(ptr->name, name) == 0)
+                       break;
+       }
+
+       if (ptr == NULL)
+       {
+               mmerror(PARSE_ERROR, ET_ERROR, "trying to access an undeclared cursor \"%s\"\n", name);
+               return NULL;
+       }
+
+       if (insert)
+       {
+               /* add all those input variables that were given earlier
+                * note that we have to append here but have to keep the existing order */
+               for (p = ptr->argsinsert; p; p = p->next)
+                       add_variable_to_tail(&argsinsert, p->variable, p->indicator);
+       }
+
+       /* add all those output variables that were given earlier */
+       for (p = ptr->argsresult; p; p = p->next)
+               add_variable_to_tail(&argsresult, p->variable, p->indicator);
+
+       return ptr;
+}
+
+static void
+add_typedef(char *name, char * dimension, char * length, enum ECPGttype type_enum, char *type_dimension, char *type_index, int initializer, int array)
+{
+       /* add entry to list */
+       struct typedefs *ptr, *this;
+
+       if ((type_enum == ECPGt_struct ||
+            type_enum == ECPGt_union) &&
+           initializer == 1)
+               mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in typedef command");
+       else
+       {
+               for (ptr = types; ptr != NULL; ptr = ptr->next)
+               {
+                       if (strcmp(name, ptr->name) == 0)
+                               /* re-definition is a bug */
+                               mmerror(PARSE_ERROR, ET_ERROR, "type %s already defined", name);
+               }
+               adjust_array(type_enum, &dimension, &length, type_dimension, type_index, array, true);
+
+               this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
+
+               /* initial definition */
+               this->next = types;
+               this->name = name;
+               this->brace_level = braces_open;
+               this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
+               this->type->type_enum = type_enum;
+               this->type->type_str = mm_strdup(name);
+               this->type->type_dimension = dimension; /* dimension of array */
+               this->type->type_index = length;        /* length of string */
+               this->type->type_sizeof = ECPGstruct_sizeof;
+               this->struct_member_list = (type_enum == ECPGt_struct || type_enum == ECPGt_union) ?
+               ECPGstruct_member_dup(struct_member_list[struct_level]) : NULL;
+
+               if (type_enum != ECPGt_varchar &&
+                       type_enum != ECPGt_char &&
+                       type_enum != ECPGt_unsigned_char &&
+                       atoi(this->type->type_index) >= 0)
+                       mmerror(PARSE_ERROR, ET_ERROR, "no multidimensional array support for simple data types");
+
+               types = this;
+       }
+}
+%}
+
+%name-prefix="base_yy"
+%locations
+
+%union {
+       double  dval;
+       char    *str;
+       int     ival;
+       struct  when            action;
+       struct  index           index;
+       int             tagname;
+       struct  this_type       type;
+       enum    ECPGttype       type_enum;
+       enum    ECPGdtype       dtype_enum;
+       struct  fetch_desc      descriptor;
+       struct  su_symbol       struct_union;
+       struct  prep            prep;
+}
diff --git a/src/interfaces/ecpg/preproc/ecpg.tokens b/src/interfaces/ecpg/preproc/ecpg.tokens
new file mode 100644 (file)
index 0000000..9b51975
--- /dev/null
@@ -0,0 +1,28 @@
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.tokens,v 1.1 2008/11/14 10:03:33 meskes Exp $ */
+/* special embedded SQL token */
+%token  SQL_ALLOCATE SQL_AUTOCOMMIT SQL_BOOL SQL_BREAK
+                SQL_CALL SQL_CARDINALITY SQL_CONNECT
+                SQL_COUNT 
+                SQL_DATETIME_INTERVAL_CODE
+                SQL_DATETIME_INTERVAL_PRECISION SQL_DESCRIBE
+                SQL_DESCRIPTOR SQL_DISCONNECT SQL_FOUND
+                SQL_FREE SQL_GET SQL_GO SQL_GOTO SQL_IDENTIFIED
+                SQL_INDICATOR SQL_KEY_MEMBER SQL_LENGTH
+                SQL_LONG SQL_NULLABLE SQL_OCTET_LENGTH
+                SQL_OPEN SQL_OUTPUT SQL_REFERENCE
+                SQL_RETURNED_LENGTH SQL_RETURNED_OCTET_LENGTH SQL_SCALE
+                SQL_SECTION SQL_SHORT SQL_SIGNED SQL_SQL SQL_SQLERROR
+                SQL_SQLPRINT SQL_SQLWARNING SQL_START SQL_STOP
+                SQL_STRUCT SQL_UNSIGNED SQL_VAR SQL_WHENEVER
+
+/* C token */
+%token  S_ADD S_AND S_ANYTHING S_AUTO S_CONST S_DEC S_DIV
+                S_DOTPOINT S_EQUAL S_EXTERN S_INC S_LSHIFT S_MEMPOINT
+                S_MEMBER S_MOD S_MUL S_NEQUAL S_OR S_REGISTER S_RSHIFT
+                S_STATIC S_SUB S_VOLATILE
+                S_TYPEDEF
+
+%token TYPECAST
+%token CSTRING CVARIABLE CPP_LINE IP 
+%token DOLCONST ECONST NCONST UCONST UIDENT
+
diff --git a/src/interfaces/ecpg/preproc/ecpg.trailer b/src/interfaces/ecpg/preproc/ecpg.trailer
new file mode 100644 (file)
index 0000000..819c764
--- /dev/null
@@ -0,0 +1,2003 @@
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.trailer,v 1.1 2008/11/14 10:03:33 meskes Exp $ */
+
+statements: /*EMPTY*/
+                | statements statement
+                ;
+
+statement: ecpgstart at stmt ';'        { connection = NULL; }
+                | ecpgstart stmt ';'
+                | ecpgstart ECPGVarDeclaration
+                {
+                        fprintf(yyout, "%s", $2);
+                        free($2);
+                        output_line_number();
+                }
+                | ECPGDeclaration
+                | c_thing               { fprintf(yyout, "%s", $1); free($1); }
+                | CPP_LINE              { fprintf(yyout, "%s", $1); free($1); }
+                | '{'                   { braces_open++; fputs("{", yyout); }
+                | '}'                   { remove_typedefs(braces_open); remove_variables(braces_open--); fputs("}", yyout); }
+                ;
+
+CreateAsStmt: CREATE OptTemp TABLE create_as_target AS {FoundInto = 0;} SelectStmt opt_with_data
+               {
+                       if (FoundInto == 1)
+                               mmerror(PARSE_ERROR, ET_ERROR, "CREATE TABLE / AS SELECT cannot specify INTO\n");
+
+                       $$ = cat_str(6, make_str("create"), $2, make_str("table"), $4, make_str("as"), $7);
+               }
+       ;
+
+RuleStmt: CREATE opt_or_replace RULE name AS
+               {QueryIsRule = 1;}
+               ON event TO qualified_name where_clause
+               DO opt_instead RuleActionList
+               {
+                       QueryIsRule=0;
+                       $$ = 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);
+               }
+       ;
+
+at: AT connection_object
+                {
+                        connection = $2;
+                        /*
+                         *      Do we have a variable as connection target?
+                         *      Remove the variable from the variable
+                         *      list or else it will be used twice
+                         */
+                        if (argsinsert != NULL)
+                                argsinsert = NULL;
+                }
+        ;
+
+/*
+ * the exec sql connect statement: connect to the given database
+ */
+ECPGConnect: SQL_CONNECT TO connection_target opt_connection_name opt_user
+                       { $$ = cat_str(5, $3, make_str(","), $5, make_str(","), $4); }
+               | SQL_CONNECT TO DEFAULT
+                       { $$ = make_str("NULL, NULL, NULL, \"DEFAULT\""); }
+                 /* also allow ORACLE syntax */
+               | SQL_CONNECT ora_user
+                       { $$ = cat_str(3, make_str("NULL,"), $2, make_str(", NULL")); }
+               | DATABASE connection_target
+                       { $$ = cat2_str($2, make_str(", NULL, NULL, NULL")); }
+               ;
+
+connection_target: opt_database_name opt_server opt_port
+               {
+                       /* old style: dbname[@server][:port] */
+                       if (strlen($2) > 0 && *($2) != '@')
+                               mmerror(PARSE_ERROR, ET_ERROR, "expected \"@\", found \"%s\"", $2);
+                       
+                       /* C strings need to be handled differently */
+                       if ($1[0] == '\"')
+                               $$ = $1;
+                       else
+                               $$ = make3_str(make_str("\""), make3_str($1, $2, $3), make_str("\""));
+               }
+               |  db_prefix ':' server opt_port '/' opt_database_name opt_options
+               {
+                       /* new style: <tcp|unix>:postgresql://server[:port][/dbname] */
+                       if (strncmp($1, "unix:postgresql", strlen("unix:postgresql")) != 0 && strncmp($1, "tcp:postgresql", strlen("tcp:postgresql")) != 0)
+                               mmerror(PARSE_ERROR, ET_ERROR, "only protocols \"tcp\" and \"unix\" and database type \"postgresql\" are supported");
+
+                       if (strncmp($3, "//", strlen("//")) != 0)
+                               mmerror(PARSE_ERROR, ET_ERROR, "expected \"://\", found \"%s\"", $3);
+
+                       if (strncmp($1, "unix", strlen("unix")) == 0 &&
+                               strncmp($3 + strlen("//"), "localhost", strlen("localhost")) != 0 &&
+                               strncmp($3 + strlen("//"), "127.0.0.1", strlen("127.0.0.1")) != 0)
+                               mmerror(PARSE_ERROR, ET_ERROR, "unix domain sockets only work on \"localhost\" but not on \"%s\"", $3 + strlen("//"));
+
+                       $$ = make3_str(make3_str(make_str("\""), $1, make_str(":")), $3, make3_str(make3_str($4, make_str("/"), $6),    $7, make_str("\"")));
+               }
+               | char_variable
+               {
+                       $$ = $1;
+               }
+               | ecpg_sconst
+               {
+                       /* We can only process double quoted strings not single quotes ones,
+                        * so we change the quotes.
+                        * Note, that the rule for ecpg_sconst adds these single quotes. */
+                       $1[0] = '\"';
+                       $1[strlen($1)-1] = '\"';
+                       $$ = $1;
+               }
+               ;
+
+opt_database_name: database_name               { $$ = $1; }
+               | /*EMPTY*/                     { $$ = EMPTY; }
+               ;
+
+db_prefix: ecpg_ident cvariable
+               {
+                       if (strcmp($2, "postgresql") != 0 && strcmp($2, "postgres") != 0)
+                               mmerror(PARSE_ERROR, ET_ERROR, "expected \"postgresql\", found \"%s\"", $2);
+
+                       if (strcmp($1, "tcp") != 0 && strcmp($1, "unix") != 0)
+                               mmerror(PARSE_ERROR, ET_ERROR, "illegal connection type %s", $1);
+
+                       $$ = make3_str($1, make_str(":"), $2);
+               }
+               ;
+
+server: Op server_name
+               {
+                       if (strcmp($1, "@") != 0 && strcmp($1, "//") != 0)
+                               mmerror(PARSE_ERROR, ET_ERROR, "expected \"@\" or \"://\", found \"%s\"", $1);
+
+                       $$ = make2_str($1, $2);
+               }
+               ;
+
+opt_server: server                     { $$ = $1; }
+               | /*EMPTY*/                     { $$ = EMPTY; }
+               ;
+
+server_name: ColId                                     { $$ = $1; }
+               | ColId '.' server_name         { $$ = make3_str($1, make_str("."), $3); }
+               | IP                                            { $$ = make_name(); }
+               ;
+
+opt_port: ':' Iconst           { $$ = make2_str(make_str(":"), $2); }
+               | /*EMPTY*/     { $$ = EMPTY; }
+               ;
+
+opt_connection_name: AS connection_object      { $$ = $2; }
+               | /*EMPTY*/                     { $$ = make_str("NULL"); }
+               ;
+
+opt_user: USER ora_user                { $$ = $2; }
+               | /*EMPTY*/                     { $$ = make_str("NULL, NULL"); }
+               ;
+
+ora_user: user_name
+                       { $$ = cat2_str($1, make_str(", NULL")); }
+               | user_name '/' user_name
+                       { $$ = cat_str(3, $1, make_str(","), $3); }
+               | user_name SQL_IDENTIFIED BY user_name
+                       { $$ = cat_str(3, $1, make_str(","), $4); }
+               | user_name USING user_name
+                       { $$ = cat_str(3, $1, make_str(","), $3); }
+               ;
+
+user_name: RoleId
+               {
+                       if ($1[0] == '\"')
+                               $$ = $1;
+                       else
+                               $$ = make3_str(make_str("\""), $1, make_str("\""));
+               }
+               | ecpg_sconst
+               {
+                       if ($1[0] == '\"')
+                               $$ = $1;
+                       else
+                               $$ = make3_str(make_str("\""), $1, make_str("\""));
+               }
+               | civar
+               {
+                       enum ECPGttype type = argsinsert->variable->type->type;
+
+                       /* if array see what's inside */
+                       if (type == ECPGt_array)
+                               type = argsinsert->variable->type->u.element->type;
+
+                       /* handle varchars */
+                       if (type == ECPGt_varchar)
+                               $$ = make2_str(mm_strdup(argsinsert->variable->name), make_str(".arr"));
+                       else
+                               $$ = mm_strdup(argsinsert->variable->name);
+               }
+               ;
+
+char_variable: cvariable
+               {
+                       /* check if we have a string variable */
+                       struct variable *p = find_variable($1);
+                       enum ECPGttype type = p->type->type;
+
+                       /* If we have just one character this is not a string */
+                       if (atol(p->type->size) == 1)
+                                       mmerror(PARSE_ERROR, ET_ERROR, "invalid datatype");
+                       else
+                       {
+                               /* if array see what's inside */
+                               if (type == ECPGt_array)
+                                       type = p->type->u.element->type;
+
+                               switch (type)
+                               {
+                                       case ECPGt_char:
+                                       case ECPGt_unsigned_char:
+                                               $$ = $1;
+                                               break;
+                                       case ECPGt_varchar:
+                                               $$ = make2_str($1, make_str(".arr"));
+                                               break;
+                                       default:
+                                               mmerror(PARSE_ERROR, ET_ERROR, "invalid datatype");
+                                               $$ = $1;
+                                               break;
+                               }
+                       }
+               }
+               ;
+
+opt_options: Op connect_options
+               {
+                       if (strlen($1) == 0)
+                               mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement");
+
+                       if (strcmp($1, "?") != 0)
+                               mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", $1);
+
+                       $$ = make2_str(make_str("?"), $2);
+               }
+               | /*EMPTY*/     { $$ = EMPTY; }
+               ;
+
+connect_options:  ColId opt_opt_value 
+                       { $$ = make2_str($1, $2); }
+       | ColId opt_opt_value Op connect_options
+                       {
+                               if (strlen($3) == 0)
+                                       mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement");
+
+                               if (strcmp($3, "&") != 0)
+                                       mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", $3);
+
+                               $$ = cat_str(3, make2_str($1, $2), $3, $4);
+                       }
+       ;
+
+opt_opt_value: /*EMPTY*/
+                       { $$ = EMPTY; }
+               | '=' Iconst
+                       { $$ = make2_str(make_str("="), $2); }
+               | '=' ecpg_ident
+                       { $$ = make2_str(make_str("="), $2); }
+               | '=' civar
+                       { $$ = make2_str(make_str("="), $2); }
+               ;
+
+prepared_name: name             {
+                                        if ($1[0] == '\"' && $1[strlen($1)-1] == '\"') /* already quoted? */
+                                                $$ = $1;
+                                        else /* not quoted => convert to lowercase */
+                                        {
+                                                int i;
+
+                                                for (i = 0; i< strlen($1); i++)
+                                                        $1[i] = tolower((unsigned char) $1[i]);
+
+                                                $$ = make3_str(make_str("\""), $1, make_str("\""));
+                                        }
+                                }
+                | char_variable { $$ = $1; }
+                ;
+
+/*
+ * Declare a prepared cursor. The syntax is different from the standard
+ * declare statement, so we create a new rule.
+ */
+ECPGCursorStmt:  DECLARE name cursor_options CURSOR opt_hold FOR prepared_name
+               {
+                       struct cursor *ptr, *this;
+                       struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
+                       const char *con = connection ? connection : "NULL";
+
+                       for (ptr = cur; ptr != NULL; ptr = ptr->next)
+                       {
+                               if (strcmp($2, ptr->name) == 0)
+                                       /* re-definition is a bug */
+                                       mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" already defined", $2);
+                       }
+
+                       this = (struct cursor *) mm_alloc(sizeof(struct cursor));
+
+                       /* initial definition */
+                       this->next = cur;
+                       this->name = $2;
+                       this->connection = connection;
+                       this->command =  cat_str(6, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for $1"));
+                       this->argsresult = NULL;
+
+                       thisquery->type = &ecpg_query;
+                       thisquery->brace_level = 0;
+                       thisquery->next = NULL;
+                       thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement(, , __LINE__)") + strlen(con) + strlen($7));
+                       sprintf(thisquery->name, "ECPGprepared_statement(%s, %s, __LINE__)", con, $7);
+
+                       this->argsinsert = NULL;
+                       add_variable_to_head(&(this->argsinsert), thisquery, &no_indicator);
+
+                       cur = this;
+
+                       $$ = cat_str(3, make_str("/*"), mm_strdup(this->command), make_str("*/"));
+               }
+               ;
+
+ECPGExecuteImmediateStmt: EXECUTE IMMEDIATE execstring
+                       { 
+                         /* execute immediate means prepare the statement and
+                          * immediately execute it */
+                         $$ = $3;
+                       };
+/*
+ * variable decalartion outside exec sql declare block
+ */
+ECPGVarDeclaration: single_vt_declaration;
+
+single_vt_declaration: type_declaration                { $$ = $1; }
+               | var_declaration               { $$ = $1; }
+               ;
+
+precision:     NumericOnly     { $$ = $1; };
+
+opt_scale:     ',' NumericOnly { $$ = $2; }
+               | /* EMPTY */   { $$ = EMPTY; }
+               ;
+
+ecpg_interval: opt_interval    { $$ = $1; }
+               | YEAR_P TO MINUTE_P    { $$ = make_str("year to minute"); }
+               | YEAR_P TO SECOND_P    { $$ = make_str("year to second"); }
+               | DAY_P TO DAY_P                { $$ = make_str("day to day"); }
+               | MONTH_P TO MONTH_P    { $$ = make_str("month to month"); }
+               ;
+
+/*
+ * variable declaration inside exec sql declare block
+ */
+ECPGDeclaration: sql_startdeclare
+               { fputs("/* exec sql begin declare section */", yyout); }
+               var_type_declarations sql_enddeclare
+               {
+                       fprintf(yyout, "%s/* exec sql end declare section */", $3);
+                       free($3);
+                       output_line_number();
+               }
+               ;
+
+sql_startdeclare: ecpgstart BEGIN_P DECLARE SQL_SECTION ';' {};
+
+sql_enddeclare: ecpgstart END_P DECLARE SQL_SECTION ';' {};
+
+var_type_declarations: /*EMPTY*/                       { $$ = EMPTY; }
+               | vt_declarations                       { $$ = $1; }
+               | CPP_LINE                              { $$ = $1; }
+               ;
+
+vt_declarations:  var_declaration                      { $$ = $1; }
+               | type_declaration                      { $$ = $1; }
+               | vt_declarations var_declaration       { $$ = cat2_str($1, $2); }
+               | vt_declarations type_declaration      { $$ = cat2_str($1, $2); }
+               | vt_declarations CPP_LINE              { $$ = cat2_str($1, $2); }
+               ;
+
+variable_declarations: var_declaration         { $$ = $1; }
+               | variable_declarations var_declaration         { $$ = cat2_str($1, $2); }
+               ;
+
+type_declaration: S_TYPEDEF
+       {
+               /* reset this variable so we see if there was */
+               /* an initializer specified */
+               initializer = 0;
+       }
+       var_type opt_pointer ECPGColLabelCommon opt_array_bounds ';'
+       {
+               add_typedef($5, $6.index1, $6.index2, $3.type_enum, $3.type_dimension, $3.type_index, initializer, *$4 ? 1 : 0);
+
+               fprintf(yyout, "typedef %s %s %s %s;\n", $3.type_str, *$4 ? "*" : "", $5, $6.str);
+               output_line_number();
+               $$ = make_str("");
+       };
+
+var_declaration: storage_declaration
+               var_type
+               {
+                       actual_type[struct_level].type_enum = $2.type_enum;
+                       actual_type[struct_level].type_dimension = $2.type_dimension;
+                       actual_type[struct_level].type_index = $2.type_index;
+                       actual_type[struct_level].type_sizeof = $2.type_sizeof;
+
+                       actual_startline[struct_level] = hashline_number();
+               }
+               variable_list ';'
+               {
+                       $$ = cat_str(5, actual_startline[struct_level], $1, $2.type_str, $4, make_str(";\n"));
+               }
+               | var_type
+               {
+                       actual_type[struct_level].type_enum = $1.type_enum;
+                       actual_type[struct_level].type_dimension = $1.type_dimension;
+                       actual_type[struct_level].type_index = $1.type_index;
+                       actual_type[struct_level].type_sizeof = $1.type_sizeof;
+
+                       actual_startline[struct_level] = hashline_number();
+               }
+               variable_list ';'
+               {
+                       $$ = cat_str(4, actual_startline[struct_level], $1.type_str, $3, make_str(";\n"));
+               }
+               | struct_union_type_with_symbol ';'
+               {
+                       $$ = cat2_str($1, make_str(";"));
+               }
+               ;
+
+opt_bit_field: ':' Iconst      { $$ =cat2_str(make_str(":"), $2); }
+               | /* EMPTY */   { $$ = EMPTY; }
+               ;
+
+storage_declaration: storage_clause storage_modifier
+                       {$$ = cat2_str ($1, $2); }
+               | storage_clause                {$$ = $1; }
+               | storage_modifier              {$$ = $1; }
+               ;
+
+storage_clause : S_EXTERN      { $$ = make_str("extern"); }
+               | S_STATIC                      { $$ = make_str("static"); }
+               | S_REGISTER            { $$ = make_str("register"); }
+               | S_AUTO                        { $$ = make_str("auto"); }
+               ;
+
+storage_modifier : S_CONST     { $$ = make_str("const"); }
+               | S_VOLATILE            { $$ = make_str("volatile"); }
+               ;
+
+var_type:      simple_type
+               {
+                       $$.type_enum = $1;
+                       $$.type_str = mm_strdup(ecpg_type_name($1));
+                       $$.type_dimension = make_str("-1");
+                       $$.type_index = make_str("-1");
+                       $$.type_sizeof = NULL;
+               }
+               | struct_union_type
+               {
+                       $$.type_str = $1;
+                       $$.type_dimension = make_str("-1");
+                       $$.type_index = make_str("-1");
+
+                       if (strncmp($1, "struct", sizeof("struct")-1) == 0)
+                       {
+                               $$.type_enum = ECPGt_struct;
+                               $$.type_sizeof = ECPGstruct_sizeof;
+                       }
+                       else
+                       {
+                               $$.type_enum = ECPGt_union;
+                               $$.type_sizeof = NULL;
+                       }
+               }
+               | enum_type
+               {
+                       $$.type_str = $1;
+                       $$.type_enum = ECPGt_int;
+                       $$.type_dimension = make_str("-1");
+                       $$.type_index = make_str("-1");
+                       $$.type_sizeof = NULL;
+               }
+               | ECPGColLabelCommon '(' precision opt_scale ')'
+               {
+                       if (strcmp($1, "numeric") == 0)
+                       {
+                               $$.type_enum = ECPGt_numeric;
+                               $$.type_str = make_str("numeric");
+                       }
+                       else if (strcmp($1, "decimal") == 0)
+                       {
+                               $$.type_enum = ECPGt_decimal;
+                               $$.type_str = make_str("decimal");
+                       }
+                       else
+                       {
+                               mmerror(PARSE_ERROR, ET_ERROR, "only numeric/decimal have precision/scale argument");
+                               $$.type_enum = ECPGt_numeric;
+                               $$.type_str = make_str("numeric");
+                       }
+
+                       $$.type_dimension = make_str("-1");
+                       $$.type_index = make_str("-1");
+                       $$.type_sizeof = NULL;
+               }
+               | ECPGColLabelCommon ecpg_interval
+               {
+                       if (strlen($2) != 0 && strcmp ($1, "datetime") != 0 && strcmp ($1, "interval") != 0)
+                               mmerror (PARSE_ERROR, ET_ERROR, "interval specification not allowed here");
+
+                       /*
+                        * Check for type names that the SQL grammar treats as
+                        * unreserved keywords
+                        */
+                       if (strcmp($1, "varchar") == 0)
+                       {
+                               $$.type_enum = ECPGt_varchar;
+                               $$.type_str = EMPTY; /*make_str("varchar");*/
+                               $$.type_dimension = make_str("-1");
+                               $$.type_index = make_str("-1");
+                               $$.type_sizeof = NULL;
+                       }
+                       else if (strcmp($1, "float") == 0)
+                       {
+                               $$.type_enum = ECPGt_float;
+                               $$.type_str = make_str("float");
+                               $$.type_dimension = make_str("-1");
+                               $$.type_index = make_str("-1");
+                               $$.type_sizeof = NULL;
+                       }
+                       else if (strcmp($1, "double") == 0)
+                       {
+                               $$.type_enum = ECPGt_double;
+                               $$.type_str = make_str("double");
+                               $$.type_dimension = make_str("-1");
+                               $$.type_index = make_str("-1");
+                               $$.type_sizeof = NULL;
+                       }
+                       else if (strcmp($1, "numeric") == 0)
+                       {
+                               $$.type_enum = ECPGt_numeric;
+                               $$.type_str = make_str("numeric");
+                               $$.type_dimension = make_str("-1");
+                               $$.type_index = make_str("-1");
+                               $$.type_sizeof = NULL;
+                       }
+                       else if (strcmp($1, "decimal") == 0)
+                       {
+                               $$.type_enum = ECPGt_decimal;
+                               $$.type_str = make_str("decimal");
+                               $$.type_dimension = make_str("-1");
+                               $$.type_index = make_str("-1");
+                               $$.type_sizeof = NULL;
+                       }
+                       else if (strcmp($1, "date") == 0)
+                       {
+                               $$.type_enum = ECPGt_date;
+                               $$.type_str = make_str("date");
+                               $$.type_dimension = make_str("-1");
+                               $$.type_index = make_str("-1");
+                               $$.type_sizeof = NULL;
+                       }
+                       else if (strcmp($1, "timestamp") == 0)
+                       {
+                               $$.type_enum = ECPGt_timestamp;
+                               $$.type_str = make_str("timestamp");
+                               $$.type_dimension = make_str("-1");
+                               $$.type_index = make_str("-1");
+                               $$.type_sizeof = NULL;
+                       }
+                       else if (strcmp($1, "interval") == 0)
+                       {
+                               $$.type_enum = ECPGt_interval;
+                               $$.type_str = make_str("interval");
+                               $$.type_dimension = make_str("-1");
+                               $$.type_index = make_str("-1");
+                               $$.type_sizeof = NULL;
+                       }
+                       else if (strcmp($1, "datetime") == 0)
+                       {
+                               $$.type_enum = ECPGt_timestamp;
+                               $$.type_str = make_str("timestamp");
+                               $$.type_dimension = make_str("-1");
+                               $$.type_index = make_str("-1");
+                               $$.type_sizeof = NULL;
+                       }
+                       else
+                       {
+                               /* this is for typedef'ed types */
+                               struct typedefs *this = get_typedef($1);
+
+                               $$.type_str = (this->type->type_enum == ECPGt_varchar) ? EMPTY : mm_strdup(this->name);
+                               $$.type_enum = this->type->type_enum;
+                               $$.type_dimension = this->type->type_dimension;
+                               $$.type_index = this->type->type_index;
+                               if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0)
+                                       $$.type_sizeof = this->type->type_sizeof;
+                               else 
+                                       $$.type_sizeof = cat_str(3, make_str("sizeof("), mm_strdup(this->name), make_str(")"));
+
+                               struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
+                       }
+               }
+               | s_struct_union_symbol
+               {
+                       /* this is for named structs/unions */
+                       char *name;
+                       struct typedefs *this;
+                       bool forward = (forward_name != NULL && strcmp($1.symbol, forward_name) == 0 && strcmp($1.su, "struct") == 0);
+
+                       name = cat2_str($1.su, $1.symbol);
+                       /* Do we have a forward definition? */
+                       if (!forward)
+                       {
+                               /* No */
+
+                               this = get_typedef(name);
+                               $$.type_str = mm_strdup(this->name);
+                               $$.type_enum = this->type->type_enum;
+                               $$.type_dimension = this->type->type_dimension;
+                               $$.type_index = this->type->type_index;
+                               $$.type_sizeof = this->type->type_sizeof;
+                               struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
+                               free(name);
+                       }
+                       else
+                       {
+                               $$.type_str = name;
+                               $$.type_enum = ECPGt_long;
+                               $$.type_dimension = make_str("-1");
+                               $$.type_index = make_str("-1");
+                               $$.type_sizeof = make_str("");
+                               struct_member_list[struct_level] = NULL;
+                       }
+               }
+               ;
+
+enum_type: ENUM_P symbol enum_definition
+                       { $$ = cat_str(3, make_str("enum"), $2, $3); }
+               | ENUM_P enum_definition
+                       { $$ = cat2_str(make_str("enum"), $2); }
+               | ENUM_P symbol
+                       { $$ = cat2_str(make_str("enum"), $2); }
+               ;
+
+enum_definition: '{' c_list '}'
+                       { $$ = cat_str(3, make_str("{"), $2, make_str("}")); };
+
+struct_union_type_with_symbol: s_struct_union_symbol
+               {
+                       struct_member_list[struct_level++] = NULL;
+                       if (struct_level >= STRUCT_DEPTH)
+                                mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition");
+                       forward_name = mm_strdup($1.symbol);
+               }
+               '{' variable_declarations '}'
+               {
+                       struct typedefs *ptr, *this;
+                       struct this_type su_type;
+
+                       ECPGfree_struct_member(struct_member_list[struct_level]);
+                       struct_member_list[struct_level] = NULL;
+                       struct_level--;
+                       if (strncmp($1.su, "struct", sizeof("struct")-1) == 0)
+                               su_type.type_enum = ECPGt_struct;
+                       else
+                               su_type.type_enum = ECPGt_union;
+                       su_type.type_str = cat2_str($1.su, $1.symbol);
+                       free(forward_name);
+                       forward_name = NULL;
+
+                       /* This is essantially a typedef but needs the keyword struct/union as well.
+                        * So we create the typedef for each struct definition with symbol */
+                       for (ptr = types; ptr != NULL; ptr = ptr->next)
+                       {
+                                       if (strcmp(su_type.type_str, ptr->name) == 0)
+                                                       /* re-definition is a bug */
+                                                       mmerror(PARSE_ERROR, ET_ERROR, "type \"%s\" already defined", su_type.type_str);
+                       }
+
+                       this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
+
+                       /* initial definition */
+                       this->next = types;
+                       this->name = mm_strdup(su_type.type_str);
+                       this->brace_level = braces_open;
+                       this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
+                       this->type->type_enum = su_type.type_enum;
+                       this->type->type_str = mm_strdup(su_type.type_str);
+                       this->type->type_dimension = make_str("-1"); /* dimension of array */
+                       this->type->type_index = make_str("-1");        /* length of string */
+                       this->type->type_sizeof = ECPGstruct_sizeof;
+                       this->struct_member_list = struct_member_list[struct_level];
+
+                       types = this;
+                       $$ = cat_str(4, su_type.type_str, make_str("{"), $4, make_str("}"));
+               }
+               ;
+
+struct_union_type: struct_union_type_with_symbol       { $$ = $1; }
+               | s_struct_union
+               {
+                       struct_member_list[struct_level++] = NULL;
+                       if (struct_level >= STRUCT_DEPTH)
+                                mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition");
+               }
+               '{' variable_declarations '}'
+               {
+                       ECPGfree_struct_member(struct_member_list[struct_level]);
+                       struct_member_list[struct_level] = NULL;
+                       struct_level--;
+                       $$ = cat_str(4, $1, make_str("{"), $4, make_str("}"));
+               }
+               ;
+
+s_struct_union_symbol: SQL_STRUCT symbol
+               {
+                       $$.su = make_str("struct");
+                       $$.symbol = $2;
+                       ECPGstruct_sizeof = cat_str(3, make_str("sizeof("), cat2_str(mm_strdup($$.su), mm_strdup($$.symbol)), make_str(")"));
+               }
+               | UNION symbol
+               {
+                       $$.su = make_str("union");
+                       $$.symbol = $2;
+               }
+               ;
+
+s_struct_union: SQL_STRUCT
+               {
+                       ECPGstruct_sizeof = make_str(""); /* This must not be NULL to distinguish from simple types. */
+                       $$ = make_str("struct");
+               }
+               | UNION         { $$ = make_str("union"); }
+               ;
+
+simple_type: unsigned_type                                     { $$=$1; }
+               |       opt_signed signed_type                  { $$=$2; }
+               ;
+
+unsigned_type: SQL_UNSIGNED SQL_SHORT          { $$ = ECPGt_unsigned_short; }
+               | SQL_UNSIGNED SQL_SHORT INT_P  { $$ = ECPGt_unsigned_short; }
+               | SQL_UNSIGNED                                          { $$ = ECPGt_unsigned_int; }
+               | SQL_UNSIGNED INT_P                            { $$ = ECPGt_unsigned_int; }
+               | SQL_UNSIGNED SQL_LONG                         { $$ = ECPGt_unsigned_long; }
+               | SQL_UNSIGNED SQL_LONG INT_P           { $$ = ECPGt_unsigned_long; }
+               | SQL_UNSIGNED SQL_LONG SQL_LONG
+               {
+#ifdef HAVE_LONG_LONG_INT_64
+                       $$ = ECPGt_unsigned_long_long;
+#else
+                       $$ = ECPGt_unsigned_long;
+#endif
+               }
+               | SQL_UNSIGNED SQL_LONG SQL_LONG INT_P
+               {
+#ifdef HAVE_LONG_LONG_INT_64
+                       $$ = ECPGt_unsigned_long_long;
+#else
+                       $$ = ECPGt_unsigned_long;
+#endif
+               }
+               | SQL_UNSIGNED CHAR_P                   { $$ = ECPGt_unsigned_char; }
+               ;
+
+signed_type: SQL_SHORT                         { $$ = ECPGt_short; }
+               | SQL_SHORT INT_P                       { $$ = ECPGt_short; }
+               | INT_P                                         { $$ = ECPGt_int; }
+               | SQL_LONG                                      { $$ = ECPGt_long; }
+               | SQL_LONG INT_P                        { $$ = ECPGt_long; }
+               | SQL_LONG SQL_LONG
+               {
+#ifdef HAVE_LONG_LONG_INT_64
+                       $$ = ECPGt_long_long;
+#else
+                       $$ = ECPGt_long;
+#endif
+               }
+               | SQL_LONG SQL_LONG INT_P
+               {
+#ifdef HAVE_LONG_LONG_INT_64
+                       $$ = ECPGt_long_long;
+#else
+                       $$ = ECPGt_long;
+#endif
+               }
+               | SQL_BOOL                                      { $$ = ECPGt_bool; }
+               | CHAR_P                                        { $$ = ECPGt_char; }
+               | DOUBLE_P                                      { $$ = ECPGt_double; }
+               ;
+
+opt_signed: SQL_SIGNED
+               |       /* EMPTY */
+               ;
+
+variable_list: variable
+                       { $$ = $1; }
+               | variable_list ',' variable
+                       { $$ = cat_str(3, $1, make_str(","), $3); }
+               ;
+
+variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initializer
+               {
+                       struct ECPGtype * type;
+                       char *dimension = $3.index1; /* dimension of array */
+                       char *length = $3.index2;    /* length of string */
+                       char dim[14L];
+                       char *vcn;
+
+                       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);
+
+                       switch (actual_type[struct_level].type_enum)
+                       {
+                               case ECPGt_struct:
+                               case ECPGt_union:
+                                       if (atoi(dimension) < 0)
+                                               type = ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_sizeof);
+                                       else
+                                               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);
+
+                                       $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5);
+                                       break;
+
+                               case ECPGt_varchar:
+                                       if (atoi(dimension) < 0)
+                                               type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, yylineno);
+                                       else
+                                               type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, yylineno), dimension);
+                                       
+                                       if (strcmp(dimension, "0") == 0 || abs(atoi(dimension)) == 1)
+                                                       *dim = '\0';
+                                       else
+                                                       sprintf(dim, "[%s]", dimension);
+                                       /* cannot check for atoi <= 0 because a defined constant will yield 0 here as well */
+                                       if (atoi(length) < 0 || strcmp(length, "0") == 0)
+                                               mmerror(PARSE_ERROR, ET_ERROR, "pointer to varchar are not implemented");
+
+                                       /* make sure varchar struct name is unique by adding linenumer of its definition */
+                                       vcn = (char *) mm_alloc(strlen($2) + sizeof(int) * CHAR_BIT * 10 / 3);
+                                       sprintf(vcn, "%s_%d", $2, yylineno);
+                                       if (strcmp(dimension, "0") == 0)
+                                               $$ = 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);
+                                       else
+                                               $$ = 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);
+                                       break;
+
+                               case ECPGt_char:
+                               case ECPGt_unsigned_char:
+                                       if (atoi(dimension) == -1)
+                                       {
+                                               int i = strlen($5);
+
+                                               if (atoi(length) == -1 && i > 0) /* char <var>[] = "string" */
+                                               {
+                                                       /* if we have an initializer but no string size set, let's use the initializer's length */
+                                                       free(length);
+                                                       length = mm_alloc(i+sizeof("sizeof()"));
+                                                       sprintf(length, "sizeof(%s)", $5+2);
+                                               }
+                                               type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0);
+                                       }
+                                       else
+                                               type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0), dimension);
+
+                                       $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5);
+                                       break;
+
+                               default:
+                                       if (atoi(dimension) < 0)
+                                               type = ECPGmake_simple_type(actual_type[struct_level].type_enum, make_str("1"), 0);
+                                       else
+                                               type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, make_str("1"), 0), dimension);
+
+                                       $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5);
+                                       break;
+                       }
+
+                       if (struct_level == 0)
+                               new_variable($2, type, braces_open);
+                       else
+                               ECPGmake_struct_member($2, type, &(struct_member_list[struct_level - 1]));
+
+                       free($2);
+               }
+               ;
+
+opt_initializer: /*EMPTY*/
+                       { $$ = EMPTY; }
+               | '=' c_term
+               {
+                       initializer = 1;
+                       $$ = cat2_str(make_str("="), $2);
+               }
+               ;
+
+opt_pointer: /*EMPTY*/                         { $$ = EMPTY; }
+               | '*'                                           { $$ = make_str("*"); }
+               | '*' '*'                                       { $$ = make_str("**"); }
+               ;
+
+/*
+ * We try to simulate the correct DECLARE syntax here so we get dynamic SQL
+ */
+ECPGDeclare: DECLARE STATEMENT ecpg_ident
+               {
+                       /* this is only supported for compatibility */
+                       $$ = cat_str(3, make_str("/* declare statement"), $3, make_str("*/"));
+               }
+               ;
+/*
+ * the exec sql disconnect statement: disconnect from the given database
+ */
+ECPGDisconnect: SQL_DISCONNECT dis_name { $$ = $2; }
+               ;
+
+dis_name: connection_object                    { $$ = $1; }
+               | CURRENT_P                     { $$ = make_str("\"CURRENT\""); }
+               | ALL                           { $$ = make_str("\"ALL\""); }
+               | /* EMPTY */                   { $$ = make_str("\"CURRENT\""); }
+               ;
+
+connection_object: database_name               { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
+               | DEFAULT                       { $$ = make_str("\"DEFAULT\""); }
+               | char_variable                 { $$ = $1; }
+               ;
+
+execstring: char_variable
+                       { $$ = $1; }
+               |       CSTRING
+                       { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
+               ;
+
+/*
+ * the exec sql free command to deallocate a previously
+ * prepared statement
+ */
+ECPGFree:      SQL_FREE name   { $$ = $2; }
+               | SQL_FREE ALL  { $$ = make_str("all"); }
+               ;
+
+/*
+ * open is an open cursor, at the moment this has to be removed
+ */
+ECPGOpen: SQL_OPEN name opt_ecpg_using { $$ = $2; };
+
+opt_ecpg_using: /*EMPTY*/      { $$ = EMPTY; }
+               | ecpg_using            { $$ = $1; }
+               ;
+
+ecpg_using:    USING using_list        { $$ = EMPTY; }
+               | using_descriptor      { $$ = $1; }
+               ;
+
+using_descriptor: USING opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
+               {
+                       add_variable_to_head(&argsinsert, descriptor_variable($4,0), &no_indicator);
+                       $$ = EMPTY;
+               }
+               ;
+
+into_descriptor: INTO opt_sql SQL_DESCRIPTOR quoted_ident_stringvar
+               {
+                       add_variable_to_head(&argsresult, descriptor_variable($4,1), &no_indicator);
+                       $$ = EMPTY;
+               }
+               ;
+
+opt_sql: /*EMPTY*/ | SQL_SQL;
+
+using_list: UsingValue | UsingValue ',' using_list;
+
+UsingValue: UsingConst
+               {
+                       char *length = mm_alloc(32);
+
+                       sprintf(length, "%d", (int) strlen($1));
+                       add_variable_to_head(&argsinsert, new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0), &no_indicator);
+               }
+               | civar { $$ = EMPTY; }
+               | civarind { $$ = EMPTY; }
+               ; 
+
+UsingConst: Iconst                     { $$ = $1; }
+               | ecpg_fconst           { $$ = $1; }
+               | ecpg_sconst           { $$ = $1; }
+               | ecpg_bconst           { $$ = $1; }
+               | ecpg_xconst           { $$ = $1; }
+               ;
+
+/*
+ * We accept descibe but do nothing with it so far.
+ */
+ECPGDescribe: SQL_DESCRIBE INPUT_P name using_descriptor
+       {
+               const char *con = connection ? connection : "NULL";
+               mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement\n");
+               $$ = (char *) mm_alloc(sizeof("1, ECPGprepared_statement(, \"\", __LINE__)") + strlen(con) + strlen($3));
+               sprintf($$, "1, ECPGprepared_statement(%s, \"%s\", __LINE__)", con, $3);
+       }
+       | SQL_DESCRIBE opt_output name using_descriptor
+       {
+               const char *con = connection ? connection : "NULL";
+               mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement\n");
+               $$ = (char *) mm_alloc(sizeof("0, ECPGprepared_statement(, \"\", __LINE__)") + strlen(con) + strlen($3));
+               sprintf($$, "0, ECPGprepared_statement(%s, \"%s\", __LINE__)", con, $3);
+       }
+       | SQL_DESCRIBE opt_output name into_descriptor
+       {
+               const char *con = connection ? connection : "NULL";
+               mmerror(PARSE_ERROR, ET_WARNING, "using unsupported describe statement\n");
+               $$ = (char *) mm_alloc(sizeof("0, ECPGprepared_statement(, \"\", __LINE__)") + strlen(con) + strlen($3));
+               sprintf($$, "0, ECPGprepared_statement(%s, \"%s\", __LINE__)", con, $3);
+       }
+       ;
+
+opt_output:    SQL_OUTPUT      { $$ = make_str("output"); }
+       |       /* EMPTY */     { $$ = EMPTY; }
+       ;
+
+/*
+ * dynamic SQL: descriptor based access
+ *     originall written by Christof Petig <christof.petig@wtal.de>
+ *                     and Peter Eisentraut <peter.eisentraut@credativ.de>
+ */
+
+/*
+ * allocate a descriptor
+ */
+ECPGAllocateDescr:     SQL_ALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
+               {
+                       add_descriptor($3,connection);
+                       $$ = $3;
+               }
+               ;
+
+
+/*
+ * deallocate a descriptor
+ */
+ECPGDeallocateDescr:   DEALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
+               {
+                       drop_descriptor($3,connection);
+                       $$ = $3;
+               }
+               ;
+
+/*
+ * manipulate a descriptor header
+ */
+
+ECPGGetDescriptorHeader: SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar ECPGGetDescHeaderItems
+                       {  $$ = $3; }
+               ;
+
+ECPGGetDescHeaderItems: ECPGGetDescHeaderItem
+               | ECPGGetDescHeaderItems ',' ECPGGetDescHeaderItem
+               ;
+
+ECPGGetDescHeaderItem: cvariable '=' desc_header_item
+                       { push_assignment($1, $3); }
+               ;
+
+
+ECPGSetDescriptorHeader: SET SQL_DESCRIPTOR quoted_ident_stringvar ECPGSetDescHeaderItems
+                       { $$ = $3; }
+               ;
+
+ECPGSetDescHeaderItems: ECPGSetDescHeaderItem
+               | ECPGSetDescHeaderItems ',' ECPGSetDescHeaderItem
+               ;
+
+ECPGSetDescHeaderItem: desc_header_item '=' IntConstVar
+               {
+                       push_assignment($3, $1);
+               }
+               ;
+
+IntConstVar:    Iconst
+                {
+                        char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
+
+                        sprintf(length, "%d", (int) strlen($1));
+                        new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
+                        $$ = $1;
+                }
+                | cvariable     { $$ = $1; }
+                ;
+
+desc_header_item:      SQL_COUNT                       { $$ = ECPGd_count; }
+               ;
+
+/*
+ * manipulate a descriptor
+ */
+
+ECPGGetDescriptor:     SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGGetDescItems
+                       {  $$.str = $5; $$.name = $3; }
+               ;
+
+ECPGGetDescItems: ECPGGetDescItem
+               | ECPGGetDescItems ',' ECPGGetDescItem
+               ;
+
+ECPGGetDescItem: cvariable '=' descriptor_item { push_assignment($1, $3); };
+
+
+ECPGSetDescriptor:     SET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGSetDescItems
+                       {  $$.str = $5; $$.name = $3; }
+               ;
+
+ECPGSetDescItems: ECPGSetDescItem
+               | ECPGSetDescItems ',' ECPGSetDescItem
+               ;
+
+ECPGSetDescItem: descriptor_item '=' AllConstVar
+               {
+                       push_assignment($3, $1);
+               }
+               ;
+
+AllConstVar:    ecpg_fconst
+                {
+                        char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
+
+                        sprintf(length, "%d", (int) strlen($1));
+                        new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
+                        $$ = $1;
+                }
+                | IntConstVar           { $$ = $1; }
+                | '-' ecpg_fconst
+                {
+                        char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
+                        char *var = cat2_str(make_str("-"), $2);
+
+                        sprintf(length, "%d", (int) strlen(var));
+                        new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
+                        $$ = var;
+                }
+                | '-' Iconst
+                {
+                        char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
+                        char *var = cat2_str(make_str("-"), $2);
+
+                        sprintf(length, "%d", (int) strlen(var));
+                        new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
+                        $$ = var;
+                }
+                | ecpg_sconst
+                {
+                        char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
+                        char *var = $1 + 1;
+
+                        var[strlen(var) - 1] = '\0';
+                        sprintf(length, "%d", (int) strlen(var));
+                        new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
+                        $$ = var;
+                }
+               ;
+
+descriptor_item:       SQL_CARDINALITY                 { $$ = ECPGd_cardinality; }
+               | DATA_P                                { $$ = ECPGd_data; }
+               | SQL_DATETIME_INTERVAL_CODE            { $$ = ECPGd_di_code; }
+               | SQL_DATETIME_INTERVAL_PRECISION       { $$ = ECPGd_di_precision; }
+               | SQL_INDICATOR                         { $$ = ECPGd_indicator; }
+               | SQL_KEY_MEMBER                        { $$ = ECPGd_key_member; }
+               | SQL_LENGTH                            { $$ = ECPGd_length; }
+               | NAME_P                                { $$ = ECPGd_name; }
+               | SQL_NULLABLE                          { $$ = ECPGd_nullable; }
+               | SQL_OCTET_LENGTH                      { $$ = ECPGd_octet; }
+               | PRECISION                             { $$ = ECPGd_precision; }
+               | SQL_RETURNED_LENGTH                   { $$ = ECPGd_length; }
+               | SQL_RETURNED_OCTET_LENGTH             { $$ = ECPGd_ret_octet; }
+               | SQL_SCALE                             { $$ = ECPGd_scale; }
+               | TYPE_P                                { $$ = ECPGd_type; }
+               ;
+
+/*
+ * set/reset the automatic transaction mode, this needs a differnet handling
+ * as the other set commands
+ */
+ECPGSetAutocommit:     SET SQL_AUTOCOMMIT '=' on_off   { $$ = $4; }
+               |  SET SQL_AUTOCOMMIT TO on_off   { $$ = $4; }
+               ;
+
+on_off: ON                             { $$ = make_str("on"); }
+               | OFF                   { $$ = make_str("off"); }
+               ;
+
+/*
+ * set the actual connection, this needs a differnet handling as the other
+ * set commands
+ */
+ECPGSetConnection:     SET CONNECTION TO connection_object { $$ = $4; }
+               | SET CONNECTION '=' connection_object { $$ = $4; }
+               | SET CONNECTION  connection_object { $$ = $3; }
+               ;
+
+/*
+ * define a new type for embedded SQL
+ */
+ECPGTypedef: TYPE_P
+               {
+                       /* reset this variable so we see if there was */
+                       /* an initializer specified */
+                       initializer = 0;
+               }
+               ECPGColLabelCommon IS var_type opt_array_bounds opt_reference
+               {
+                       add_typedef($3, $6.index1, $6.index2, $5.type_enum, $5.type_dimension, $5.type_index, initializer, *$7 ? 1 : 0);
+
+                       if (auto_create_c == false)
+                               $$ = 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("*/"));
+                       else
+                               $$ = 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(";"));
+               }
+               ;
+
+opt_reference: SQL_REFERENCE           { $$ = make_str("reference"); }
+               | /*EMPTY*/                                     { $$ = EMPTY; }
+               ;
+
+/*
+ * define the type of one variable for embedded SQL
+ */
+ECPGVar: SQL_VAR
+               {
+                       /* reset this variable so we see if there was */
+                       /* an initializer specified */
+                       initializer = 0;
+               }
+               ColLabel IS var_type opt_array_bounds opt_reference
+               {
+                       struct variable *p = find_variable($3);
+                       char *dimension = $6.index1;
+                       char *length = $6.index2;
+                       struct ECPGtype * type;
+
+                       if (($5.type_enum == ECPGt_struct ||
+                                $5.type_enum == ECPGt_union) &&
+                               initializer == 1)
+                               mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in EXEC SQL VAR command");
+                       else
+                       {
+                               adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7?1:0, false);
+
+                               switch ($5.type_enum)
+                               {
+                                       case ECPGt_struct:
+                                       case ECPGt_union:
+                                               if (atoi(dimension) < 0)
+                                                       type = ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, $5.type_sizeof);
+                                               else
+                                                       type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum,$5.type_sizeof), dimension);
+                                               break;
+
+                                       case ECPGt_varchar:
+                                               if (atoi(dimension) == -1)
+                                                       type = ECPGmake_simple_type($5.type_enum, length, 0);
+                                               else
+                                                       type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length, 0), dimension);
+                                               break;
+
+                                       case ECPGt_char:
+                                       case ECPGt_unsigned_char:
+                                               if (atoi(dimension) == -1)
+                                                       type = ECPGmake_simple_type($5.type_enum, length, 0);
+                                               else
+                                                       type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length, 0), dimension);
+                                               break;
+
+                                       default:
+                                               if (atoi(length) >= 0)
+                                                       mmerror(PARSE_ERROR, ET_ERROR, "no multidimensional array support for simple data types");
+
+                                               if (atoi(dimension) < 0)
+                                                       type = ECPGmake_simple_type($5.type_enum, make_str("1"), 0);
+                                               else
+                                                       type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, make_str("1"), 0), dimension);
+                                               break;
+                               }
+
+                               ECPGfree_type(p->type);
+                               p->type = type;
+                       }
+
+                       $$ = 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("*/"));
+               }
+               ;
+
+/*
+ * whenever statement: decide what to do in case of error/no data found
+ * according to SQL standards we lack: SQLSTATE, CONSTRAINT and SQLEXCEPTION
+ */
+ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action
+               {
+                       when_error.code = $<action>3.code;
+                       when_error.command = $<action>3.command;
+                       $$ = cat_str(3, make_str("/* exec sql whenever sqlerror "), $3.str, make_str("; */"));
+               }
+               | SQL_WHENEVER NOT SQL_FOUND action
+               {
+                       when_nf.code = $<action>4.code;
+                       when_nf.command = $<action>4.command;
+                       $$ = cat_str(3, make_str("/* exec sql whenever not found "), $4.str, make_str("; */"));
+               }
+               | SQL_WHENEVER SQL_SQLWARNING action
+               {
+                       when_warn.code = $<action>3.code;
+                       when_warn.command = $<action>3.command;
+                       $$ = cat_str(3, make_str("/* exec sql whenever sql_warning "), $3.str, make_str("; */"));
+               }
+               ;
+
+action : CONTINUE_P
+               {
+                       $<action>$.code = W_NOTHING;
+                       $<action>$.command = NULL;
+                       $<action>$.str = make_str("continue");
+               }
+               | SQL_SQLPRINT
+               {
+                       $<action>$.code = W_SQLPRINT;
+                       $<action>$.command = NULL;
+                       $<action>$.str = make_str("sqlprint");
+               }
+               | SQL_STOP
+               {
+                       $<action>$.code = W_STOP;
+                       $<action>$.command = NULL;
+                       $<action>$.str = make_str("stop");
+               }
+               | SQL_GOTO name
+               {
+                       $<action>$.code = W_GOTO;
+                       $<action>$.command = strdup($2);
+                       $<action>$.str = cat2_str(make_str("goto "), $2);
+               }
+               | SQL_GO TO name
+               {
+                       $<action>$.code = W_GOTO;
+                       $<action>$.command = strdup($3);
+                       $<action>$.str = cat2_str(make_str("goto "), $3);
+               }
+               | DO name '(' c_args ')'
+               {
+                       $<action>$.code = W_DO;
+                       $<action>$.command = cat_str(4, $2, make_str("("), $4, make_str(")"));
+                       $<action>$.str = cat2_str(make_str("do"), mm_strdup($<action>$.command));
+               }
+               | DO SQL_BREAK
+               {
+                       $<action>$.code = W_BREAK;
+                       $<action>$.command = NULL;
+                       $<action>$.str = make_str("break");
+               }
+               | SQL_CALL name '(' c_args ')'
+               {
+                       $<action>$.code = W_DO;
+                       $<action>$.command = cat_str(4, $2, make_str("("), $4, make_str(")"));
+                       $<action>$.str = cat2_str(make_str("call"), mm_strdup($<action>$.command));
+               }
+               | SQL_CALL name
+               {
+                       $<action>$.code = W_DO;
+                       $<action>$.command = cat2_str($2, make_str("()"));
+                       $<action>$.str = cat2_str(make_str("call"), mm_strdup($<action>$.command));
+               }
+               ;
+
+/* some other stuff for ecpg */
+
+/* additional unreserved keywords */
+ECPGKeywords: ECPGKeywords_vanames     { $$ = $1; }
+               | ECPGKeywords_rest     { $$ = $1; }
+               ;
+
+ECPGKeywords_vanames:  SQL_BREAK               { $$ = make_str("break"); }
+               | SQL_CALL                                              { $$ = make_str("call"); }
+               | SQL_CARDINALITY                               { $$ = make_str("cardinality"); }
+               | SQL_COUNT                                             { $$ = make_str("count"); }
+               | SQL_DATETIME_INTERVAL_CODE    { $$ = make_str("datetime_interval_code"); }
+               | SQL_DATETIME_INTERVAL_PRECISION       { $$ = make_str("datetime_interval_precision"); }
+               | SQL_FOUND                                             { $$ = make_str("found"); }
+               | SQL_GO                                                { $$ = make_str("go"); }
+               | SQL_GOTO                                              { $$ = make_str("goto"); }
+               | SQL_IDENTIFIED                                { $$ = make_str("identified"); }
+               | SQL_INDICATOR                         { $$ = make_str("indicator"); }
+               | SQL_KEY_MEMBER                        { $$ = make_str("key_member"); }
+               | SQL_LENGTH                            { $$ = make_str("length"); }
+               | SQL_NULLABLE                          { $$ = make_str("nullable"); }
+               | SQL_OCTET_LENGTH                      { $$ = make_str("octet_length"); }
+               | SQL_RETURNED_LENGTH           { $$ = make_str("returned_length"); }
+               | SQL_RETURNED_OCTET_LENGTH     { $$ = make_str("returned_octet_length"); }
+               | SQL_SCALE                                     { $$ = make_str("scale"); }
+               | SQL_SECTION                           { $$ = make_str("section"); }
+               | SQL_SQL                               { $$ = make_str("sql"); }
+               | SQL_SQLERROR                          { $$ = make_str("sqlerror"); }
+               | SQL_SQLPRINT                          { $$ = make_str("sqlprint"); }
+               | SQL_SQLWARNING                        { $$ = make_str("sqlwarning"); }
+               | SQL_STOP                                      { $$ = make_str("stop"); }
+               ;
+
+ECPGKeywords_rest:  SQL_CONNECT                { $$ = make_str("connect"); }
+               | SQL_DESCRIBE                          { $$ = make_str("describe"); }
+               | SQL_DISCONNECT                        { $$ = make_str("disconnect"); }
+               | SQL_OPEN                                      { $$ = make_str("open"); }
+               | SQL_VAR                                       { $$ = make_str("var"); }
+               | SQL_WHENEVER                          { $$ = make_str("whenever"); }
+               ;
+
+/* additional keywords that can be SQL type names (but not ECPGColLabels) */
+ECPGTypeName:  SQL_BOOL                                { $$ = make_str("bool"); }
+               | SQL_LONG                                      { $$ = make_str("long"); }
+               | SQL_OUTPUT                            { $$ = make_str("output"); }
+               | SQL_SHORT                                     { $$ = make_str("short"); }
+               | SQL_STRUCT                            { $$ = make_str("struct"); }
+               | SQL_SIGNED                            { $$ = make_str("signed"); }
+               | SQL_UNSIGNED                          { $$ = make_str("unsigned"); }
+               ;
+
+symbol: ColLabel                                       { $$ = $1; }
+               ;
+
+ECPGColId: ecpg_ident                          { $$ = $1; }
+               | ECPGunreserved_interval       { $$ = $1; }
+               | ECPGunreserved_con            { $$ = $1; }
+               | col_name_keyword              { $$ = $1; }
+               | ECPGKeywords                  { $$ = $1; }
+               | ECPGCKeywords                 { $$ = $1; }
+               | CHAR_P                        { $$ = make_str("char"); }
+               | VALUES                        { $$ = make_str("values"); }
+               ;
+/* Column label --- allowed labels in "AS" clauses.
+ * This presently includes *all* Postgres keywords.
+ */
+ColLabel:  ECPGColLabel                                { $$ = $1; }
+               | ECPGTypeName                  { $$ = $1; }
+               | CHAR_P                        { $$ = make_str("char"); }
+               | INPUT_P                       { $$ = make_str("input"); }
+               | INT_P                         { $$ = make_str("int"); }
+               | UNION                         { $$ = make_str("union"); }
+               | TO                            { $$ = make_str("to"); }
+               | ECPGCKeywords                 { $$ = $1; }
+               | ECPGunreserved_interval       { $$ = $1; }
+               ;
+
+ECPGColLabelCommon:  ecpg_ident                        { $$ = $1; }
+               | col_name_keyword              { $$ = $1; }
+               | type_func_name_keyword        { $$ = $1; }
+               | ECPGKeywords_vanames          { $$ = $1; }
+               ;
+
+ECPGColLabel:  ECPGColLabelCommon      { $$ = $1; }
+               | reserved_keyword              { $$ = $1; }
+               | ECPGunreserved                { $$ = $1; }
+               | ECPGKeywords_rest             { $$ = $1; }
+               ;
+
+ECPGCKeywords: S_AUTO                  { $$ = make_str("auto"); }
+               | S_CONST                               { $$ = make_str("const"); }
+               | S_EXTERN                              { $$ = make_str("extern"); }
+               | S_REGISTER                    { $$ = make_str("register"); }
+               | S_STATIC                              { $$ = make_str("static"); }
+               | S_TYPEDEF                             { $$ = make_str("typedef"); }
+               | S_VOLATILE                    { $$ = make_str("volatile"); }
+               ;
+
+/*
+ * Keyword classification lists.  Generally, every keyword present in
+ * the Postgres grammar should appear in exactly one of these lists.
+ *
+ * Put a new keyword into the first list that it can go into without causing
+ * shift or reduce conflicts.  The earlier lists define "less reserved"
+ * categories of keywords.
+ */
+
+/* "Unreserved" keywords --- available for use as any kind of name.
+ */
+/* The following symbols must be excluded from ECPGColLabel and directly included into ColLabel
+   to enable C variables to get names from ECPGColLabel:
+   DAY_P, HOUR_P, MINUTE_P, MONTH_P, SECOND_P, YEAR_P
+ */
+unreserved_keyword: ECPGunreserved_interval | ECPGunreserved;
+
+ECPGunreserved_interval: DAY_P                 { $$ = make_str("day"); }
+               | HOUR_P                        { $$ = make_str("hour"); }
+               | MINUTE_P                      { $$ = make_str("minute"); }
+               | MONTH_P                       { $$ = make_str("month"); }
+               | SECOND_P                      { $$ = make_str("second"); }
+               | YEAR_P                        { $$ = make_str("year"); }
+               ;
+
+/* The following symbol must be excluded from var_name but still included in ColId
+   to enable ecpg special postgresql variables with this name:  CONNECTION
+ */
+ECPGunreserved:        ECPGunreserved_con              { $$ = $1; }
+               | CONNECTION                    { $$ = make_str("connection"); }
+               ;
+
+ECPGunreserved_con:      ABORT_P                       { $$ = make_str("abort"); }
+               | ABSOLUTE_P            { $$ = make_str("absolute"); }
+               | ACCESS                        { $$ = make_str("access"); }
+               | ACTION                        { $$ = make_str("action"); }
+               | ADD_P                         { $$ = make_str("add"); }
+               | ADMIN                         { $$ = make_str("admin"); }
+               | AFTER                         { $$ = make_str("after"); }
+               | AGGREGATE                     { $$ = make_str("aggregate"); }
+               | ALSO                          { $$ = make_str("also"); }
+               | ALTER                         { $$ = make_str("alter"); }
+               | ALWAYS                        { $$ = make_str("always"); }
+               | ASSERTION                     { $$ = make_str("assertion"); }
+               | ASSIGNMENT            { $$ = make_str("assignment"); }
+               | AT                            { $$ = make_str("at"); }
+               | BACKWARD                      { $$ = make_str("backward"); }
+               | BEFORE                        { $$ = make_str("before"); }
+               | BEGIN_P                       { $$ = make_str("begin"); }
+               | BY                            { $$ = make_str("by"); }
+               | CACHE                         { $$ = make_str("cache"); }
+               | CASCADE                       { $$ = make_str("cascade"); }
+               | CASCADED                      { $$ = make_str("cascaded"); }
+               | CHAIN                         { $$ = make_str("chain"); }
+               | CHARACTERISTICS       { $$ = make_str("characteristics"); }
+               | CHECKPOINT            { $$ = make_str("checkpoint"); }
+               | CLASS                         { $$ = make_str("class"); }
+               | CLOSE                         { $$ = make_str("close"); }
+               | CLUSTER                       { $$ = make_str("cluster"); }
+               | COMMENT                       { $$ = make_str("comment"); }
+               | COMMIT                        { $$ = make_str("commit"); }
+               | COMMITTED                     { $$ = make_str("committed"); }
+               | CONCURRENTLY          { $$ = make_str("concurrently"); }
+               | CONFIGURATION         { $$ = make_str("configuration"); }
+/*             | CONNECTION            { $$ = make_str("connection"); }*/
+               | CONSTRAINTS           { $$ = make_str("constraints"); }
+               | CONTENT_P             { $$ = make_str("content"); }
+               | CONTINUE_P            { $$ = make_str("continue"); }
+               | CONVERSION_P          { $$ = make_str("conversion"); }
+               | COPY                          { $$ = make_str("copy"); }
+               | COST                          { $$ = make_str("cost"); }
+               | CREATEDB                      { $$ = make_str("createdb"); }
+               | CREATEROLE            { $$ = make_str("createrole"); }
+               | CREATEUSER            { $$ = make_str("createuser"); }
+               | CSV                           { $$ = make_str("csv"); }
+               | CTYPE                 { $$ = make_str("ctype"); }
+               | CURSOR                        { $$ = make_str("cursor"); }
+               | CYCLE                         { $$ = make_str("cycle"); }
+               | DATA_P                        { $$ = make_str("data"); }
+               | DATABASE                      { $$ = make_str("database"); }
+/*             | DAY_P                         { $$ = make_str("day"); }*/
+               | DEALLOCATE            { $$ = make_str("deallocate"); }
+               | DECLARE                       { $$ = make_str("declare"); }
+               | DEFAULTS                      { $$ = make_str("defaults"); }
+               | DEFERRED                      { $$ = make_str("deferred"); }
+               | DELETE_P                      { $$ = make_str("delete"); }
+               | DELIMITER                     { $$ = make_str("delimiter"); }
+               | DELIMITERS            { $$ = make_str("delimiters"); }
+               | DICTIONARY            { $$ = make_str("dictionary"); }
+               | DISABLE_P                     { $$ = make_str("disable"); }
+               | DISCARD                       { $$ = make_str("discard"); }
+               | DOCUMENT_P                    { $$ = make_str("document"); }
+               | DOMAIN_P                      { $$ = make_str("domain"); }
+               | DOUBLE_P                      { $$ = make_str("double"); }
+               | DROP                          { $$ = make_str("drop"); }
+               | EACH                          { $$ = make_str("each"); }
+               | ENABLE_P                      { $$ = make_str("enable"); }
+               | ENCODING                      { $$ = make_str("encoding"); }
+               | ENCRYPTED                     { $$ = make_str("encrypted"); }
+/*             | ENUM_P                        { $$ = make_str("enum"); }*/
+               | ESCAPE                        { $$ = make_str("escape"); }
+               | EXCLUDING                     { $$ = make_str("excluding"); }
+               | EXCLUSIVE                     { $$ = make_str("exclusive"); }
+               | EXECUTE                       { $$ = make_str("execute"); }
+               | EXPLAIN                       { $$ = make_str("explain"); }
+               | EXTERNAL                      { $$ = make_str("external"); }
+               | FAMILY                        { $$ = make_str("family"); }
+/*             | FETCH                         { $$ = make_str("fetch"); }*/
+               | FIRST_P                       { $$ = make_str("first"); }
+               | FORCE                         { $$ = make_str("force"); }
+               | FORWARD                       { $$ = make_str("forward"); }
+               | FUNCTION                      { $$ = make_str("function"); }
+               | GLOBAL                        { $$ = make_str("global"); }
+               | GRANTED                       { $$ = make_str("granted"); }
+               | HANDLER                       { $$ = make_str("handler"); }
+               | HEADER_P                      { $$ = make_str("header"); }
+               | HOLD                          { $$ = make_str("hold"); }
+/*             | HOUR_P                        { $$ = make_str("hour"); }*/
+               | IDENTITY_P                    { $$ = make_str("identity"); }
+               | IF_P                          { $$ = make_str("if"); }
+               | IMMEDIATE                     { $$ = make_str("immediate"); }
+               | IMMUTABLE                     { $$ = make_str("immutable"); }
+               | IMPLICIT_P            { $$ = make_str("implicit"); }
+               | INCLUDING                     { $$ = make_str("including"); }
+               | INCREMENT                     { $$ = make_str("increment"); }
+               | INDEX                         { $$ = make_str("index"); }
+               | INDEXES                       { $$ = make_str("indexes"); }
+               | INHERIT                       { $$ = make_str("inherit"); }
+               | INHERITS                      { $$ = make_str("inherits"); }
+               | INSENSITIVE           { $$ = make_str("insensitive"); }
+               | INSERT                        { $$ = make_str("insert"); }
+               | INSTEAD                       { $$ = make_str("instead"); }
+               | ISOLATION                     { $$ = make_str("isolation"); }
+               | KEY                           { $$ = make_str("key"); }
+               | LANCOMPILER           { $$ = make_str("lancompiler"); }
+               | LANGUAGE                      { $$ = make_str("language"); }
+               | LARGE_P                       { $$ = make_str("large"); }
+               | LAST_P                        { $$ = make_str("last"); }
+               | LEVEL                         { $$ = make_str("level"); }
+               | LISTEN                        { $$ = make_str("listen"); }
+               | LOAD                          { $$ = make_str("load"); }
+               | LOCAL                         { $$ = make_str("local"); }
+               | LOCATION                      { $$ = make_str("location"); }
+               | LOCK_P                        { $$ = make_str("lock"); }
+               | LOGIN_P                       { $$ = make_str("login"); }
+               | MAPPING                       { $$ = make_str("mapping"); }
+               | MATCH                         { $$ = make_str("match"); }
+               | MAXVALUE                      { $$ = make_str("maxvalue"); }
+/*             | MINUTE_P                      { $$ = make_str("minute"); }*/
+               | MINVALUE                      { $$ = make_str("minvalue"); }
+               | MODE                          { $$ = make_str("mode"); }
+/*             | MONTH_P                       { $$ = make_str("month"); }*/
+               | MOVE                          { $$ = make_str("move"); }
+               | NAME_P                        { $$ = make_str("name"); }
+               | NAMES                         { $$ = make_str("names"); }
+               | NEXT                          { $$ = make_str("next"); }
+               | NO                            { $$ = make_str("no"); }
+               | NOCREATEDB            { $$ = make_str("nocreatedb"); }
+               | NOCREATEROLE          { $$ = make_str("nocreaterole"); }
+               | NOCREATEUSER          { $$ = make_str("nocreateuser"); }
+               | NOINHERIT                     { $$ = make_str("noinherit"); }
+               | NOLOGIN_P             { $$ = make_str("nologin"); }
+               | NOSUPERUSER           { $$ = make_str("nosuperuser"); }
+               | NOTHING                       { $$ = make_str("nothing"); }
+               | NOTIFY                        { $$ = make_str("notify"); }
+               | NOWAIT                        { $$ = make_str("nowait"); }
+               | NULLS_P                       { $$ = make_str("nulls"); }
+               | OBJECT_P                      { $$ = make_str("object"); }
+               | OF                            { $$ = make_str("of"); }
+               | OIDS                          { $$ = make_str("oids"); }
+               | OPERATOR                      { $$ = make_str("operator"); }
+               | OPTION                        { $$ = make_str("option"); }
+               | OWNED                         { $$ = make_str("owned"); }
+               | OWNER                         { $$ = make_str("owner"); }
+               | PARSER                        { $$ = make_str("parser"); }
+               | PARTIAL                       { $$ = make_str("partial"); }
+               | PASSWORD                      { $$ = make_str("password"); }
+               | PLANS                         { $$ = make_str("plans"); }
+               | PREPARE                       { $$ = make_str("prepare"); }
+               | PREPARED                      { $$ = make_str("prepared"); }
+               | PRESERVE                      { $$ = make_str("preserver"); }
+               | PRIOR                         { $$ = make_str("prior"); }
+               | PRIVILEGES            { $$ = make_str("privileges"); }
+               | PROCEDURAL            { $$ = make_str("procedural"); }
+               | PROCEDURE                     { $$ = make_str("procedure"); }
+               | QUOTE                         { $$ = make_str("quote"); }
+               | READ                          { $$ = make_str("read"); }
+               | REASSIGN                      { $$ = make_str("reassign"); }
+               | RECHECK                       { $$ = make_str("recheck"); }
+               | RECURSIVE                     { $$ = make_str("recursive"); }
+               | REINDEX                       { $$ = make_str("reindex"); }
+               | RELATIVE_P            { $$ = make_str("relative"); }
+               | RELEASE                       { $$ = make_str("release"); }
+               | RENAME                        { $$ = make_str("rename"); }
+               | REPEATABLE            { $$ = make_str("repeatable"); }
+               | REPLACE                       { $$ = make_str("replace"); }
+               | REPLICA                       { $$ = make_str("replica"); }
+               | RESET                         { $$ = make_str("reset"); }
+               | RESTART                       { $$ = make_str("restart"); }
+               | RESTRICT                      { $$ = make_str("restrict"); }
+               | RETURNS                       { $$ = make_str("returns"); }
+               | REVOKE                        { $$ = make_str("revoke"); }
+               | ROLE                          { $$ = make_str("role"); }
+               | ROLLBACK                      { $$ = make_str("rollback"); }
+               | ROWS                          { $$ = make_str("rows"); }
+               | RULE                          { $$ = make_str("rule"); }
+               | SAVEPOINT                     { $$ = make_str("savepoint"); }
+               | SCHEMA                        { $$ = make_str("schema"); }
+               | SCROLL                        { $$ = make_str("scroll"); }
+               | SEARCH                        { $$ = make_str("search"); }
+/*             | SECOND_P                      { $$ = make_str("second"); }*/
+               | SEQUENCE                      { $$ = make_str("sequence"); }
+               | SERIALIZABLE          { $$ = make_str("serializable"); }
+               | SESSION                       { $$ = make_str("session"); }
+               | SET                           { $$ = make_str("set"); }
+               | SHARE                         { $$ = make_str("share"); }
+               | SHOW                          { $$ = make_str("show"); }
+               | SIMPLE                        { $$ = make_str("simple"); }
+               | STABLE                        { $$ = make_str("stable"); }
+               | STANDALONE_P                  { $$ = make_str("standalone"); }
+               | START                         { $$ = make_str("start"); }
+               | STATEMENT                     { $$ = make_str("statement"); }
+               | STATISTICS            { $$ = make_str("statistics"); }
+               | STDIN                         { $$ = make_str("stdin"); }
+               | STDOUT                        { $$ = make_str("stdout"); }
+               | STORAGE                       { $$ = make_str("storage"); }
+               | STRICT_P                      { $$ = make_str("strict"); }
+               | STRIP_P                       { $$ = make_str("strip"); }
+               | SUPERUSER_P           { $$ = make_str("superuser"); }
+               | SYSTEM_P                      { $$ = make_str("system"); }
+               | SYSID                         { $$ = make_str("sysid"); }
+               | TABLESPACE            { $$ = make_str("tablespace"); }
+               | TEMP                          { $$ = make_str("temp"); }
+               | TEMPLATE                      { $$ = make_str("template"); }
+               | TEMPORARY                     { $$ = make_str("temporary"); }
+               | TEXT_P                        { $$ = make_str("text"); }
+               | TRANSACTION           { $$ = make_str("transaction"); }
+               | TRIGGER                       { $$ = make_str("trigger"); }
+               | TRUNCATE                      { $$ = make_str("truncate"); }
+               | TRUSTED                       { $$ = make_str("trusted"); }
+               | TYPE_P                        { $$ = make_str("type"); }
+               | UNCOMMITTED           { $$ = make_str("uncommitted"); }
+               | UNENCRYPTED           { $$ = make_str("unencrypted"); }
+               | UNKNOWN                       { $$ = make_str("unknown"); }
+               | UNLISTEN                      { $$ = make_str("unlisten"); }
+               | UNTIL                         { $$ = make_str("until"); }
+               | UPDATE                        { $$ = make_str("update"); }
+               | VACUUM                        { $$ = make_str("vacuum"); }
+               | VALID                         { $$ = make_str("valid"); }
+               | VALIDATOR                     { $$ = make_str("validator"); }
+               | VALUE_P                       { $$ = make_str("value"); }
+               | VARYING                       { $$ = make_str("varying"); }
+               | VERSION_P                     { $$ = make_str("version"); }
+               | VIEW                          { $$ = make_str("view"); }
+               | VOLATILE                      { $$ = make_str("volatile"); }
+               | WHITESPACE_P                  { $$ = make_str("whitespace"); }
+               | WITHOUT                       { $$ = make_str("without"); }
+               | WORK                          { $$ = make_str("work"); }
+               | WRITE                         { $$ = make_str("write"); }
+               | XML_P                         { $$ = make_str("xml"); }
+               | YES_P                         { $$ = make_str("yes"); }
+/*             | YEAR_P                        { $$ = make_str("year"); }*/
+               | ZONE                          { $$ = make_str("zone"); }
+               ;
+
+into_list : coutputvariable | into_list ',' coutputvariable
+               ;
+
+ecpgstart: SQL_START   {
+                               reset_variables();
+                               pacounter = 1;
+                       }
+               ;
+
+c_args: /*EMPTY*/              { $$ = EMPTY; }
+               | c_list                { $$ = $1; }
+               ;
+
+coutputvariable: cvariable indicator
+                       { add_variable_to_head(&argsresult, find_variable($1), find_variable($2)); }
+               | cvariable
+                       { add_variable_to_head(&argsresult, find_variable($1), &no_indicator); }
+               ;
+
+
+civarind: cvariable indicator
+               {
+                       if (find_variable($2)->type->type == ECPGt_array)
+                               mmerror(PARSE_ERROR, ET_ERROR, "arrays of indicators are not allowed on input");
+
+                       add_variable_to_head(&argsinsert, find_variable($1), find_variable($2));
+                       $$ = create_questionmarks($1, false);
+               }
+               ;
+
+civar: cvariable
+               {
+                       add_variable_to_head(&argsinsert, find_variable($1), &no_indicator);
+                       $$ = create_questionmarks($1, false);
+               }
+               ;
+
+indicator: cvariable                           { check_indicator((find_variable($1))->type); $$ = $1; }
+               | SQL_INDICATOR cvariable       { check_indicator((find_variable($2))->type); $$ = $2; }
+               | SQL_INDICATOR name            { check_indicator((find_variable($2))->type); $$ = $2; }
+               ;
+
+cvariable:     CVARIABLE
+               {
+                       /* As long as multidimensional arrays are not implemented we have to check for those here */
+                       char *ptr = $1;
+                       int brace_open=0, brace = false;
+
+                       for (; *ptr; ptr++)
+                       {
+                               switch (*ptr)
+                               {
+                                       case '[':
+                                                       if (brace)
+                                                               mmerror(PARSE_ERROR, ET_FATAL, "no multidimensional array support for simple data types");
+                                                       brace_open++;
+                                                       break;
+                                       case ']':
+                                                       brace_open--;
+                                                       if (brace_open == 0)
+                                                               brace = true;
+                                                       break;
+                                       case '\t':
+                                       case ' ':
+                                                       break;
+                                       default:
+                                                       if (brace_open == 0)
+                                                               brace = false;
+                                                       break;
+                               }
+                       }
+                       $$ = $1;
+               }
+               ;
+
+ecpg_param:    PARAM           { $$ = make_name(); } ;
+
+ecpg_bconst:   BCONST          { $$ = make_name(); } ;
+
+ecpg_fconst:   FCONST          { $$ = make_name(); } ;
+
+ecpg_sconst:
+               SCONST
+               {
+                       /* could have been input as '' or $$ */
+                       $$ = (char *)mm_alloc(strlen($1) + 3);
+                       $$[0]='\'';
+                       strcpy($$+1, $1);
+                       $$[strlen($1)+1]='\'';
+                       $$[strlen($1)+2]='\0';
+                       free($1);
+               }
+               | ECONST
+               {
+                       $$ = (char *)mm_alloc(strlen($1) + 4);
+                       $$[0]='E';
+                       $$[1]='\'';
+                       strcpy($$+2, $1);
+                       $$[strlen($1)+2]='\'';
+                       $$[strlen($1)+3]='\0';
+                       free($1);
+               }
+               | NCONST
+               {
+                       $$ = (char *)mm_alloc(strlen($1) + 4);
+                       $$[0]='N';
+                       $$[1]='\'';
+                       strcpy($$+2, $1);
+                       $$[strlen($1)+2]='\'';
+                       $$[strlen($1)+3]='\0';
+                       free($1);
+               }
+               | UCONST        { $$ = $1; }
+               | DOLCONST      { $$ = $1; }
+               ;
+
+ecpg_xconst:   XCONST          { $$ = make_name(); } ;
+
+ecpg_ident:    IDENT           { $$ = make_name(); }
+               | CSTRING       { $$ = make3_str(make_str("\""), $1, make_str("\"")) }
+               | UIDENT        { $$ = $1; }
+               ;
+
+quoted_ident_stringvar: name
+                       { $$ = make3_str(make_str("\""), $1, make_str("\"")); }
+               | char_variable
+                       { $$ = make3_str(make_str("("), $1, make_str(")")); }
+               ;
+
+/*
+ * C stuff
+ */
+
+c_stuff_item: c_anything                       { $$ = $1; }
+               | '(' ')'                       { $$ = make_str("()"); }
+               | '(' c_stuff ')'
+                       { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
+               ;
+
+c_stuff: c_stuff_item                  { $$ = $1; }
+               | c_stuff c_stuff_item
+                       { $$ = cat2_str($1, $2); }
+               ;
+
+c_list: c_term                         { $$ = $1; }
+               | c_list ',' c_term     { $$ = cat_str(3, $1, make_str(","), $3); }
+               ;
+
+c_term:  c_stuff                       { $$ = $1; }
+               | '{' c_list '}'        { $$ = cat_str(3, make_str("{"), $2, make_str("}")); }
+               ;
+
+c_thing:       c_anything              { $$ = $1; }
+               |       '('             { $$ = make_str("("); }
+               |       ')'             { $$ = make_str(")"); }
+               |       ','             { $$ = make_str(","); }
+               |       ';'             { $$ = make_str(";"); }
+               ;
+
+c_anything:  ecpg_ident                                { $$ = $1; }
+               | Iconst                        { $$ = $1; }
+               | ecpg_fconst                   { $$ = $1; }
+               | ecpg_sconst                   { $$ = $1; }
+               | '*'                           { $$ = make_str("*"); }
+               | '+'                           { $$ = make_str("+"); }
+               | '-'                           { $$ = make_str("-"); }
+               | '/'                           { $$ = make_str("/"); }
+               | '%'                           { $$ = make_str("%"); }
+               | NULL_P                        { $$ = make_str("NULL"); }
+               | S_ADD                         { $$ = make_str("+="); }
+               | S_AND                         { $$ = make_str("&&"); }
+               | S_ANYTHING                    { $$ = make_name(); }
+               | S_AUTO                        { $$ = make_str("auto"); }
+               | S_CONST                       { $$ = make_str("const"); }
+               | S_DEC                         { $$ = make_str("--"); }
+               | S_DIV                         { $$ = make_str("/="); }
+               | S_DOTPOINT                    { $$ = make_str(".*"); }
+               | S_EQUAL                       { $$ = make_str("=="); }
+               | S_EXTERN                      { $$ = make_str("extern"); }
+               | S_INC                         { $$ = make_str("++"); }
+               | S_LSHIFT                      { $$ = make_str("<<"); }
+               | S_MEMBER                      { $$ = make_str("->"); }
+               | S_MEMPOINT                    { $$ = make_str("->*"); }
+               | S_MOD                         { $$ = make_str("%="); }
+               | S_MUL                         { $$ = make_str("*="); }
+               | S_NEQUAL                      { $$ = make_str("!="); }
+               | S_OR                          { $$ = make_str("||"); }
+               | S_REGISTER                    { $$ = make_str("register"); }
+               | S_RSHIFT                      { $$ = make_str(">>"); }
+               | S_STATIC                      { $$ = make_str("static"); }
+               | S_SUB                         { $$ = make_str("-="); }
+               | S_TYPEDEF                     { $$ = make_str("typedef"); }
+               | S_VOLATILE                    { $$ = make_str("volatile"); }
+               | SQL_BOOL                      { $$ = make_str("bool"); }
+               | ENUM_P                        { $$ = make_str("enum"); }
+               | HOUR_P                        { $$ = make_str("hour"); }
+               | INT_P                         { $$ = make_str("int"); }
+               | SQL_LONG                      { $$ = make_str("long"); }
+               | MINUTE_P                      { $$ = make_str("minute"); }
+               | MONTH_P                       { $$ = make_str("month"); }
+               | SECOND_P                      { $$ = make_str("second"); }
+               | SQL_SHORT                     { $$ = make_str("short"); }
+               | SQL_SIGNED                    { $$ = make_str("signed"); }
+               | SQL_STRUCT                    { $$ = make_str("struct"); }
+               | SQL_UNSIGNED                  { $$ = make_str("unsigned"); }
+               | YEAR_P                        { $$ = make_str("year"); }
+               | CHAR_P                        { $$ = make_str("char"); }
+               | FLOAT_P                       { $$ = make_str("float"); }
+               | TO                            { $$ = make_str("to"); }
+               | UNION                         { $$ = make_str("union"); }
+               | VARCHAR                       { $$ = make_str("varchar"); }
+               | '['                           { $$ = make_str("["); }
+               | ']'                           { $$ = make_str("]"); }
+               | '='                           { $$ = make_str("="); }
+               | ':'                           { $$ = make_str(":"); }
+               ;
+
+DeallocateStmt: DEALLOCATE prepared_name                { $$ = $2; }
+                | DEALLOCATE PREPARE prepared_name      { $$ = $3; }
+                | DEALLOCATE ALL                        { $$ = make_str("all"); }
+                | DEALLOCATE PREPARE ALL                { $$ = make_str("all"); }
+                ;
+
+Iresult:        Iconst                 { $$ = $1; }
+                | '(' Iresult ')'       { $$ = cat_str(3, make_str("("), $2, make_str(")")); }
+                | Iresult '+' Iresult   { $$ = cat_str(3, $1, make_str("+"), $3); }
+                | Iresult '-' Iresult   { $$ = cat_str(3, $1, make_str("-"), $3); }
+                | Iresult '*' Iresult   { $$ = cat_str(3, $1, make_str("*"), $3); }
+                | Iresult '/' Iresult   { $$ = cat_str(3, $1, make_str("/"), $3); }
+                | Iresult '%' Iresult   { $$ = cat_str(3, $1, make_str("%"), $3); }
+                | ecpg_sconst          { $$ = $1; }
+                | ColId                 { $$ = $1; }
+                ;
+
+execute_rest: /* EMPTY */      { $$ = EMPTY; }
+       | ecpg_using ecpg_into  { $$ = EMPTY; }
+       | ecpg_into ecpg_using  { $$ = EMPTY; }
+       | ecpg_using            { $$ = EMPTY; }
+       | ecpg_into             { $$ = EMPTY; }
+       ; 
+
+ecpg_into: INTO into_list      { $$ = EMPTY; }
+        | into_descriptor      { $$ = $1; }
+       ;
+
+%%
+
+void base_yyerror(const char * error)
+{
+       char buf[1024];
+
+       snprintf(buf,sizeof buf, _("%s at or near \"%s\""), error, token_start ? token_start : yytext);
+       buf[sizeof(buf)-1]=0;
+       mmerror(PARSE_ERROR, ET_ERROR, buf);
+}
+
+void parser_init(void)
+{
+ /* This function is empty. It only exists for compatibility with the backend parser right now. */
+}
+
+/*
+ * Must undefine base_yylex before including pgc.c, since we want it
+ * to create the function base_yylex not filtered_base_yylex.
+ */
+#undef base_yylex
+
+#include "pgc.c"
diff --git a/src/interfaces/ecpg/preproc/ecpg.type b/src/interfaces/ecpg/preproc/ecpg.type
new file mode 100644 (file)
index 0000000..11f3d23
--- /dev/null
@@ -0,0 +1,143 @@
+/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.type,v 1.1 2008/11/14 10:03:33 meskes Exp $ */
+%type <str> ECPGAllocateDescr
+%type <str> ECPGCKeywords
+%type <str> ECPGColId
+%type <str> ECPGColLabel
+%type <str> ECPGColLabelCommon
+%type <str> ECPGConnect
+%type <str> ECPGCursorStmt
+%type <str> ECPGDeallocateDescr
+%type <str> ECPGDeclaration
+%type <str> ECPGDeclare
+%type <str> ECPGDescribe
+%type <str> ECPGDisconnect
+%type <str> ECPGExecuteImmediateStmt
+%type <str> ECPGFree
+%type <str> ECPGGetDescHeaderItem
+%type <str> ECPGGetDescItem
+%type <str> ECPGGetDescriptorHeader
+%type <str> ECPGKeywords
+%type <str> ECPGKeywords_rest
+%type <str> ECPGKeywords_vanames
+%type <str> ECPGOpen
+%type <str> ECPGSetAutocommit
+%type <str> ECPGSetConnection
+%type <str> ECPGSetDescHeaderItem
+%type <str> ECPGSetDescItem
+%type <str> ECPGSetDescriptorHeader
+%type <str> ECPGTypeName
+%type <str> ECPGTypedef
+%type <str> ECPGVar
+%type <str> ECPGVarDeclaration
+%type <str> ECPGWhenever
+%type <str> ECPGunreserved
+%type <str> ECPGunreserved_con
+%type <str> ECPGunreserved_interval
+%type <str> UsingConst
+%type <str> UsingValue
+%type <str> c_anything
+%type <str> c_args
+%type <str> c_list
+%type <str> c_stuff
+%type <str> c_stuff_item
+%type <str> c_term
+%type <str> c_thing
+%type <str> char_variable
+%type <str> civar
+%type <str> civarind
+%type <str> ColLabel
+%type <str> connect_options
+%type <str> connection_object
+%type <str> connection_target
+%type <str> coutputvariable
+%type <str> cvariable
+%type <str> db_prefix
+%type <str> CreateAsStmt
+%type <str> DeallocateStmt
+%type <str> dis_name
+%type <str> ecpg_bconst
+%type <str> ecpg_fconst
+%type <str> ecpg_ident
+%type <str> ecpg_interval
+%type <str> ecpg_into
+%type <str> ecpg_param
+%type <str> ecpg_sconst
+%type <str> ecpg_using
+%type <str> ecpg_xconst
+%type <str> enum_definition
+%type <str> enum_type
+%type <str> execstring
+%type <str> execute_rest
+%type <str> indicator
+%type <str> into_descriptor
+%type <str> Iresult
+%type <str> on_off
+%type <str> opt_bit_field
+%type <str> opt_connection_name
+%type <str> opt_database_name
+%type <str> opt_ecpg_using
+%type <str> opt_initializer
+%type <str> opt_options
+%type <str> opt_output
+%type <str> opt_pointer
+%type <str> opt_port
+%type <str> opt_reference
+%type <str> opt_scale
+%type <str> opt_server
+%type <str> opt_user
+%type <str> opt_opt_value
+%type <str> ora_user
+%type <str> precision
+%type <str> prepared_name
+%type <str> quoted_ident_stringvar
+%type <str> RuleStmt
+%type <str> s_struct_union
+%type <str> server
+%type <str> server_name
+%type <str> single_vt_declaration
+%type <str> storage_clause
+%type <str> storage_declaration
+%type <str> storage_modifier
+%type <str> struct_union_type
+%type <str> struct_union_type_with_symbol
+%type <str> symbol
+%type <str> type_declaration
+%type <str> unreserved_keyword 
+%type <str> user_name
+%type <str> using_descriptor
+%type <str> var_declaration
+%type <str> var_type_declarations
+%type <str> variable
+%type <str> variable_declarations
+%type <str> variable_list
+%type <str> vt_declarations 
+
+%type <str> Op
+%type <str> IntConstVar
+%type <str> AllConstVar
+%type <str> CSTRING
+%type <str> CPP_LINE
+%type <str> CVARIABLE
+%type <str> DOLCONST
+%type <str> ECONST
+%type <str> NCONST
+%type <str> SCONST
+%type <str> UCONST
+%type <str> UIDENT
+
+%type  <struct_union> s_struct_union_symbol
+
+%type  <descriptor> ECPGGetDescriptor
+%type  <descriptor> ECPGSetDescriptor
+
+%type  <type_enum> simple_type
+%type  <type_enum> signed_type
+%type  <type_enum> unsigned_type
+
+%type  <dtype_enum> descriptor_item
+%type  <dtype_enum> desc_header_item
+
+%type  <type>   var_type
+
+%type  <action> action
+