diff options
Diffstat (limited to 'src/interfaces/ecpg/preproc')
-rw-r--r-- | src/interfaces/ecpg/preproc/Makefile | 4 | ||||
-rw-r--r-- | src/interfaces/ecpg/preproc/c_keywords.c | 1 | ||||
-rw-r--r-- | src/interfaces/ecpg/preproc/ecpg.c | 1 | ||||
-rw-r--r-- | src/interfaces/ecpg/preproc/ecpg_keywords.c | 1 | ||||
-rw-r--r-- | src/interfaces/ecpg/preproc/extern.h | 2 | ||||
-rw-r--r-- | src/interfaces/ecpg/preproc/pgc.l | 18 | ||||
-rw-r--r-- | src/interfaces/ecpg/preproc/preproc.y | 72 | ||||
-rw-r--r-- | src/interfaces/ecpg/preproc/type.c | 16 | ||||
-rw-r--r-- | src/interfaces/ecpg/preproc/type.h | 1 |
9 files changed, 78 insertions, 38 deletions
diff --git a/src/interfaces/ecpg/preproc/Makefile b/src/interfaces/ecpg/preproc/Makefile index 87e788c83cc..66c8911c5a8 100644 --- a/src/interfaces/ecpg/preproc/Makefile +++ b/src/interfaces/ecpg/preproc/Makefile @@ -1,8 +1,8 @@ SRCDIR= ../../.. include $(SRCDIR)/Makefile.global -MAJOR_VERSION=2 -MINOR_VERSION=5 +MAJOR_VERSION=3 +MINOR_VERSION=0 PATCHLEVEL=0 CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \ diff --git a/src/interfaces/ecpg/preproc/c_keywords.c b/src/interfaces/ecpg/preproc/c_keywords.c index 5395b533d38..9a8b94bd256 100644 --- a/src/interfaces/ecpg/preproc/c_keywords.c +++ b/src/interfaces/ecpg/preproc/c_keywords.c @@ -36,6 +36,7 @@ static ScanKeyword ScanKeywords[] = { {"signed", S_SIGNED}, {"static", S_STATIC}, {"struct", S_STRUCT}, + {"union", S_UNION}, {"unsigned", S_UNSIGNED}, {"varchar", S_VARCHAR}, }; diff --git a/src/interfaces/ecpg/preproc/ecpg.c b/src/interfaces/ecpg/preproc/ecpg.c index 2594718cd12..6b37442c836 100644 --- a/src/interfaces/ecpg/preproc/ecpg.c +++ b/src/interfaces/ecpg/preproc/ecpg.c @@ -165,6 +165,7 @@ main(int argc, char *const argv[]) struct arguments *l1, *l2; free(ptr->command); + free(ptr->connection); free(ptr->name); for (l1 = ptr->argsinsert; l1; l1 = l2) { diff --git a/src/interfaces/ecpg/preproc/ecpg_keywords.c b/src/interfaces/ecpg/preproc/ecpg_keywords.c index 52eea065b83..25c1f2b9813 100644 --- a/src/interfaces/ecpg/preproc/ecpg_keywords.c +++ b/src/interfaces/ecpg/preproc/ecpg_keywords.c @@ -20,6 +20,7 @@ */ static ScanKeyword ScanKeywords[] = { /* name value */ + {"at", SQL_AT}, {"bool", SQL_BOOL}, {"break", SQL_BREAK}, {"call", SQL_CALL}, diff --git a/src/interfaces/ecpg/preproc/extern.h b/src/interfaces/ecpg/preproc/extern.h index d5bc1fc9cab..94c76a507af 100644 --- a/src/interfaces/ecpg/preproc/extern.h +++ b/src/interfaces/ecpg/preproc/extern.h @@ -6,7 +6,7 @@ extern int braces_open, no_auto_trans, struct_level; -extern char *yytext; +extern char *yytext, errortext[128]; extern int yylineno, yyleng; extern FILE *yyin, diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l index 5ddac659bbc..82369690763 100644 --- a/src/interfaces/ecpg/preproc/pgc.l +++ b/src/interfaces/ecpg/preproc/pgc.l @@ -105,7 +105,6 @@ xqstart {quote} xqstop {quote} xqdouble {quote}{quote} xqinside [^\\']* -xqembedded "\\'" xqliteral [\\](.|\n) xqcat {quote}{space}*\n{space}*{quote} @@ -244,22 +243,9 @@ cppline {space}*#.*(\\{space}*\n)*\n* return SCONST; } <xq>{xqdouble} | -<xq>{xqinside} { - if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1)) - yyerror("ERROR: quoted string parse buffer exceeded"); - memcpy(literal+llen, yytext, yyleng+1); - llen += yyleng; - } -<xq>{xqembedded} { - if ((llen+yyleng-1) > (MAX_PARSE_BUFFER - 1)) - yyerror("ERROR: quoted string parse buffer exceeded"); - memcpy(literal+llen, yytext, yyleng+1); - *(literal+llen) = '\''; - llen += yyleng; - } - +<xq>{xqinside} | <xq>{xqliteral} { - if ((llen+yyleng-1) > (MAX_PARSE_BUFFER - 1)) + if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1)) yyerror("ERROR: quoted string parse buffer exceeded"); memcpy(literal+llen, yytext, yyleng+1); llen += yyleng; diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index 7bb95d77e8c..ae5edf294d9 100644 --- a/src/interfaces/ecpg/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -18,7 +18,8 @@ * Variables containing simple states. */ int struct_level = 0; -static char errortext[128]; +char errortext[128]; +static char *connection = NULL; static int QueryIsRule = 0, ForUpdateNotAllowed = 0; static struct this_type actual_type[STRUCT_DEPTH]; static char *actual_storage[STRUCT_DEPTH]; @@ -489,7 +490,7 @@ output_statement(char * stmt, int mode) { int i, j=strlen(stmt); - fputs("ECPGdo(__LINE__, \"", yyout); + fprintf(yyout, "ECPGdo(__LINE__, %s, \"", connection ? connection : "NULL"); /* do this char by char as we have to filter '\"' */ for (i = 0;i < j; i++) @@ -504,6 +505,8 @@ output_statement(char * stmt, int mode) fputs("ECPGt_EORT);", yyout); whenever_action(mode); free(stmt); + if (connection != NULL) + free(connection); } static struct typedefs * @@ -612,7 +615,7 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim } /* special embedded SQL token */ -%token SQL_BOOL SQL_BREAK +%token SQL_AT SQL_BOOL SQL_BREAK %token SQL_CALL SQL_CONNECT SQL_CONNECTION SQL_CONTINUE %token SQL_DEALLOCATE SQL_DISCONNECT SQL_ENUM %token SQL_FOUND SQL_FREE SQL_GO SQL_GOTO @@ -625,8 +628,8 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim /* C token */ %token S_ANYTHING S_AUTO S_BOOL S_CHAR S_CONST S_DOUBLE S_ENUM S_EXTERN %token S_FLOAT S_INT S -%token S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT -%token S_UNSIGNED S_VARCHAR +%token S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT +%token S_UNION S_UNSIGNED S_VARCHAR /* I need this and don't know where it is defined inside the backend */ %token TYPECAST @@ -785,8 +788,9 @@ adjust_array(enum ECPGttype type_enum, int *dimension, int *length, int type_dim %type <str> ECPGSetConnection c_line cpp_line s_enum ECPGTypedef %type <str> enum_type civariableonly ECPGCursorStmt ECPGDeallocate %type <str> ECPGFree ECPGDeclare ECPGVar sql_variable_declarations -%type <str> sql_declaration sql_variable_list sql_variable +%type <str> sql_declaration sql_variable_list sql_variable opt_at %type <str> struct_type s_struct declaration variable_declarations +%type <str> s_struct_or_union sql_struct_or_union %type <type_enum> simple_type varchar_type @@ -803,13 +807,16 @@ prog: statements; statements: /* empty */ | statements statement -statement: ecpgstart stmt SQL_SEMI +statement: ecpgstart opt_at stmt SQL_SEMI { connection = NULL; } + | ecpgstart stmt SQL_SEMI | ECPGDeclaration | c_thing { fprintf(yyout, "%s", $1); free($1); } | cpp_line { fprintf(yyout, "%s", $1); free($1); } | blockstart { fputs($1, yyout); free($1); } | blockend { fputs($1, yyout); free($1); } +opt_at: SQL_AT connection_target { connection = $2; } + stmt: AddAttrStmt { output_statement($1, 0); } | AlterUserStmt { output_statement($1, 0); } | ClosePortalStmt { output_statement($1, 0); } @@ -853,7 +860,7 @@ stmt: AddAttrStmt { output_statement($1, 0); } } | RuleStmt { output_statement($1, 0); } | TransactionStmt { - fprintf(yyout, "ECPGtrans(__LINE__, \"%s\");", $1); + fprintf(yyout, "ECPGtrans(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1); whenever_action(0); free($1); } @@ -866,6 +873,9 @@ stmt: AddAttrStmt { output_statement($1, 0); } | VariableShowStmt { output_statement($1, 0); } | VariableResetStmt { output_statement($1, 0); } | ECPGConnect { + if (connection) + yyerror("no at option for connect statement.\n"); + fprintf(yyout, "no_auto_trans = %d;\n", no_auto_trans); fprintf(yyout, "ECPGconnect(__LINE__, %s);", $1); whenever_action(0); @@ -876,6 +886,9 @@ stmt: AddAttrStmt { output_statement($1, 0); } free($1); } | ECPGDeallocate { + if (connection) + yyerror("no at option for connect statement.\n"); + fputs($1, yyout); whenever_action(0); free($1); @@ -885,6 +898,9 @@ stmt: AddAttrStmt { output_statement($1, 0); } free($1); } | ECPGDisconnect { + if (connection) + yyerror("no at option for disconnect statement.\n"); + fprintf(yyout, "ECPGdisconnect(__LINE__, \"%s\");", $1); whenever_action(0); free($1); @@ -893,7 +909,7 @@ stmt: AddAttrStmt { output_statement($1, 0); } output_statement($1, 0); } | ECPGFree { - fprintf(yyout, "ECPGdeallocate(__LINE__, \"%s\");", $1); + fprintf(yyout, "ECPGdeallocate(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1); whenever_action(0); free($1); } @@ -912,7 +928,7 @@ stmt: AddAttrStmt { output_statement($1, 0); } yyerror(errortext); } - fprintf(yyout, "ECPGdo(__LINE__, \"%s\",", ptr->command); + fprintf(yyout, "ECPGdo(__LINE__, %s, \"%s\",", ptr->connection ? ptr->connection : "NULL", ptr->command); /* dump variables to C file*/ dump_variables(ptr->argsinsert, 0); dump_variables(argsinsert, 0); @@ -923,25 +939,40 @@ stmt: AddAttrStmt { output_statement($1, 0); } free($1); } | ECPGPrepare { + if (connection) + yyerror("no at option for set connection statement.\n"); + fprintf(yyout, "ECPGprepare(__LINE__, %s);", $1); whenever_action(0); free($1); } | ECPGRelease { /* output already done */ } | ECPGSetConnection { + if (connection) + yyerror("no at option for set connection statement.\n"); + fprintf(yyout, "ECPGsetconn(__LINE__, %s);", $1); whenever_action(0); free($1); } | ECPGTypedef { + if (connection) + yyerror("no at option for typedef statement.\n"); + fputs($1, yyout); free($1); } | ECPGVar { + if (connection) + yyerror("no at option for var statement.\n"); + fputs($1, yyout); free($1); } | ECPGWhenever { + if (connection) + yyerror("no at option for whenever statement.\n"); + fputs($1, yyout); output_line_number(); free($1); @@ -2727,6 +2758,7 @@ CursorStmt: DECLARE name opt_cursor CURSOR FOR SelectStmt cursor_clause /* initial definition */ this->next = cur; this->name = $2; + this->connection = connection; this->command = cat2_str(cat5_str(make1_str("declare"), mm_strdup($2), $3, make1_str("cursor for"), $6), $7); this->argsinsert = argsinsert; this->argsresult = argsresult; @@ -3103,6 +3135,7 @@ Generic: generic generic: ident { $$ = $1; } | TYPE_P { $$ = make1_str("type"); } + | SQL_AT { $$ = make1_str("at"); } | SQL_BOOL { $$ = make1_str("bool"); } | SQL_BREAK { $$ = make1_str("break"); } | SQL_CALL { $$ = make1_str("call"); } @@ -4306,6 +4339,7 @@ ColId: ident { $$ = $1; } | VALID { $$ = make1_str("valid"); } | VERSION { $$ = make1_str("version"); } | ZONE { $$ = make1_str("zone"); } + | SQL_AT { $$ = make1_str("at"); } | SQL_BOOL { $$ = make1_str("bool"); } | SQL_BREAK { $$ = make1_str("break"); } | SQL_CALL { $$ = make1_str("call"); } @@ -4602,6 +4636,7 @@ ECPGCursorStmt: DECLARE name opt_cursor CURSOR FOR ident cursor_clause /* initial definition */ this->next = cur; this->name = $2; + this->connection = connection; this->command = cat5_str(make1_str("declare"), mm_strdup($2), $3, make1_str("cursor for ;;"), $7); this->argsresult = NULL; @@ -4731,14 +4766,17 @@ struct_type: s_struct '{' variable_declarations '}' $$ = cat4_str($1, make1_str("{"), $3, make1_str("}")); } -s_struct : S_STRUCT opt_symbol +s_struct : s_struct_or_union opt_symbol { struct_member_list[struct_level++] = NULL; if (struct_level >= STRUCT_DEPTH) yyerror("Too many levels in nested structure definition"); - $$ = cat2_str(make1_str("struct"), $2); + $$ = cat2_str($1, $2); } +s_struct_or_union: S_STRUCT { $$ = make1_str("struct"); } + | S_UNION { $$ = make1_str("union"); } + opt_symbol: /* empty */ { $$ = make1_str(""); } | symbol { $$ = $1; } @@ -4940,7 +4978,7 @@ ECPGRelease: TransactionStmt SQL_RELEASE if (strncmp($1, "begin", 5) == 0) yyerror("RELEASE does not make sense when beginning a transaction"); - fprintf(yyout, "ECPGtrans(__LINE__, \"%s\");", $1); + fprintf(yyout, "ECPGtrans(__LINE__, %s, \"%s\");", connection, $1); whenever_action(0); fprintf(yyout, "ECPGdisconnect(\"\");"); whenever_action(0); @@ -5151,7 +5189,7 @@ ctype: CHAR $$.type_index = -1; $$.type_dimension = -1; } - | SQL_STRUCT + | sql_struct_or_union { struct_member_list[struct_level++] = NULL; if (struct_level >= STRUCT_DEPTH) @@ -5159,7 +5197,7 @@ ctype: CHAR } '{' sql_variable_declarations '}' { ECPGfree_struct_member(struct_member_list[struct_level--]); - $$.type_str = cat3_str(make1_str("struct {"), $4, make1_str("}")); + $$.type_str = cat4_str($1, make1_str("{"), $4, make1_str("}")); $$.type_enum = ECPGt_struct; $$.type_index = -1; $$.type_dimension = -1; @@ -5175,6 +5213,9 @@ ctype: CHAR struct_member_list[struct_level] = this->struct_member_list; } +sql_struct_or_union: SQL_STRUCT { $$ = make1_str("struct"); } + | UNION { $$ = make1_str("union"); } + opt_signed: SQL_SIGNED | /* empty */ sql_variable_declarations: /* empty */ @@ -5735,6 +5776,7 @@ c_anything: IDENT { $$ = $1; } | S_SIGNED { $$ = make1_str("signed"); } | S_STATIC { $$ = make1_str("static"); } | S_STRUCT { $$ = make1_str("struct"); } + | S_UNION { $$ = make1_str("union"); } | S_UNSIGNED { $$ = make1_str("unsigned"); } | S_VARCHAR { $$ = make1_str("varchar"); } | S_ANYTHING { $$ = make_name(); } diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c index dd3546b50ad..b5144d5d9a7 100644 --- a/src/interfaces/ecpg/preproc/type.c +++ b/src/interfaces/ecpg/preproc/type.c @@ -164,7 +164,8 @@ get_type(enum ECPGttype typ) return ("ECPGt_char_variable"); break; default: - abort(); + sprintf(errortext, "illegal variable type %d\n", typ); + yyerror(errortext); } } @@ -357,7 +358,8 @@ ECPGfree_type(struct ECPGtype * typ) if (IS_SIMPLE_TYPE(typ->u.element->typ)) free(typ->u.element); else if (typ->u.element->typ == ECPGt_array) - abort(); /* Array of array, */ + /* Array of array, */ + yyerror("internal error, found multi-dimensional array\n"); else if (typ->u.element->typ == ECPGt_struct) { /* Array of structs. */ @@ -365,7 +367,10 @@ ECPGfree_type(struct ECPGtype * typ) free(typ->u.members); } else - abort(); + { + sprintf(errortext, "illegal variable type %d\n", typ); + yyerror(errortext); + } } else if (typ->typ == ECPGt_struct) { @@ -373,7 +378,10 @@ ECPGfree_type(struct ECPGtype * typ) free(typ->u.members); } else - abort(); + { + sprintf(errortext, "illegal variable type %d\n", typ); + yyerror(errortext); + } } free(typ); } diff --git a/src/interfaces/ecpg/preproc/type.h b/src/interfaces/ecpg/preproc/type.h index f9642d92766..59cf3be9009 100644 --- a/src/interfaces/ecpg/preproc/type.h +++ b/src/interfaces/ecpg/preproc/type.h @@ -101,6 +101,7 @@ struct cursor { char *name; char *command; + char *connection; struct arguments *argsinsert; struct arguments *argsresult; struct cursor *next; |