Commit 25ad1439 authored by Marc G. Fournier's avatar Marc G. Fournier

Major update of ecpg preprocessor

From: Michael Meskes <meskes@topsystem.de>
parent 30f737f6
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
# #
# #
# IDENTIFICATION # IDENTIFICATION
# $Header: /cvsroot/pgsql/src/interfaces/Makefile,v 1.6 1998/02/12 02:14:14 scrappy Exp $ # $Header: /cvsroot/pgsql/src/interfaces/Makefile,v 1.7 1998/02/17 01:47:19 scrappy Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
...@@ -16,7 +16,7 @@ include $(SRCDIR)/Makefile.global ...@@ -16,7 +16,7 @@ include $(SRCDIR)/Makefile.global
.DEFAULT all: .DEFAULT all:
$(MAKE) -C libpq $@ $(MAKE) -C libpq $@
# $(MAKE) -C ecpg $@ $(MAKE) -C ecpg $@
ifeq ($(HAVE_Cplusplus), true) ifeq ($(HAVE_Cplusplus), true)
$(MAKE) -C libpq++ $@ $(MAKE) -C libpq++ $@
else else
......
...@@ -9,3 +9,17 @@ Wed Feb 11 10:58:13 CET 1998 ...@@ -9,3 +9,17 @@ Wed Feb 11 10:58:13 CET 1998
Thu Feb 12 14:45:07 CET 1998 Thu Feb 12 14:45:07 CET 1998
- Changed parser to correctly handle local variables. - Changed parser to correctly handle local variables.
- Allow static and extern variable definitions.
- free() variable structure completely.
Fri Feb 13 12:35:58 CET 1998
- ecpg can use structs to store data, but only if the complete
definition of the struct lies inside the sql declare section
and only simple types used.
Fre Feb 13 14:12:41 CET 1998
- Structure now work completely.
...@@ -16,10 +16,6 @@ just -1 for them all. ...@@ -16,10 +16,6 @@ just -1 for them all.
Missing library functions to_date et al. Missing library functions to_date et al.
Possibility to define records or structs in the declare section in a way
that the record can be filled from one row in the database. This is a
simpler way to handle an entire row at a time.
Oracle has array operations that enhances speed. When implementing it in Oracle has array operations that enhances speed. When implementing it in
ecpg it is done for compatibility reasons only. For them to improve speed ecpg it is done for compatibility reasons only. For them to improve speed
would require a lot more insight in the postgres internal mechanisms than I would require a lot more insight in the postgres internal mechanisms than I
...@@ -44,5 +40,6 @@ could be realised in a script. ...@@ -44,5 +40,6 @@ could be realised in a script.
Now comes my list (MM): Now comes my list (MM):
Variable definitions containing static/volatile have to be possible. What do we do with enum data types?
'signed' isn't understood so far
...@@ -47,7 +47,7 @@ $(shlib): ecpglib.o typename.o ...@@ -47,7 +47,7 @@ $(shlib): ecpglib.o typename.o
clean: clean:
rm -f *.o *.a core a.out *~ $(shlib) libecpg.so rm -f *.o *.a core a.out *~ $(shlib) libecpg.so
install: libecpg.a install: libecpg.a $(shlib)
install -m 644 libecpg.a $(DESTDIR)$(LIBDIR) install -m 644 libecpg.a $(DESTDIR)$(LIBDIR)
install -m 644 $(shlib) $(DESTDIR)$(LIBDIR) install -m 644 $(shlib) $(DESTDIR)$(LIBDIR)
ln -sf $(shlib) $(DESTDIR)$(LIBDIR)/libecpg.so ln -sf $(shlib) $(DESTDIR)$(LIBDIR)/libecpg.so
......
...@@ -51,12 +51,7 @@ main(int argc, char *const argv[]) ...@@ -51,12 +51,7 @@ main(int argc, char *const argv[])
{ {
char *filename, *ptr2ext; char *filename, *ptr2ext;
filename = malloc(strlen(argv[fnr]) + 2); filename = mm_alloc(strlen(argv[fnr]) + 2);
if (filename == NULL)
{
perror("malloc");
continue;
}
strcpy(filename, argv[fnr]); strcpy(filename, argv[fnr]);
......
...@@ -11,3 +11,4 @@ extern FILE *yyin, *yyout; ...@@ -11,3 +11,4 @@ extern FILE *yyin, *yyout;
extern void lex_init(void); extern void lex_init(void);
extern char * input_filename; extern char * input_filename;
extern int yyparse(void); extern int yyparse(void);
extern void *mm_alloc(size_t);
...@@ -58,6 +58,14 @@ float { dbg(S_FLOAT); return S_FLOAT; } ...@@ -58,6 +58,14 @@ float { dbg(S_FLOAT); return S_FLOAT; }
double { dbg(S_DOUBLE); return S_DOUBLE; } double { dbg(S_DOUBLE); return S_DOUBLE; }
bool { dbg(S_BOOL); return S_BOOL; } bool { dbg(S_BOOL); return S_BOOL; }
static { dbg(S_STATIC); return S_STATIC; }
extern { dbg(S_EXTERN); return S_EXTERN; }
auto { dbg(S_AUTO); return S_AUTO; }
const { dbg(S_CONST); return S_CONST; }
register { dbg(S_REGISTER); return S_REGISTER; }
struct { dbg(S_STRUCT); return S_STRUCT; }
{string} { dbg(SQL_STRING); return SQL_STRING; } {string} { dbg(SQL_STRING); return SQL_STRING; }
<SQL>{ws} ; <SQL>{ws} ;
{symbol} { dbg(S_SYMBOL); return S_SYMBOL; } {symbol} { dbg(S_SYMBOL); return S_SYMBOL; }
......
...@@ -12,7 +12,11 @@ static void yyerror(char *); ...@@ -12,7 +12,11 @@ static void yyerror(char *);
/* /*
* Variables containing simple states. * Variables containing simple states.
*/ */
int debugging = 0; int debugging = 0;
static int struct_level = 0;
/* temporarily store record members while creating the data structure */
struct ECPGrecord_member *record_member_list[128] = { NULL };
/* /*
* Handle the filename and line numbering. * Handle the filename and line numbering.
...@@ -86,7 +90,7 @@ remove_variables(int brace_level) ...@@ -86,7 +90,7 @@ remove_variables(int brace_level)
{ {
struct variable * p, *prev; struct variable * p, *prev;
for (p = prev = allvariables; p; p = p->next) for (p = prev = allvariables; p; p = p ? p->next : NULL)
{ {
if (p->brace_level >= brace_level) if (p->brace_level >= brace_level)
{ {
...@@ -96,6 +100,8 @@ remove_variables(int brace_level) ...@@ -96,6 +100,8 @@ remove_variables(int brace_level)
else else
prev->next = p->next; prev->next = p->next;
ECPGfree_type(p->type);
free(p->name);
free(p); free(p);
p = prev; p = prev;
} }
...@@ -157,7 +163,7 @@ dump_variables(struct arguments * list) ...@@ -157,7 +163,7 @@ dump_variables(struct arguments * list)
dump_variables(list->next); dump_variables(list->next);
/* Then the current element. */ /* Then the current element. */
ECPGdump_a_type(yyout, list->variable->name, list->variable->type); ECPGdump_a_type(yyout, list->variable->name, list->variable->type, NULL);
/* Then release the list element. */ /* Then release the list element. */
free(list); free(list);
...@@ -179,12 +185,12 @@ dump_variables(struct arguments * list) ...@@ -179,12 +185,12 @@ dump_variables(struct arguments * list)
%token <tagname> S_SYMBOL S_LENGTH S_ANYTHING %token <tagname> S_SYMBOL S_LENGTH S_ANYTHING
%token <tagname> S_VARCHAR S_VARCHAR2 %token <tagname> S_VARCHAR S_VARCHAR2
%token <tagname> S_EXTERN S_STATIC %token <tagname> S_EXTERN S_STATIC S_AUTO S_CONST S_REGISTER S_STRUCT
%token <tagname> S_UNSIGNED S_SIGNED %token <tagname> S_UNSIGNED S_SIGNED
%token <tagname> S_LONG S_SHORT S_INT S_CHAR S_FLOAT S_DOUBLE S_BOOL %token <tagname> S_LONG S_SHORT S_INT S_CHAR S_FLOAT S_DOUBLE S_BOOL
%token <tagname> '[' ']' ';' ',' '{' '}' %token <tagname> '[' ']' ';' ',' '{' '}'
%type <type> type type_detailed varchar_type simple_type array_type %type <type> type type_detailed varchar_type simple_type array_type struct_type
%type <symbolname> symbol %type <symbolname> symbol
%type <tagname> maybe_storage_clause varchar_tag %type <tagname> maybe_storage_clause varchar_tag
%type <type_enum> simple_tag %type <type_enum> simple_tag
...@@ -227,8 +233,12 @@ variable_declarations : /* empty */ ...@@ -227,8 +233,12 @@ variable_declarations : /* empty */
/* Here is where we can enter support for typedef. */ /* Here is where we can enter support for typedef. */
variable_declaration : type ';' { variable_declaration : type ';' {
new_variable($<type>1.name, $<type>1.typ); /* don't worry about our list when we're working on a struct */
free($<type>1.name); if (struct_level == 0)
{
new_variable($<type>1.name, $<type>1.typ);
free($<type>1.name);
}
fprintf(yyout, ";"); fprintf(yyout, ";");
} }
...@@ -244,12 +254,18 @@ symbol : S_SYMBOL { ...@@ -244,12 +254,18 @@ symbol : S_SYMBOL {
type : maybe_storage_clause type_detailed { $<type>$ = $<type>2; }; type : maybe_storage_clause type_detailed { $<type>$ = $<type>2; };
type_detailed : varchar_type { $<type>$ = $<type>1; } type_detailed : varchar_type { $<type>$ = $<type>1; }
| simple_type { $<type>$ = $<type>1; } | simple_type { $<type>$ = $<type>1; }
| array_type {$<type>$ = $<type>1; }; | array_type {$<type>$ = $<type>1; }
| struct_type {$<type>$ = $<type>1; };
varchar_type : varchar_tag symbol index { varchar_type : varchar_tag symbol index {
fprintf(yyout, "struct varchar_%s { int len; char arr[%d]; } %s", $<symbolname>2, $<indexsize>3, $<symbolname>2); fprintf(yyout, "struct varchar_%s { int len; char arr[%d]; } %s", $<symbolname>2, $<indexsize>3, $<symbolname>2);
$<type>$.name = $<symbolname>2; if (struct_level == 0)
$<type>$.typ = ECPGmake_varchar_type(ECPGt_varchar, $<indexsize>3); {
$<type>$.name = $<symbolname>2;
$<type>$.typ = ECPGmake_varchar_type(ECPGt_varchar, $<indexsize>3);
}
else
ECPGmake_record_member($<symbolname>2, ECPGmake_varchar_type(ECPGt_varchar, $<indexsize>3), &(record_member_list[struct_level-1]));
} }
varchar_tag : S_VARCHAR { $<tagname>$ = $<tagname>1; } varchar_tag : S_VARCHAR { $<tagname>$ = $<tagname>1; }
...@@ -257,14 +273,42 @@ varchar_tag : S_VARCHAR { $<tagname>$ = $<tagname>1; } ...@@ -257,14 +273,42 @@ varchar_tag : S_VARCHAR { $<tagname>$ = $<tagname>1; }
simple_type : simple_tag symbol { simple_type : simple_tag symbol {
fprintf(yyout, "%s %s", ECPGtype_name($<type_enum>1), $<symbolname>2); fprintf(yyout, "%s %s", ECPGtype_name($<type_enum>1), $<symbolname>2);
$<type>$.name = $<symbolname>2; if (struct_level == 0)
$<type>$.typ = ECPGmake_simple_type($<type_enum>1); {
$<type>$.name = $<symbolname>2;
$<type>$.typ = ECPGmake_simple_type($<type_enum>1);
}
else
ECPGmake_record_member($<symbolname>2, ECPGmake_simple_type($<type_enum>1), &(record_member_list[struct_level-1]));
} }
array_type : simple_tag symbol index { array_type : simple_tag symbol index {
fprintf(yyout, "%s %s [%d]", ECPGtype_name($<type_enum>1), $<symbolname>2, $<indexsize>3); fprintf(yyout, "%s %s [%d]", ECPGtype_name($<type_enum>1), $<symbolname>2, $<indexsize>3);
$<type>$.name = $<symbolname>2; if (struct_level == 0)
$<type>$.typ = ECPGmake_array_type(ECPGmake_simple_type($<type_enum>1), $<indexsize>3); {
$<type>$.name = $<symbolname>2;
$<type>$.typ = ECPGmake_array_type(ECPGmake_simple_type($<type_enum>1), $<indexsize>3);
}
else
ECPGmake_record_member($<symbolname>2, ECPGmake_array_type(ECPGmake_simple_type($<type_enum>1), $<indexsize>3), &(record_member_list[struct_level-1]));
}
s_struct : S_STRUCT symbol {
struct_level++;
fprintf(yyout, "struct %s {", $<symbolname>2);
}
struct_type : s_struct '{' variable_declarations '}' symbol {
struct_level--;
if (struct_level == 0)
{
$<type>$.name = $<symbolname>5;
$<type>$.typ = ECPGmake_record_type(record_member_list[struct_level]);
}
else
ECPGmake_record_member($<symbolname>5, ECPGmake_record_type(record_member_list[struct_level]), &(record_member_list[struct_level-1]));
fprintf(yyout, "} %s", $<symbolname>5);
record_member_list[struct_level] = NULL;
} }
simple_tag : S_CHAR { $<type_enum>$ = ECPGt_char; } simple_tag : S_CHAR { $<type_enum>$ = ECPGt_char; }
...@@ -281,6 +325,9 @@ simple_tag : S_CHAR { $<type_enum>$ = ECPGt_char; } ...@@ -281,6 +325,9 @@ simple_tag : S_CHAR { $<type_enum>$ = ECPGt_char; }
maybe_storage_clause : S_EXTERN { fwrite(yytext, yyleng, 1, yyout); } maybe_storage_clause : S_EXTERN { fwrite(yytext, yyleng, 1, yyout); }
| S_STATIC { fwrite(yytext, yyleng, 1, yyout); } | S_STATIC { fwrite(yytext, yyleng, 1, yyout); }
| S_CONST { fwrite(yytext, yyleng, 1, yyout); }
| S_REGISTER { fwrite(yytext, yyleng, 1, yyout); }
| S_AUTO { fwrite(yytext, yyleng, 1, yyout); }
| /* empty */ { }; | /* empty */ { };
index : '[' length ']' { index : '[' length ']' {
...@@ -369,13 +416,14 @@ canything : both_anything ...@@ -369,13 +416,14 @@ canything : both_anything
sqlanything : both_anything; sqlanything : both_anything;
both_anything : S_LENGTH | S_VARCHAR | S_VARCHAR2 both_anything : S_LENGTH | S_VARCHAR | S_VARCHAR2
| S_LONG | S_SHORT | S_INT | S_CHAR | S_FLOAT | S_DOUBLE | S_LONG | S_SHORT | S_INT | S_CHAR | S_FLOAT | S_DOUBLE | S_BOOL
| SQL_OPEN | SQL_CONNECT | SQL_OPEN | SQL_CONNECT
| SQL_STRING | SQL_STRING
| SQL_BEGIN | SQL_END | SQL_BEGIN | SQL_END
| SQL_DECLARE | SQL_SECTION | SQL_DECLARE | SQL_SECTION
| SQL_INCLUDE | SQL_INCLUDE
| S_SYMBOL | S_SYMBOL
| S_STATIC | S_EXTERN | S_AUTO | S_CONST | S_REGISTER | S_STRUCT
| '[' | ']' | ',' | '[' | ']' | ','
| S_ANYTHING; | S_ANYTHING;
......
This diff is collapsed.
...@@ -4,7 +4,9 @@ struct ECPGtype; ...@@ -4,7 +4,9 @@ struct ECPGtype;
struct ECPGrecord_member { struct ECPGrecord_member {
char * name; char * name;
struct ECPGtype * typ; struct ECPGtype * typ;
struct ECPGrecord_member * next;
}; };
struct ECPGtype { struct ECPGtype {
enum ECPGttype typ; enum ECPGttype typ;
unsigned short size; /* For array it is the number of elements. unsigned short size; /* For array it is the number of elements.
...@@ -14,17 +16,17 @@ struct ECPGtype { ...@@ -14,17 +16,17 @@ struct ECPGtype {
struct ECPGtype * element; /* For an array this is the type of the struct ECPGtype * element; /* For an array this is the type of the
* element */ * element */
struct ECPGrecord_member ** members; struct ECPGrecord_member * members;
/* A pointer to an array of members. */ /* A pointer to a list of members. */
} u; } u;
}; };
/* Everything is malloced. */ /* Everything is malloced. */
struct ECPGrecord_member * ECPGmake_record_member(char *, struct ECPGtype *); struct ECPGrecord_member * ECPGmake_record_member(char *, struct ECPGtype *, struct ECPGrecord_member **);
struct ECPGtype * ECPGmake_simple_type(enum ECPGttype); struct ECPGtype * ECPGmake_simple_type(enum ECPGttype);
struct ECPGtype * ECPGmake_varchar_type(enum ECPGttype, unsigned short); struct ECPGtype * ECPGmake_varchar_type(enum ECPGttype, unsigned short);
struct ECPGtype * ECPGmake_array_type(struct ECPGtype *, unsigned short); struct ECPGtype * ECPGmake_array_type(struct ECPGtype *, unsigned short);
struct ECPGtype * ECPGmake_record_type(struct ECPGrecord_member *[]); struct ECPGtype * ECPGmake_record_type(struct ECPGrecord_member *);
/* Frees a type. */ /* Frees a type. */
void ECPGfree_record_member(struct ECPGrecord_member *); void ECPGfree_record_member(struct ECPGrecord_member *);
...@@ -40,7 +42,7 @@ void ECPGfree_type(struct ECPGtype *); ...@@ -40,7 +42,7 @@ void ECPGfree_type(struct ECPGtype *);
size is the maxsize in case it is a varchar. Otherwise it is the size of size is the maxsize in case it is a varchar. Otherwise it is the size of
the variable (required to do array fetches of records). the variable (required to do array fetches of records).
*/ */
void ECPGdump_a_type(FILE *, const char * name, struct ECPGtype *); void ECPGdump_a_type(FILE *, const char * name, struct ECPGtype *, const char *);
/* A simple struct to keep a variable and its type. */ /* A simple struct to keep a variable and its type. */
struct ECPGtemp_type { struct ECPGtemp_type {
......
create table meskes(name char8, born int4); create table meskes(name char8, born int4, age int2);
insert into meskes(name, born) values ('Petra', 19661202); insert into meskes(name, born) values ('Petra', 19661202, 31);
insert into meskes(name, born) values ('Michael', 19660117); insert into meskes(name, born) values ('Michael', 19660117, 32);
insert into meskes(name, born) values ('Carsten', 19910103); insert into meskes(name, born) values ('Carsten', 19910103, 7);
insert into meskes(name, born) values ('Marc', 19930907); insert into meskes(name, born) values ('Marc', 19930907, 4);
insert into meskes(name, born) values ('Chris', 19970923); insert into meskes(name, born) values ('Chris', 19970923, 0);
...@@ -18,8 +18,11 @@ int ...@@ -18,8 +18,11 @@ int
main () main ()
{ {
exec sql begin declare section; exec sql begin declare section;
varchar name[8]; struct personal_struct { varchar name[8];
long born; struct birth_struct { long born;
short age;
} birth;
} personal;
exec sql end declare section; exec sql end declare section;
FILE *dbgs; FILE *dbgs;
...@@ -31,7 +34,7 @@ exec sql end declare section; ...@@ -31,7 +34,7 @@ exec sql end declare section;
db_error ("connect"); db_error ("connect");
exec sql declare cur cursor for exec sql declare cur cursor for
select name, born from meskes; select name, born, age from meskes;
if (SQLCODE) db_error ("declare"); if (SQLCODE) db_error ("declare");
exec sql open cur; exec sql open cur;
...@@ -39,10 +42,10 @@ exec sql end declare section; ...@@ -39,10 +42,10 @@ exec sql end declare section;
db_error ("open"); db_error ("open");
while (1) { while (1) {
exec sql fetch in cur into :name, :born; exec sql fetch in cur into :personal;
if (SQLCODE) if (SQLCODE)
break; break;
printf ("%8.8s was born %d\n", name.arr, born); printf ("%8.8s was born %d (age = %d)\n", personal.name.arr, personal.birth.born, personal.birth.age);
} }
if (SQLCODE < 0) if (SQLCODE < 0)
......
...@@ -43,9 +43,6 @@ foo.bar. ...@@ -43,9 +43,6 @@ foo.bar.
.BR "file1, file2, ..." .BR "file1, file2, ..."
The files to be processed. The files to be processed.
.SH "BUGS" .SH "BUGS"
This version of ecpg is not able to handle structures inside the sql declare
blocks.
.TP
The return code is alway -1 in case of an error. You cannot see which error The return code is alway -1 in case of an error. You cannot see which error
occured by examining the return code. occured by examining the return code.
.SH "RETURN VALUE" .SH "RETURN VALUE"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment