1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

From: Michael Meskes <meskes@topsystem.de>

+ Thu Apr 23 09:27:16 CEST 1998
+
+       - Also allow call in whenever statement with the same functionality
+         as do.
+
+ Thu Apr 23 12:29:28 CEST 1998
+
+       - Also rewrote variable declaration part. It is now possible to
+         declare more than one variable per line.
+       - Set version to 2.1.0
+
+ Fri Apr 24 13:50:15 CEST 1998
+
+       - Fixed some bugs.
+       - Set version to 2.1.1
This commit is contained in:
Marc G. Fournier
1998-04-24 12:10:20 +00:00
parent f2b64d3593
commit 7500a961f1
13 changed files with 341 additions and 258 deletions

View File

@ -121,8 +121,24 @@ Mon Apr 20 16:13:25 CEST 1998
Mon Apr 20 16:39:23 CEST 1998 Mon Apr 20 16:39:23 CEST 1998
- Cursor is opened when the open command is issued, not at declare time. - Cursor is opened when the open command is issued, not at declare time.
- Set version to 2.0.0
Tue Apr 21 12:53:49 CEST 1998 Tue Apr 21 12:53:49 CEST 1998
- Set indicator to amount of data really written (truncation). - Set indicator to amount of data really written (truncation).
Thu Apr 23 09:27:16 CEST 1998
- Also allow call in whenever statement with the same functionality
as do.
Thu Apr 23 12:29:28 CEST 1998
- Also rewrote variable declaration part. It is now possible to
declare more than one variable per line.
- Set version to 2.1.0
Fri Apr 24 13:50:15 CEST 1998
- Fixed some bugs.
- Set version to 2.1.1

View File

@ -35,8 +35,6 @@ There is no exec sql prepare statement.
The complete structure definition has to be listed inside the declare The complete structure definition has to be listed inside the declare
section for ecpg to be able to understand it. section for ecpg to be able to understand it.
Each variable has to be defined on a line on its own.
There is no way yet to fill a complete array with one call except arrays of There is no way yet to fill a complete array with one call except arrays of
[unsigned] char which are considered strings. [unsigned] char which are considered strings.
@ -54,4 +52,7 @@ exec sql disconnect {current|default|all|connectionname|connection_hostvar};
| CURRENT | CURRENT
commit release|commit work release auch disconnect commit release|commit work release auch disconnect
It is not neccessary to check for sql not found after all commands. It is not neccessary to check for "not found" after all commands.
It would be nice to be able to specify parts of a structure like :foo.bar or
:foo->bar.

View File

@ -21,7 +21,6 @@ ifeq ($(PORTNAME), linux)
install-shlib-dep := install-shlib install-shlib-dep := install-shlib
shlib := libecpg.so.$(SO_MAJOR_VERSION).$(SO_MINOR_VERSION) shlib := libecpg.so.$(SO_MAJOR_VERSION).$(SO_MINOR_VERSION)
LDFLAGS_SL = -shared -soname libecpg.so.$(SO_MAJOR_VERSION) LDFLAGS_SL = -shared -soname libecpg.so.$(SO_MAJOR_VERSION)
CFLAGS += $(CFLAGS_SL)
endif endif
endif endif
ifeq ($(PORTNAME), bsd) ifeq ($(PORTNAME), bsd)
@ -47,12 +46,12 @@ endif
all: libecpg.a $(shlib) all: libecpg.a $(shlib)
$(shlib): ecpglib.o typename.o $(shlib): ecpglib.sho typename.sho
$(LD) $(LDFLAGS_SL) -o $@ ecpglib.o typename.o $(LD) $(LDFLAGS_SL) -o $@ ecpglib.sho typename.sho
ln -sf $@ libecpg.so ln -sf $@ libecpg.so
clean: clean:
rm -f *.o *.a core a.out *~ $(shlib) libecpg.so rm -f *.o *.sho *.a core a.out *~ $(shlib) libecpg.so
dep depend: dep depend:
@ -70,6 +69,11 @@ uninstall::
libecpg.a : libecpg.a(ecpglib.o) libecpg.a(typename.o) libecpg.a : libecpg.a(ecpglib.o) libecpg.a(typename.o)
ecpglib.o : ecpglib.c ../include/ecpglib.h ../include/ecpgtype.h ecpglib.o : ecpglib.c ../include/ecpglib.h ../include/ecpgtype.h
$(CC) $(CFLAGS) -I../include $(PQ_INCLUDE) -c ecpglib.c $(CC) $(CFLAGS) -I../include $(PQ_INCLUDE) -c $< -o $@
typename.o : typename.c ../include/ecpgtype.h typename.o : typename.c ../include/ecpgtype.h
$(CC) $(CFLAGS) -I../include $(PQ_INCLUDE) -c typename.c $(CC) $(CFLAGS) -I../include $(PQ_INCLUDE) -c $< -o $@
ecpglib.sho : ecpglib.c ../include/ecpglib.h ../include/ecpgtype.h
$(CC) $(CFLAGS) $(CFLAGS_SL) -I../include $(PQ_INCLUDE) -c $< -o $@
typename.sho : typename.c ../include/ecpgtype.h
$(CC) $(CFLAGS) $(CFLAGS_SL) -I../include $(PQ_INCLUDE) -c $< -o $@

View File

@ -2,8 +2,8 @@ SRCDIR= ../../..
include $(SRCDIR)/Makefile.global include $(SRCDIR)/Makefile.global
MAJOR_VERSION=2 MAJOR_VERSION=2
MINOR_VERSION=0 MINOR_VERSION=1
PATCHLEVEL=0 PATCHLEVEL=1
CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \ CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \
-DMINOR_VERSION=$(MINOR_VERSION) -DPATCHLEVEL=$(PATCHLEVEL) \ -DMINOR_VERSION=$(MINOR_VERSION) -DPATCHLEVEL=$(PATCHLEVEL) \

View File

@ -27,7 +27,7 @@ static void
usage(char *progname) usage(char *progname)
{ {
fprintf(stderr, "ecpg - the postgresql preprocessor, version: %d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL); fprintf(stderr, "ecpg - the postgresql preprocessor, version: %d.%d.%d\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL);
fprintf(stderr, "Usage: %s: [-v] [-d] [-I include path] [ -o output file name] file1 [file2] ...\n", progname); fprintf(stderr, "Usage: %s: [-v] [-I include path] [ -o output file name] file1 [file2] ...\n", progname);
} }
static void static void
@ -51,7 +51,7 @@ main(int argc, char *const argv[])
add_include_path("/usr/local/include"); add_include_path("/usr/local/include");
add_include_path("."); add_include_path(".");
while ((c = getopt(argc, argv, "vdo:I:")) != EOF) while ((c = getopt(argc, argv, "vo:I:")) != EOF)
{ {
switch (c) switch (c)
{ {
@ -62,9 +62,6 @@ main(int argc, char *const argv[])
else else
out_option = 1; out_option = 1;
break; break;
case 'd':
debugging = 1;
break;
case 'I': case 'I':
add_include_path(optarg); add_include_path(optarg);
break; break;

View File

@ -21,6 +21,7 @@
*/ */
static ScanKeyword ScanKeywords[] = { static ScanKeyword ScanKeywords[] = {
/* name value */ /* name value */
{"call", SQL_CALL},
{"connect", SQL_CONNECT}, {"connect", SQL_CONNECT},
{"continue", SQL_CONTINUE}, {"continue", SQL_CONTINUE},
{"found", SQL_FOUND}, {"found", SQL_FOUND},

View File

@ -2,8 +2,7 @@
/* variables */ /* variables */
extern int debugging, extern int braces_open;
braces_open;
extern char *yytext; extern char *yytext;
extern int yylineno, extern int yylineno,
yyleng; yyleng;
@ -23,6 +22,18 @@ struct cursor { char *name;
extern struct cursor *cur; extern struct cursor *cur;
/* This is a linked list of the variable names and types. */
struct variable
{
char * name;
struct ECPGtype * type;
int brace_level;
struct variable * next;
};
extern struct ECPGtype ecpg_no_indicator;
extern struct variable no_indicator;
/* functions */ /* functions */
extern void lex_init(void); extern void lex_init(void);

View File

@ -70,6 +70,7 @@ struct _yy_buffer { YY_BUFFER_STATE buffer;
%x xb %x xb
%x xc %x xc
%x xd %x xd
%x xdc
%x xh %x xh
%x xm %x xm
%x xq %x xq
@ -261,7 +262,7 @@ sql [sS][qQ][lL]
<xd>{xdstop} { <xd>{xdstop} {
BEGIN(SQL); BEGIN(SQL);
yylval.str = strdup(literal); yylval.str = strdup(literal);
return (IDENT); return (CSTRING);
} }
<xd>{xdinside} { <xd>{xdinside} {
if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1)) if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1))
@ -269,7 +270,22 @@ sql [sS][qQ][lL]
memcpy(literal+llen, yytext, yyleng+1); memcpy(literal+llen, yytext, yyleng+1);
llen += yyleng; llen += yyleng;
} }
<C>{xdstart} {
BEGIN(xdc);
llen = 0;
*literal = '\0';
}
<xdc>{xdstop} {
BEGIN(C);
yylval.str = strdup(literal);
return (CSTRING);
}
<xdc>{xdinside} {
if ((llen+yyleng) > (MAX_PARSE_BUFFER - 1))
yyerror("ERROR: quoted string parse buffer exceeded");
memcpy(literal+llen, yytext, yyleng+1);
llen += yyleng;
}
<xm>{space}* { /* ignore */ } <xm>{space}* { /* ignore */ }
<xm>{xmstop} { <xm>{xmstop} {
@ -379,6 +395,10 @@ sql [sS][qQ][lL]
return (FCONST); return (FCONST);
} }
<SQL>:{identifier} {
yylval.str = strdup((char*)yytext+1);
return(CVARIABLE);
}
<SQL>{identifier} { <SQL>{identifier} {
int i; int i;
ScanKeyword *keyword; ScanKeyword *keyword;
@ -423,12 +443,14 @@ sql [sS][qQ][lL]
} }
} }
<C>";" { return(';'); } <C>";" { return(';'); }
<C>"," { return(','); }
<C>"*" { return('*'); }
<C>{space} { ECHO; } <C>{space} { ECHO; }
\{ { return('{'); } <C>\{ { return('{'); }
\} { return('}'); } <C>\} { return('}'); }
\[ { return('['); } <C>\[ { return('['); }
\] { return(']'); } <C>\] { return(']'); }
\= { return('='); } <C>\= { return('='); }
<C>{other} { return (S_ANYTHING); } <C>{other} { return (S_ANYTHING); }
<C>{exec}{space}{sql}{space}{include} { BEGIN(incl); } <C>{exec}{space}{sql}{space}{include} { BEGIN(incl); }
<incl>{space} /* eat the whitespace */ <incl>{space} /* eat the whitespace */

View File

@ -12,9 +12,10 @@
* Variables containing simple states. * Variables containing simple states.
*/ */
static int struct_level = 0; static int struct_level = 0;
static char *do_str = NULL, errortext[128]; static char errortext[128];
static int do_length = 0;
static int QueryIsRule = 0; static int QueryIsRule = 0;
static enum ECPGttype actual_type[128];
static char *actual_storage[128];
/* temporarily store record members while creating the data structure */ /* temporarily store record members while creating the data structure */
struct ECPGrecord_member *record_member_list[128] = { NULL }; struct ECPGrecord_member *record_member_list[128] = { NULL };
@ -22,6 +23,9 @@ struct ECPGrecord_member *record_member_list[128] = { NULL };
/* keep a list of cursors */ /* keep a list of cursors */
struct cursor *cur = NULL; struct cursor *cur = NULL;
struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, 0L, {NULL}};
struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL};
/* /*
* Handle the filename and line numbering. * Handle the filename and line numbering.
*/ */
@ -82,15 +86,6 @@ whenever_action()
*/ */
int braces_open; int braces_open;
/* This is a linked list of the variable names and types. */
struct variable
{
char * name;
struct ECPGtype * type;
int brace_level;
struct variable * next;
};
static struct variable * allvariables = NULL; static struct variable * allvariables = NULL;
static struct variable * static struct variable *
@ -105,7 +100,7 @@ find_variable(char * name)
return p; return p;
} }
sprintf(errorstring, "The variable :%s is not declared", name); sprintf(errorstring, "The variable %s is not declared", name);
yyerror(errorstring); yyerror(errorstring);
free (errorstring); free (errorstring);
@ -167,9 +162,6 @@ struct arguments {
static struct arguments * argsinsert = NULL; static struct arguments * argsinsert = NULL;
static struct arguments * argsresult = NULL; static struct arguments * argsresult = NULL;
static struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, 0L, {NULL}};
static struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL};
static void static void
reset_variables(void) reset_variables(void)
{ {
@ -209,7 +201,9 @@ dump_variables(struct arguments * list)
dump_variables(list->next); dump_variables(list->next);
/* Then the current element and its indicator */ /* Then the current element and its indicator */
ECPGdump_a_type(yyout, list->variable->name, list->variable->type, list->indicator->name, list->indicator->type, NULL, NULL); ECPGdump_a_type(yyout, list->variable->name, list->variable->type,
(list->indicator->type->typ != ECPGt_NO_INDICATOR) ? list->indicator->name : NULL,
(list->indicator->type->typ != ECPGt_NO_INDICATOR) ? list->indicator->type : NULL, NULL, NULL);
/* Then release the list element. */ /* Then release the list element. */
free(list); free(list);
@ -360,7 +354,15 @@ make_name(void)
static void static void
output_statement(const char * stmt) output_statement(const char * stmt)
{ {
fprintf(yyout, "ECPGdo(__LINE__, \"%s\", ", stmt); int i, j=strlen(stmt);
fputs("ECPGdo(__LINE__, \"", yyout);
/* do this char by char as we have to filter '\"' */
for (i = 0;i < j; i++)
if (stmt[i] != '\"')
fputc(stmt[i], yyout);
fputs("\", ", yyout);
/* dump variables to C file*/ /* dump variables to C file*/
dump_variables(argsinsert); dump_variables(argsinsert);
@ -375,14 +377,14 @@ output_statement(const char * stmt)
double dval; double dval;
int ival; int ival;
char * str; char * str;
struct ECPGtemp_type type;
struct when action; struct when action;
struct index index;
int tagname; int tagname;
enum ECPGttype type_enum; enum ECPGttype type_enum;
} }
/* special embedded SQL token */ /* special embedded SQL token */
%token SQL_CONNECT SQL_CONTINUE SQL_FOUND SQL_GO SQL_GOTO %token SQL_CALL SQL_CONNECT SQL_CONTINUE SQL_FOUND SQL_GO SQL_GOTO
%token SQL_IMMEDIATE SQL_INDICATOR SQL_OPEN %token SQL_IMMEDIATE SQL_INDICATOR SQL_OPEN
%token SQL_SECTION SQL_SEMI SQL_SQLERROR SQL_SQLPRINT SQL_START %token SQL_SECTION SQL_SEMI SQL_SQLERROR SQL_SQLPRINT SQL_START
%token SQL_STOP SQL_WHENEVER %token SQL_STOP SQL_WHENEVER
@ -449,7 +451,7 @@ output_statement(const char * stmt)
%token USER, PASSWORD, CREATEDB, NOCREATEDB, CREATEUSER, NOCREATEUSER, VALID, UNTIL %token USER, PASSWORD, CREATEDB, NOCREATEDB, CREATEUSER, NOCREATEUSER, VALID, UNTIL
/* Special keywords, not in the query language - see the "lex" file */ /* Special keywords, not in the query language - see the "lex" file */
%token <str> IDENT SCONST Op %token <str> IDENT SCONST Op CSTRING CVARIABLE
%token <ival> ICONST PARAM %token <ival> ICONST PARAM
%token <dval> FCONST %token <dval> FCONST
@ -538,11 +540,18 @@ output_statement(const char * stmt)
%type <str> GrantStmt privileges operation_commalist operation %type <str> GrantStmt privileges operation_commalist operation
%type <str> ECPGWhenever ECPGConnect db_name ECPGOpen open_opts %type <str> ECPGWhenever ECPGConnect db_name ECPGOpen open_opts
%type <str> indicator ECPGExecute c_expr %type <str> indicator ECPGExecute c_expr variable_list dotext
%type <str> storage_clause opt_initializer vartext c_anything blockstart
%type <str> blockend variable_list variable var_anything sql_anything
%type <str> opt_pointer ecpg_ident cvariable identlist
%type <str> stmt symbol %type <str> stmt symbol
%type <type_enum> simple_type type struct_type
%type <action> action %type <action> action
%type <index> opt_index
%% %%
prog: statements; prog: statements;
@ -551,9 +560,9 @@ statements: /* empty */
statement: ecpgstart stmt SQL_SEMI statement: ecpgstart stmt SQL_SEMI
| ECPGDeclaration | ECPGDeclaration
| c_anything | c_anything { fputs($1, yyout); }
| blockstart | blockstart { fputs($1, yyout); }
| blockend | blockend { fputs($1, yyout); }
stmt: AddAttrStmt { output_statement($1); } stmt: AddAttrStmt { output_statement($1); }
| AlterUserStmt { output_statement($1); } | AlterUserStmt { output_statement($1); }
@ -1332,7 +1341,7 @@ TriggerFuncArg: Iconst
$$ = make_name(); $$ = make_name();
} }
| Sconst { $$ = $1; } | Sconst { $$ = $1; }
| IDENT { $$ = $1; } | ecpg_ident { $$ = $1; }
; ;
DropTrigStmt: DROP TRIGGER name ON relation_name DropTrigStmt: DROP TRIGGER name ON relation_name
@ -1829,7 +1838,7 @@ OptStmtMulti: OptStmtMulti OptimizableStmt ';'
event_object: relation_name '.' attr_name event_object: relation_name '.' attr_name
{ {
$$ = make3_str($1, ",", $3); $$ = cat3_str($1, ".", $3);
} }
| relation_name | relation_name
{ {
@ -2243,7 +2252,7 @@ sortby: ColId OptUseOp
} }
| ColId '.' ColId OptUseOp | ColId '.' ColId OptUseOp
{ {
$$ = make4_str($1, ".", $3, $4); $$ = make2_str(cat3_str($1, ".", $3), $4);
} }
| Iconst OptUseOp | Iconst OptUseOp
{ {
@ -2292,7 +2301,7 @@ groupby: ColId
} }
| ColId '.' ColId | ColId '.' ColId
{ {
$$ = make3_str($1, ",", $3); $$ = cat3_str($1, ",", $3);
} }
| Iconst | Iconst
{ {
@ -2383,7 +2392,7 @@ join_using: ColId
} }
| ColId '.' ColId | ColId '.' ColId
{ {
$$ = make3_str($1, ".", $3); $$ = cat3_str($1, ".", $3);
} }
| Iconst | Iconst
{ {
@ -2455,7 +2464,7 @@ Generic: generic
} }
; ;
generic: IDENT { $$ = $1; } generic: ecpg_ident { $$ = $1; }
| TYPE_P { $$ = "type"; } | TYPE_P { $$ = "type"; }
; ;
@ -3409,20 +3418,20 @@ not_in_expr_nodes: AexprConst
attr: relation_name '.' attrs attr: relation_name '.' attrs
{ {
$$ = make3_str($1, ".", $3); $$ = cat3_str($1, ".", $3);
} }
| ParamNo '.' attrs | ParamNo '.' attrs
{ {
$$ = make3_str($1, ".", $3); $$ = cat3_str($1, ".", $3);
} }
; ;
attrs: attr_name attrs: attr_name
{ $$ = $1; } { $$ = $1; }
| attrs '.' attr_name | attrs '.' attr_name
{ $$ = make3_str($1, ".", $3); } { $$ = cat3_str($1, ".", $3); }
| attrs '.' '*' | attrs '.' '*'
{ $$ = make2_str($1, ".*"); } { $$ = cat2_str($1, ".*"); }
; ;
@ -3449,7 +3458,7 @@ res_target_el: ColId opt_indirection '=' a_expr_or_null
} }
| relation_name '.' '*' | relation_name '.' '*'
{ {
$$ = make2_str($1, ".*"); $$ = cat2_str($1, ".*");
} }
; ;
@ -3475,7 +3484,7 @@ res_target_el2: a_expr_or_null AS ColLabel
} }
| relation_name '.' '*' | relation_name '.' '*'
{ {
$$ = make2_str($1, ".*"); $$ = cat2_str($1, ".*");
} }
| '*' | '*'
{ {
@ -3505,9 +3514,9 @@ relation_name: SpecialRuleRelation
; ;
database_name: ColId { $$ = $1; }; database_name: ColId { $$ = $1; };
access_method: IDENT { $$ = $1; }; access_method: ecpg_ident { $$ = $1; };
attr_name: ColId { $$ = $1; }; attr_name: ColId { $$ = $1; };
class: IDENT { $$ = $1; }; class: ecpg_ident { $$ = $1; };
index_name: ColId { $$ = $1; }; index_name: ColId { $$ = $1; };
/* Functions /* Functions
@ -3518,7 +3527,7 @@ name: ColId { $$ = $1; };
func_name: ColId { $$ = $1; }; func_name: ColId { $$ = $1; };
file_name: Sconst { $$ = $1; }; file_name: Sconst { $$ = $1; };
recipe_name: IDENT { $$ = $1; }; recipe_name: ecpg_ident { $$ = $1; };
/* Constants /* Constants
* Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24 * Include TRUE/FALSE for SQL3 support. - thomas 1997-10-24
@ -3569,7 +3578,7 @@ Sconst: SCONST {
$$[strlen($1)+2]='\0'; $$[strlen($1)+2]='\0';
$$[strlen($1)+1]='\''; $$[strlen($1)+1]='\'';
} }
UserId: IDENT { $$ = $1;}; UserId: ecpg_ident { $$ = $1;};
/* Column and type identifier /* Column and type identifier
* Does not include explicit datetime types * Does not include explicit datetime types
@ -3591,7 +3600,7 @@ TypeId: ColId
* list due to shift/reduce conflicts in yacc. If so, move * list due to shift/reduce conflicts in yacc. If so, move
* down to the ColLabel entity. - thomas 1997-11-06 * down to the ColLabel entity. - thomas 1997-11-06
*/ */
ColId: IDENT { $$ = $1; } ColId: ecpg_ident { $$ = $1; }
| datetime { $$ = $1; } | datetime { $$ = $1; }
| ACTION { $$ = "action"; } | ACTION { $$ = "action"; }
| CACHE { $$ = "cache"; } | CACHE { $$ = "cache"; }
@ -3688,169 +3697,139 @@ sql_enddeclare: ecpgstart END_TRANS DECLARE SQL_SECTION SQL_SEMI {
output_line_number(); output_line_number();
} }
variable_declarations : /* empty */ variable_declarations: /* empty */
| variable_declarations variable_declaration; | declaration variable_declarations;
/* Here is where we can enter support for typedef. */ declaration: storage_clause type
variable_declaration: type initializer ';' {
/* don't worry about our list when we're working on a struct */
if (struct_level == 0)
{ {
new_variable($<type>1.name, $<type>1.typ); actual_storage[struct_level] = $1;
free((void *)$<type>1.name); actual_type[struct_level] = $2;
if ($2 != ECPGt_varchar && $2 != ECPGt_record)
fprintf(yyout, "%s %s", $1, ECPGtype_name($2));
} }
fputs(";", yyout); variable_list ';' { fputc(';', yyout); }
}
initializer : /*empty */ storage_clause : S_EXTERN { $$ = "extern"; }
| '=' {fwrite(yytext, yyleng, 1, yyout);} vartext; | S_STATIC { $$ = "static"; }
| S_SIGNED { $$ = "signed"; }
| S_CONST { $$ = "const"; }
| S_REGISTER { $$ = "register"; }
| S_AUTO { $$ = "auto"; }
| /* empty */ { $$ = "" ; }
type : maybe_storage_clause type_detailed { $<type>$ = $<type>2; }; type: simple_type
type_detailed : varchar_type { $<type>$ = $<type>1; } | struct_type
| simple_type { $<type>$ = $<type>1; }
| string_type { $<type>$ = $<type>1; }
/* | array_type {$<type>$ = $<type>1; }
| pointer_type {$<type>$ = $<type>1; }*/
| struct_type {$<type>$ = $<type>1; };
varchar_type : varchar_tag symbol index { struct_type: s_struct '{' variable_declarations '}'
if ($<ival>3 > 0L)
fprintf(yyout, "struct varchar_%s { int len; char arr[%d]; } %s", $2, $<ival>3, $2);
else
fprintf(yyout, "struct varchar_%s { int len; char arr[]; } %s", $2, $2);
if (struct_level == 0)
{ {
$<type>$.name = $2; struct_level--;
$<type>$.typ = ECPGmake_varchar_type(ECPGt_varchar, $<ival>3); $$ = actual_type[struct_level] = ECPGt_record;
} }
else
ECPGmake_record_member($2, ECPGmake_varchar_type(ECPGt_varchar, $<ival>3), &(record_member_list[struct_level-1]));
}
varchar_tag: S_VARCHAR /*| S_VARCHAR2 */; s_struct : S_STRUCT symbol
simple_type : simple_tag symbol {
fprintf(yyout, "%s %s", ECPGtype_name($<type_enum>1), $2);
if (struct_level == 0)
{ {
$<type>$.name = $2;
$<type>$.typ = ECPGmake_simple_type($<type_enum>1, 1);
}
else
ECPGmake_record_member($2, ECPGmake_simple_type($<type_enum>1, 1), &(record_member_list[struct_level-1]));
}
string_type : char_tag symbol index {
if ($<ival>3 > 0L)
fprintf(yyout, "%s %s [%d]", ECPGtype_name($<type_enum>1), $2, $<ival>3);
else
fprintf(yyout, "%s %s []", ECPGtype_name($<type_enum>1), $2);
if (struct_level == 0)
{
$<type>$.name = $2;
$<type>$.typ = ECPGmake_simple_type($<type_enum>1, $<ival>3);
}
else
ECPGmake_record_member($2, ECPGmake_simple_type($<type_enum>1, $<ival>3), &(record_member_list[struct_level-1]));
}
| char_tag '*' symbol {
fprintf(yyout, "%s *%s", ECPGtype_name($<type_enum>1), $3);
if (struct_level == 0)
{
$<type>$.name = $3;
$<type>$.typ = ECPGmake_simple_type($<type_enum>1, 0);
}
else
ECPGmake_record_member($3, ECPGmake_simple_type($<type_enum>1, 0), &(record_member_list[struct_level-1]));
}
| char_tag symbol {
fprintf(yyout, "%s %s", ECPGtype_name($<type_enum>1), $2);
if (struct_level == 0)
{
$<type>$.name = $2;
$<type>$.typ = ECPGmake_simple_type($<type_enum>1, 1);
}
else
ECPGmake_record_member($2, ECPGmake_simple_type($<type_enum>1, 1), &(record_member_list[struct_level-1]));
}
char_tag : S_CHAR { $<type_enum>$ = ECPGt_char; }
| S_UNSIGNED S_CHAR { $<type_enum>$ = ECPGt_unsigned_char; }
/*
array_type : simple_tag symbol index {
if ($<ival>3 > 0)
fprintf(yyout, "%s %s [%ld]", ECPGtype_name($<type_enum>1), $2, $<ival>3);
else
fprintf(yyout, "%s %s []", ECPGtype_name($<type_enum>1), $2);
if (struct_level == 0)
{
$<type>$.name = $2;
$<type>$.typ = ECPGmake_array_type(ECPGmake_simple_type($<type_enum>1), $<ival>3);
}
else
ECPGmake_record_member($2, ECPGmake_array_type(ECPGmake_simple_type($<type_enum>1), $<ival>3), &(record_member_list[struct_level-1]));
}
pointer_type : simple_tag '*' symbol {
fprintf(yyout, "%s * %s", ECPGtype_name($<type_enum>1), $3);
if (struct_level == 0)
{
$<type>$.name = $3;
$<type>$.typ = ECPGmake_array_type(ECPGmake_simple_type($<type_enum>1), 0);
}
else
ECPGmake_record_member($3, ECPGmake_array_type(ECPGmake_simple_type($<type_enum>1), 0), &(record_member_list[struct_level-1]));
}
*/
s_struct : S_STRUCT symbol {
struct_level++; struct_level++;
fprintf(yyout, "struct %s {", $2); fprintf(yyout, "struct %s {", $2);
}
struct_type : s_struct '{' variable_declarations '}' symbol {
struct_level--;
if (struct_level == 0)
{
$<type>$.name = $5;
$<type>$.typ = ECPGmake_record_type(record_member_list[struct_level]);
} }
simple_type: S_SHORT { $$ = ECPGt_short; }
| S_UNSIGNED S_SHORT { $$ = ECPGt_unsigned_short; }
| S_INT { $$ = ECPGt_int; }
| S_UNSIGNED S_INT { $$ = ECPGt_unsigned_int; }
| S_LONG { $$ = ECPGt_long; }
| S_UNSIGNED S_LONG { $$ = ECPGt_unsigned_long; }
| S_FLOAT { $$ = ECPGt_float; }
| S_DOUBLE { $$ = ECPGt_double; }
| S_BOOL { $$ = ECPGt_bool; };
| S_CHAR { $$ = ECPGt_char; }
| S_UNSIGNED S_CHAR { $$ = ECPGt_unsigned_char; }
| S_VARCHAR { $$ = ECPGt_varchar; }
variable_list: variable
| variable_list ','
{
if (actual_type[struct_level] != ECPGt_varchar)
fputs(", ", yyout);
else else
ECPGmake_record_member($5, ECPGmake_record_type(record_member_list[struct_level]), &(record_member_list[struct_level-1])); fputs(";\n ", yyout);
fprintf(yyout, "} %s", $5); } variable
variable: opt_pointer symbol opt_index opt_initializer
{
int length = $3.ival;
/* pointer has to get length 0 */
if (strlen($1) > 0)
length = 0;
switch (actual_type[struct_level])
{
case ECPGt_record:
if (struct_level == 0)
new_variable($2, ECPGmake_record_type(record_member_list[struct_level]));
else
ECPGmake_record_member($2, ECPGmake_record_type(record_member_list[struct_level]), &(record_member_list[struct_level-1]));
record_member_list[struct_level] = NULL; record_member_list[struct_level] = NULL;
} fprintf(yyout, "} %s%s%s%s", $1, $2, $3.str, $4);
simple_tag : S_SHORT { $<type_enum>$ = ECPGt_short; } break;
| S_UNSIGNED S_SHORT { $<type_enum>$ = ECPGt_unsigned_short; } case ECPGt_varchar:
| S_INT { $<type_enum>$ = ECPGt_int; } if (strlen($4) != 0)
| S_UNSIGNED S_INT { $<type_enum>$ = ECPGt_unsigned_int; } yyerror("varchar initilization impossible");
| S_LONG { $<type_enum>$ = ECPGt_long; }
| S_UNSIGNED S_LONG { $<type_enum>$ = ECPGt_unsigned_long; }
| S_FLOAT { $<type_enum>$ = ECPGt_float; }
| S_DOUBLE { $<type_enum>$ = ECPGt_double; }
| S_BOOL { $<type_enum>$ = ECPGt_bool; };
maybe_storage_clause : S_EXTERN { fwrite(yytext, yyleng, 1, yyout); } if (struct_level == 0)
| S_STATIC { fwrite(yytext, yyleng, 1, yyout); } new_variable($2, ECPGmake_varchar_type(actual_type[struct_level], length));
| S_SIGNED { fwrite(yytext, yyleng, 1, yyout); } else
| S_CONST { fwrite(yytext, yyleng, 1, yyout); } ECPGmake_record_member($2, ECPGmake_varchar_type(actual_type[struct_level], length), &(record_member_list[struct_level-1]));
| S_REGISTER { fwrite(yytext, yyleng, 1, yyout); }
| S_AUTO { fwrite(yytext, yyleng, 1, yyout); }
| /* empty */ { };
index : '[' Iconst ']' { $<ival>$ = atol($2); } if (length > 0)
| '[' ']' { $<ival>$ = 0L; } fprintf(yyout, "%s struct varchar_%s { int len; char arr[%d]; } %s", actual_storage[struct_level], $2, length, $2);
else
fprintf(yyout, "%s struct varchar_%s { int len; char arr[]; } %s", actual_storage[struct_level], $2, $2);
break;
default:
if (struct_level == 0)
new_variable($2, ECPGmake_simple_type(actual_type[struct_level], length));
else
ECPGmake_record_member($2, ECPGmake_simple_type(actual_type[struct_level], length), &(record_member_list[struct_level-1]));
fprintf(yyout, "%s%s%s%s", $1, $2, $3.str, $4);
break;
}
}
opt_initializer: /* empty */ { $$ = ""; }
| '=' vartext { $$ = cat2_str("=", $2); }
opt_pointer: /* empty */ { $$ = ""; }
| '*' { $$ = "*"; }
opt_index: '[' Iconst ']' {
$$.ival = atol($2);
$$.str = cat3_str("[", $2, "]");
}
| '[' ']'
{
$$.ival = 0;
$$.str = "[]";
}
| /* empty */ {
$$.ival = 1;
$$.str = "";
}
/* /*
* the exec sql connect statement: connect to the given database * the exec sql connect statement: connect to the given database
*/ */
ECPGConnect : SQL_CONNECT db_name { $$ = $2; } ECPGConnect: SQL_CONNECT db_name { $$ = $2; }
db_name : database_name { $$ = $1; } db_name: database_name { $$ = $1; }
| ':' name { /* check if we have a char variable */ | cvariable { /* check if we have a char variable */
struct variable *p = find_variable($2); struct variable *p = find_variable($1);
enum ECPGttype typ = p->type->typ; enum ECPGttype typ = p->type->typ;
/* if array see what's inside */ /* if array see what's inside */
@ -3859,13 +3838,13 @@ db_name : database_name { $$ = $1; }
if (typ != ECPGt_char && typ != ECPGt_unsigned_char) if (typ != ECPGt_char && typ != ECPGt_unsigned_char)
yyerror("invalid datatype"); yyerror("invalid datatype");
$$ = $2; $$ = $1;
} }
/* /*
* execute a given string as sql command * execute a given string as sql command
*/ */
ECPGExecute : EXECUTE SQL_IMMEDIATE ':' name { $$ = $4; }; ECPGExecute : EXECUTE SQL_IMMEDIATE cvariable { $$ = $3; };
/* /*
* open is an open cursor, at the moment this has to be removed * open is an open cursor, at the moment this has to be removed
@ -3890,12 +3869,15 @@ ECPGOpen: SQL_OPEN name open_opts {
}; };
open_opts: /* empty */ { $$ = ""; } open_opts: /* empty */ { $$ = ""; }
| USING ':' name { | USING cvariable {
yyerror ("open cursor with variables not implemented yet"); yyerror ("open cursor with variables not implemented yet");
} }
/* /*
* whenever statement: decide what to do in case of error/no dat * whenever statement: decide what to do in case of error/no data found
* according to SQL standards we miss: SQLSTATE, CONSTRAINT, SQLEXCEPTION
* and SQLWARNING
*/ */
ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action { ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action {
when_error.code = $<action>3.code; when_error.code = $<action>3.code;
@ -3933,17 +3915,15 @@ action : SQL_CONTINUE {
$<action>$.command = $3; $<action>$.command = $3;
$<action>$.str = make2_str("goto ", $3); $<action>$.str = make2_str("goto ", $3);
} }
| DO name '(' { | DO name '(' dotext ')' {
do_str = (char *) mm_alloc(do_length = strlen($2) + 4);
sprintf(do_str, "%s (", $2);
} dotext ')' {
do_str[strlen(do_str)+1]='\0';
do_str[strlen(do_str)]=')';
$<action>$.code = W_DO; $<action>$.code = W_DO;
$<action>$.command = do_str; $<action>$.command = cat4_str($2, "(", $4, ")");
$<action>$.str = make2_str("do ", do_str); $<action>$.str = make2_str("do", $<action>$.command);
do_str = NULL; }
do_length = 0; | SQL_CALL name '(' dotext ')' {
$<action>$.code = W_DO;
$<action>$.command = cat4_str($2, "(", $4, ")");
$<action>$.str = make2_str("call", $<action>$.command);
} }
/* some other stuff for ecpg */ /* some other stuff for ecpg */
@ -4231,59 +4211,94 @@ into_list : coutputvariable | into_list ',' coutputvariable;
ecpgstart: SQL_START { reset_variables();} ecpgstart: SQL_START { reset_variables();}
dotext: /* empty */ dotext: /* empty */ { $$ = ""; }
| dotext sql_anything { | dotext sql_anything { $$ = cat2_str($1, $2); }
if (strlen(do_str) + yyleng + 1 >= do_length)
do_str = mm_realloc(do_str, do_length += yyleng);
strcat(do_str, yytext); vartext: var_anything { $$ = $1; }
| vartext var_anything { $$ = cat2_str($1, $2); }
coutputvariable : cvariable indicator {
add_variable(&argsresult, find_variable($1), ($2 == NULL) ? &no_indicator : find_variable($2));
} }
vartext: both_anything { fwrite(yytext, yyleng, 1, yyout); } cinputvariable : cvariable indicator {
| vartext both_anything { fwrite(yytext, yyleng, 1, yyout); } add_variable(&argsinsert, find_variable($1), ($2 == NULL) ? &no_indicator : find_variable($2));
coutputvariable : ':' name indicator {
add_variable(&argsresult, find_variable($2), ($3 == NULL) ? &no_indicator : find_variable($3));
} }
cinputvariable : ':' name indicator { civariableonly : cvariable name {
add_variable(&argsinsert, find_variable($2), ($3 == NULL) ? &no_indicator : find_variable($3)); add_variable(&argsinsert, find_variable($1), &no_indicator);
} }
civariableonly : ':' name { cvariable: CVARIABLE { $$ = $1; }
add_variable(&argsinsert, find_variable($2), &no_indicator); | CVARIABLE '.' identlist { $$ = $1; }
} | CVARIABLE '-' '>' identlist { $$ = $1; }
identlist: IDENT { $$ = $1; }
| IDENT '.' identlist { $$ = $1; }
| IDENT '-' '>' identlist { $$ = $1; }
indicator: /* empty */ { $$ = NULL; } indicator: /* empty */ { $$ = NULL; }
| ':' name { check_indicator((find_variable($2))->type); $$ = $2; } | cvariable { check_indicator((find_variable($1))->type); $$ = $1; }
| SQL_INDICATOR ':' name { check_indicator((find_variable($3))->type); $$ = $3; } | SQL_INDICATOR cvariable { check_indicator((find_variable($2))->type); $$ = $2; }
| SQL_INDICATOR name { check_indicator((find_variable($2))->type); $$ = $2; } | SQL_INDICATOR name { check_indicator((find_variable($2))->type); $$ = $2; }
ecpg_ident: IDENT { $$ = $1; }
| CSTRING { $$ = cat3_str("\"", $1, "\""); }
/* /*
* C stuff * C stuff
*/ */
symbol: IDENT { $$ = $1; } symbol: ecpg_ident { $$ = $1; }
c_anything: both_anything { fwrite(yytext, yyleng, 1, yyout); } c_anything: ecpg_ident { $$ = $1; }
| ';' { fputc(';', yyout); } | Iconst { $$ = $1; }
| FCONST { $$ = make_name(); }
| '*' { $$ = "*"; }
| ';' { $$ = ";"; }
| S_AUTO { $$ = "auto"; }
| S_BOOL { $$ = "bool"; }
| S_CHAR { $$ = "char"; }
| S_CONST { $$ = "const"; }
| S_DOUBLE { $$ = "double"; }
| S_EXTERN { $$ = "extern"; }
| S_FLOAT { $$ = "float"; }
| S_INT { $$ = "int"; }
| S_LONG { $$ = "long"; }
| S_REGISTER { $$ = "register"; }
| S_SHORT { $$ = "short"; }
| S_SIGNED { $$ = "signed"; }
| S_STATIC { $$ = "static"; }
| S_STRUCT { $$ = "struct"; }
| S_UNSIGNED { $$ = "unsigned"; }
| S_VARCHAR { $$ = "varchar"; }
| S_ANYTHING { $$ = make_name(); }
| '[' { $$ = "["; }
| ']' { $$ = "]"; }
| '(' { $$ = "("; }
| ')' { $$ = ")"; }
| '=' { $$ = "="; }
| ',' { $$ = ","; }
sql_anything: IDENT {} | ICONST {} | FCONST {} sql_anything: ecpg_ident { $$ = $1; }
| Iconst { $$ = $1; }
| FCONST { $$ = make_name(); }
| ',' { $$ = ","; }
both_anything: IDENT {} | ICONST {} | FCONST {} var_anything: ecpg_ident { $$ = $1; }
| S_AUTO | S_BOOL | S_CHAR | S_CONST | S_DOUBLE | S_EXTERN | S_FLOAT | Iconst { $$ = $1; }
| S_INT | S_LONG | S_REGISTER | S_SHORT | S_SIGNED | S_STATIC | FCONST { $$ = make_name(); }
| S_STRUCT | S_UNSIGNED | S_VARCHAR | S_ANYTHING /*FIXME: | ',' { $$ = ","; }*/
| '[' | ']' | '(' | ')' | '=' | '{' { $$ = "{"; }
| '}' { $$ = "}"; }
blockstart : '{' { blockstart : '{' {
braces_open++; braces_open++;
fputc('{', yyout); $$ = "{";
} }
blockend : '}' { blockend : '}' {
remove_variables(braces_open--); remove_variables(braces_open--);
fputc('}', yyout); $$ = "}";
} }
%% %%

View File

@ -130,6 +130,12 @@ ECPGdump_a_record(FILE *o, const char *name, const char *ind_name, long arrsiz,
void void
ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *ind_name, struct ECPGtype * ind_typ, const char *prefix, const char *ind_prefix) ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *ind_name, struct ECPGtype * ind_typ, const char *prefix, const char *ind_prefix)
{ {
if (ind_typ == NULL)
{
ind_typ = &ecpg_no_indicator;
ind_name = "no_indicator";
}
if (IS_SIMPLE_TYPE(typ->typ)) if (IS_SIMPLE_TYPE(typ->typ))
{ {
ECPGdump_a_simple(o, name, typ->typ, typ->size, 0, 0, prefix); ECPGdump_a_simple(o, name, typ->typ, typ->size, 0, 0, prefix);
@ -267,7 +273,7 @@ ECPGdump_a_record(FILE *o, const char *name, const char * ind_name, long arrsiz,
* then we are in a record in a record and the offset is used as * then we are in a record in a record and the offset is used as
* offset. * offset.
*/ */
struct ECPGrecord_member *p, *ind_p; struct ECPGrecord_member *p, *ind_p = NULL;
char obuf[BUFSIZ]; char obuf[BUFSIZ];
char pbuf[BUFSIZ], ind_pbuf[BUFSIZ]; char pbuf[BUFSIZ], ind_pbuf[BUFSIZ];
const char *offset; const char *offset;
@ -288,9 +294,11 @@ ECPGdump_a_record(FILE *o, const char *name, const char * ind_name, long arrsiz,
sprintf(ind_pbuf, "%s%s.", ind_prefix ? ind_prefix : "", ind_name); sprintf(ind_pbuf, "%s%s.", ind_prefix ? ind_prefix : "", ind_name);
ind_prefix = ind_pbuf; ind_prefix = ind_pbuf;
for (p = typ->u.members, ind_p = ind_typ->u.members; p; p = p->next, ind_p = ind_p->next) if (ind_typ != NULL) ind_p = ind_typ->u.members;
for (p = typ->u.members; p; p = p->next)
{ {
ECPGdump_a_type(o, p->name, p->typ, ind_p->name, ind_p->typ, prefix, ind_prefix); ECPGdump_a_type(o, p->name, p->typ, (ind_p != NULL) ? ind_p->name : NULL, (ind_p != NULL) ? ind_p->typ : NULL, prefix, ind_prefix);
if (ind_p != NULL) ind_p = ind_p->next;
} }
} }

View File

@ -74,3 +74,9 @@ struct when
char *command; char *command;
char *str; char *str;
}; };
struct index
{
int ival;
char *str;
};

View File

@ -119,5 +119,7 @@ exec sql end declare section;
exec sql drop table perftest1; exec sql drop table perftest1;
exec sql commit;
return (0); return (0);
} }

View File

@ -24,7 +24,7 @@ exec sql begin declare section;
} ind_birth; } ind_birth;
} ind_personal; } ind_personal;
long ind_married; long ind_married;
char married[9]="a"; char married[9];
exec sql end declare section; exec sql end declare section;
char msg[128], command[128]; char msg[128], command[128];
FILE *dbgs; FILE *dbgs;
@ -60,7 +60,7 @@ exec sql end declare section;
while (not_found == 0) { while (not_found == 0) {
strcpy(msg, "fetch"); strcpy(msg, "fetch");
exec sql fetch cur into :personal:ind_personal, :married:ind_married; exec sql fetch cur into :personal:ind_personal, :married:ind_married, :personal.birth.born;
if (not_found == 0) if (not_found == 0)
printf ("%8.8s was born %d (age = %d) %s%s\n", personal.name.arr, personal.birth.born, personal.birth.age, ind_married ? "" : "and married ", ind_married ? "" : married); printf ("%8.8s was born %d (age = %d) %s%s\n", personal.name.arr, personal.birth.born, personal.birth.age, ind_married ? "" : "and married ", ind_married ? "" : married);
} }