aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/ecpg/preproc
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/ecpg/preproc')
-rw-r--r--src/interfaces/ecpg/preproc/Makefile4
-rw-r--r--src/interfaces/ecpg/preproc/c_keywords.c1
-rw-r--r--src/interfaces/ecpg/preproc/ecpg.c1
-rw-r--r--src/interfaces/ecpg/preproc/ecpg_keywords.c1
-rw-r--r--src/interfaces/ecpg/preproc/extern.h2
-rw-r--r--src/interfaces/ecpg/preproc/pgc.l18
-rw-r--r--src/interfaces/ecpg/preproc/preproc.y72
-rw-r--r--src/interfaces/ecpg/preproc/type.c16
-rw-r--r--src/interfaces/ecpg/preproc/type.h1
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;