Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
25ad1439
Commit
25ad1439
authored
Feb 17, 1998
by
Marc G. Fournier
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Major update of ecpg preprocessor
From: Michael Meskes <meskes@topsystem.de>
parent
30f737f6
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
379 additions
and
254 deletions
+379
-254
src/interfaces/Makefile
src/interfaces/Makefile
+2
-2
src/interfaces/ecpg/ChangeLog
src/interfaces/ecpg/ChangeLog
+14
-0
src/interfaces/ecpg/TODO
src/interfaces/ecpg/TODO
+2
-5
src/interfaces/ecpg/lib/Makefile.in
src/interfaces/ecpg/lib/Makefile.in
+1
-1
src/interfaces/ecpg/preproc/ecpg.c
src/interfaces/ecpg/preproc/ecpg.c
+1
-6
src/interfaces/ecpg/preproc/extern.h
src/interfaces/ecpg/preproc/extern.h
+1
-0
src/interfaces/ecpg/preproc/pgc.l
src/interfaces/ecpg/preproc/pgc.l
+8
-0
src/interfaces/ecpg/preproc/preproc.y
src/interfaces/ecpg/preproc/preproc.y
+63
-15
src/interfaces/ecpg/preproc/type.c
src/interfaces/ecpg/preproc/type.c
+266
-206
src/interfaces/ecpg/preproc/type.h
src/interfaces/ecpg/preproc/type.h
+7
-5
src/interfaces/ecpg/test/mm.sql
src/interfaces/ecpg/test/mm.sql
+6
-6
src/interfaces/ecpg/test/test2.pgc
src/interfaces/ecpg/test/test2.pgc
+8
-5
src/man/ecpg.1
src/man/ecpg.1
+0
-3
No files found.
src/interfaces/Makefile
View file @
25ad1439
...
...
@@ -7,7 +7,7 @@
#
#
# 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
.DEFAULT all
:
$(MAKE)
-C
libpq
$@
#
$(MAKE) -C ecpg $@
$(MAKE)
-C
ecpg
$@
ifeq
($(HAVE_Cplusplus), true)
$(MAKE)
-C
libpq++
$@
else
...
...
src/interfaces/ecpg/ChangeLog
View file @
25ad1439
...
...
@@ -9,3 +9,17 @@ Wed Feb 11 10:58:13 CET 1998
Thu Feb 12 14:45:07 CET 1998
- 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.
src/interfaces/ecpg/TODO
View file @
25ad1439
...
...
@@ -16,10 +16,6 @@ just -1 for them all.
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
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
...
...
@@ -44,5 +40,6 @@ could be realised in a script.
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
src/interfaces/ecpg/lib/Makefile.in
View file @
25ad1439
...
...
@@ -47,7 +47,7 @@ $(shlib): ecpglib.o typename.o
clean
:
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
$(shlib)
$(DESTDIR)$(LIBDIR)
ln
-sf
$(shlib)
$(DESTDIR)$(LIBDIR)
/libecpg.so
...
...
src/interfaces/ecpg/preproc/ecpg.c
View file @
25ad1439
...
...
@@ -51,12 +51,7 @@ main(int argc, char *const argv[])
{
char
*
filename
,
*
ptr2ext
;
filename
=
malloc
(
strlen
(
argv
[
fnr
])
+
2
);
if
(
filename
==
NULL
)
{
perror
(
"malloc"
);
continue
;
}
filename
=
mm_alloc
(
strlen
(
argv
[
fnr
])
+
2
);
strcpy
(
filename
,
argv
[
fnr
]);
...
...
src/interfaces/ecpg/preproc/extern.h
View file @
25ad1439
...
...
@@ -11,3 +11,4 @@ extern FILE *yyin, *yyout;
extern
void
lex_init
(
void
);
extern
char
*
input_filename
;
extern
int
yyparse
(
void
);
extern
void
*
mm_alloc
(
size_t
);
src/interfaces/ecpg/preproc/pgc.l
View file @
25ad1439
...
...
@@ -58,6 +58,14 @@ float { dbg(S_FLOAT); return S_FLOAT; }
double { dbg(S_DOUBLE); return S_DOUBLE; }
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; }
<SQL>{ws} ;
{symbol} { dbg(S_SYMBOL); return S_SYMBOL; }
...
...
src/interfaces/ecpg/preproc/preproc.y
View file @
25ad1439
...
...
@@ -13,6 +13,10 @@ static void yyerror(char *);
* Variables containing simple states.
*/
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.
...
...
@@ -86,7 +90,7 @@ remove_variables(int brace_level)
{
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)
{
...
...
@@ -96,6 +100,8 @@ remove_variables(int brace_level)
else
prev->next = p->next;
ECPGfree_type(p->type);
free(p->name);
free(p);
p = prev;
}
...
...
@@ -157,7 +163,7 @@ dump_variables(struct arguments * list)
dump_variables(list->next);
/* 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. */
free(list);
...
...
@@ -179,12 +185,12 @@ dump_variables(struct arguments * list)
%token <tagname> S_SYMBOL S_LENGTH S_ANYTHING
%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_LONG S_SHORT S_INT S_CHAR S_FLOAT S_DOUBLE S_BOOL
%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 <tagname> maybe_storage_clause varchar_tag
%type <type_enum> simple_tag
...
...
@@ -227,8 +233,12 @@ variable_declarations : /* empty */
/* Here is where we can enter support for typedef. */
variable_declaration : type ';' {
/* 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);
free($<type>1.name);
}
fprintf(yyout, ";");
}
...
...
@@ -244,12 +254,18 @@ symbol : S_SYMBOL {
type : maybe_storage_clause type_detailed { $<type>$ = $<type>2; };
type_detailed : varchar_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 {
fprintf(yyout, "struct varchar_%s { int len; char arr[%d]; } %s", $<symbolname>2, $<indexsize>3, $<symbolname>2);
if (struct_level == 0)
{
$<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; }
...
...
@@ -257,14 +273,42 @@ varchar_tag : S_VARCHAR { $<tagname>$ = $<tagname>1; }
simple_type : simple_tag symbol {
fprintf(yyout, "%s %s", ECPGtype_name($<type_enum>1), $<symbolname>2);
if (struct_level == 0)
{
$<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 {
fprintf(yyout, "%s %s [%d]", ECPGtype_name($<type_enum>1), $<symbolname>2, $<indexsize>3);
if (struct_level == 0)
{
$<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; }
...
...
@@ -281,6 +325,9 @@ simple_tag : S_CHAR { $<type_enum>$ = ECPGt_char; }
maybe_storage_clause : S_EXTERN { 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 */ { };
index : '[' length ']' {
...
...
@@ -369,13 +416,14 @@ canything : both_anything
sqlanything : both_anything;
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_STRING
| SQL_BEGIN | SQL_END
| SQL_DECLARE | SQL_SECTION
| SQL_INCLUDE
| S_SYMBOL
| S_STATIC | S_EXTERN | S_AUTO | S_CONST | S_REGISTER | S_STRUCT
| '[' | ']' | ','
| S_ANYTHING;
...
...
src/interfaces/ecpg/preproc/type.c
View file @
25ad1439
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "type.h"
/* malloc + error check */
void
*
mm_alloc
(
size_t
size
)
{
void
*
ptr
=
malloc
(
size
);
if
(
ptr
==
NULL
)
{
fprintf
(
stderr
,
"Out of memory
\n
"
);
exit
(
1
);
}
return
(
ptr
);
}
/* Constructors
Yes, I mostly write c++-code
*/
/* The NAME argument is copied. The type argument is preserved as a pointer. */
struct
ECPGrecord_member
*
ECPGmake_record_member
(
char
*
name
,
struct
ECPGtype
*
type
)
ECPGmake_record_member
(
char
*
name
,
struct
ECPGtype
*
type
,
struct
ECPGrecord_member
**
start
)
{
struct
ECPGrecord_member
*
ne
=
(
struct
ECPGrecord_member
*
)
m
alloc
(
sizeof
(
struct
ECPGrecord_member
));
struct
ECPGrecord_member
*
ptr
,
*
ne
=
(
struct
ECPGrecord_member
*
)
mm_
alloc
(
sizeof
(
struct
ECPGrecord_member
));
ne
->
name
=
strdup
(
name
);
ne
->
typ
=
type
;
ne
->
next
=
NULL
;
for
(
ptr
=
*
start
;
ptr
&&
ptr
->
next
;
ptr
=
ptr
->
next
);
if
(
ptr
)
ptr
->
next
=
ne
;
else
*
start
=
ne
;
return
ne
;
}
struct
ECPGtype
*
ECPGmake_simple_type
(
enum
ECPGttype
typ
)
{
struct
ECPGtype
*
ne
=
(
struct
ECPGtype
*
)
m
alloc
(
sizeof
(
struct
ECPGtype
));
struct
ECPGtype
*
ne
=
(
struct
ECPGtype
*
)
mm_
alloc
(
sizeof
(
struct
ECPGtype
));
ne
->
typ
=
typ
;
ne
->
size
=
0
;
...
...
@@ -35,7 +57,7 @@ ECPGmake_simple_type(enum ECPGttype typ)
struct
ECPGtype
*
ECPGmake_varchar_type
(
enum
ECPGttype
typ
,
unsigned
short
siz
)
{
struct
ECPGtype
*
ne
=
ECPGmake_simple_type
(
typ
);
struct
ECPGtype
*
ne
=
ECPGmake_simple_type
(
typ
);
ne
->
size
=
siz
;
...
...
@@ -43,9 +65,9 @@ ECPGmake_varchar_type(enum ECPGttype typ, unsigned short siz)
}
struct
ECPGtype
*
ECPGmake_array_type
(
struct
ECPGtype
*
typ
,
unsigned
short
siz
)
ECPGmake_array_type
(
struct
ECPGtype
*
typ
,
unsigned
short
siz
)
{
struct
ECPGtype
*
ne
=
ECPGmake_simple_type
(
ECPGt_array
);
struct
ECPGtype
*
ne
=
ECPGmake_simple_type
(
ECPGt_array
);
ne
->
size
=
siz
;
ne
->
u
.
element
=
typ
;
...
...
@@ -54,9 +76,9 @@ ECPGmake_array_type(struct ECPGtype * typ, unsigned short siz)
}
struct
ECPGtype
*
ECPGmake_record_type
(
struct
ECPGrecord_member
*
rm
[]
)
ECPGmake_record_type
(
struct
ECPGrecord_member
*
rm
)
{
struct
ECPGtype
*
ne
=
ECPGmake_simple_type
(
ECPGt_record
);
struct
ECPGtype
*
ne
=
ECPGmake_simple_type
(
ECPGt_record
);
ne
->
u
.
members
=
rm
;
...
...
@@ -78,25 +100,25 @@ ECPGmake_record_type(struct ECPGrecord_member * rm[])
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).
*/
void
ECPGdump_a_simple
(
FILE
*
o
,
const
char
*
name
,
enum
ECPGttype
typ
,
void
ECPGdump_a_simple
(
FILE
*
o
,
const
char
*
name
,
enum
ECPGttype
typ
,
short
varcharsize
,
unsigned
short
arrsiz
,
const
char
*
siz
);
void
ECPGdump_a_record
(
FILE
*
o
,
const
char
*
name
,
unsigned
short
arrsiz
,
struct
ECPGtype
*
typ
,
const
char
*
offset
);
unsigned
short
arrsiz
,
const
char
*
siz
,
const
char
*
prefix
);
void
ECPGdump_a_record
(
FILE
*
o
,
const
char
*
name
,
unsigned
short
arrsiz
,
struct
ECPGtype
*
typ
,
const
char
*
offset
,
const
char
*
prefix
);
void
ECPGdump_a_type
(
FILE
*
o
,
const
char
*
name
,
struct
ECPGtype
*
typ
)
ECPGdump_a_type
(
FILE
*
o
,
const
char
*
name
,
struct
ECPGtype
*
typ
,
const
char
*
prefix
)
{
if
(
IS_SIMPLE_TYPE
(
typ
->
typ
))
{
ECPGdump_a_simple
(
o
,
name
,
typ
->
typ
,
typ
->
size
,
0
,
0
);
ECPGdump_a_simple
(
o
,
name
,
typ
->
typ
,
typ
->
size
,
0
,
0
,
prefix
);
}
else
if
(
typ
->
typ
==
ECPGt_array
)
{
if
(
IS_SIMPLE_TYPE
(
typ
->
u
.
element
->
typ
))
ECPGdump_a_simple
(
o
,
name
,
typ
->
u
.
element
->
typ
,
typ
->
u
.
element
->
size
,
typ
->
size
,
0
);
typ
->
u
.
element
->
size
,
typ
->
size
,
0
,
prefix
);
else
if
(
typ
->
u
.
element
->
typ
==
ECPGt_array
)
{
abort
();
/* Array of array, */
...
...
@@ -104,7 +126,7 @@ ECPGdump_a_type(FILE * o, const char * name, struct ECPGtype * typ)
else
if
(
typ
->
u
.
element
->
typ
==
ECPGt_record
)
{
/* Array of records. */
ECPGdump_a_record
(
o
,
name
,
typ
->
size
,
typ
->
u
.
element
,
0
);
ECPGdump_a_record
(
o
,
name
,
typ
->
size
,
typ
->
u
.
element
,
0
,
prefix
);
}
else
{
...
...
@@ -113,7 +135,7 @@ ECPGdump_a_type(FILE * o, const char * name, struct ECPGtype * typ)
}
else
if
(
typ
->
typ
==
ECPGt_record
)
{
ECPGdump_a_record
(
o
,
name
,
0
,
typ
,
0
);
ECPGdump_a_record
(
o
,
name
,
0
,
typ
,
0
,
prefix
);
}
else
{
...
...
@@ -125,68 +147,69 @@ ECPGdump_a_type(FILE * o, const char * name, struct ECPGtype * typ)
/* If siz is NULL, then the offset is 0, if not use siz as a
string, it represents the offset needed if we are in an array of records. */
void
ECPGdump_a_simple
(
FILE
*
o
,
const
char
*
name
,
enum
ECPGttype
typ
,
ECPGdump_a_simple
(
FILE
*
o
,
const
char
*
name
,
enum
ECPGttype
typ
,
short
varcharsize
,
unsigned
short
arrsiz
,
const
char
*
siz
)
const
char
*
siz
,
const
char
*
prefix
)
{
switch
(
typ
)
{
case
ECPGt_char
:
fprintf
(
o
,
"
\n\t
ECPGt_char,&%s,0,%d,%s, "
,
name
,
arrsiz
,
fprintf
(
o
,
"
\n\t
ECPGt_char,&%s%s,0,%d,%s, "
,
prefix
?
prefix
:
""
,
name
,
arrsiz
,
siz
==
NULL
?
"sizeof(char)"
:
siz
);
break
;
case
ECPGt_unsigned_char
:
fprintf
(
o
,
"
\n\t
ECPGt_unsigned_char,&%s,0,%d,%s,
"
,
name
,
arrsiz
,
fprintf
(
o
,
"
\n\t
ECPGt_unsigned_char,&%s%s,0,%d,%s, "
,
prefix
?
prefix
:
"
"
,
name
,
arrsiz
,
siz
==
NULL
?
"sizeof(unsigned char)"
:
siz
);
break
;
case
ECPGt_short
:
fprintf
(
o
,
"
\n\t
ECPGt_short,&%s,0,%d,%s,
"
,
name
,
arrsiz
,
fprintf
(
o
,
"
\n\t
ECPGt_short,&%s%s,0,%d,%s, "
,
prefix
?
prefix
:
"
"
,
name
,
arrsiz
,
siz
==
NULL
?
"sizeof(short)"
:
siz
);
break
;
case
ECPGt_unsigned_short
:
fprintf
(
o
,
"
\n\t
ECPGt_unsigned_short,&%s,0,%d,%s,
"
,
name
,
arrsiz
,
"
\n\t
ECPGt_unsigned_short,&%s%s,0,%d,%s, "
,
prefix
?
prefix
:
"
"
,
name
,
arrsiz
,
siz
==
NULL
?
"sizeof(unsigned short)"
:
siz
);
break
;
case
ECPGt_int
:
fprintf
(
o
,
"
\n\t
ECPGt_int,&%s,0,%d,%s,
"
,
name
,
arrsiz
,
fprintf
(
o
,
"
\n\t
ECPGt_int,&%s%s,0,%d,%s, "
,
prefix
?
prefix
:
"
"
,
name
,
arrsiz
,
siz
==
NULL
?
"sizeof(int)"
:
siz
);
break
;
case
ECPGt_unsigned_int
:
fprintf
(
o
,
"
\n\t
ECPGt_unsigned_int,&%s,0,%d,%s,
"
,
name
,
arrsiz
,
fprintf
(
o
,
"
\n\t
ECPGt_unsigned_int,&%s%s,0,%d,%s, "
,
prefix
?
prefix
:
"
"
,
name
,
arrsiz
,
siz
==
NULL
?
"sizeof(unsigned int)"
:
siz
);
break
;
case
ECPGt_long
:
fprintf
(
o
,
"
\n\t
ECPGt_long,&%s,0,%d,%s,
"
,
name
,
arrsiz
,
fprintf
(
o
,
"
\n\t
ECPGt_long,&%s%s,0,%d,%s, "
,
prefix
?
prefix
:
"
"
,
name
,
arrsiz
,
siz
==
NULL
?
"sizeof(long)"
:
siz
);
break
;
case
ECPGt_unsigned_long
:
fprintf
(
o
,
"
\n\t
ECPGt_unsigned_int,&%s,0,%d,%s,
"
,
name
,
arrsiz
,
fprintf
(
o
,
"
\n\t
ECPGt_unsigned_int,&%s%s,0,%d,%s, "
,
prefix
?
prefix
:
"
"
,
name
,
arrsiz
,
siz
==
NULL
?
"sizeof(unsigned int)"
:
siz
);
break
;
case
ECPGt_float
:
fprintf
(
o
,
"
\n\t
ECPGt_float,&%s,0,%d,%s,
"
,
name
,
arrsiz
,
fprintf
(
o
,
"
\n\t
ECPGt_float,&%s%s,0,%d,%s, "
,
prefix
?
prefix
:
"
"
,
name
,
arrsiz
,
siz
==
NULL
?
"sizeof(float)"
:
siz
);
break
;
case
ECPGt_double
:
fprintf
(
o
,
"
\n\t
ECPGt_double,&%s,0,%d,%s,
"
,
name
,
arrsiz
,
fprintf
(
o
,
"
\n\t
ECPGt_double,&%s%s,0,%d,%s, "
,
prefix
?
prefix
:
"
"
,
name
,
arrsiz
,
siz
==
NULL
?
"sizeof(double)"
:
siz
);
break
;
case
ECPGt_bool
:
fprintf
(
o
,
"
\n\t
ECPGt_bool,&%s,0,%d,%s,
"
,
name
,
arrsiz
,
fprintf
(
o
,
"
\n\t
ECPGt_bool,&%s%s,0,%d,%s, "
,
prefix
?
prefix
:
"
"
,
name
,
arrsiz
,
siz
==
NULL
?
"sizeof(bool)"
:
siz
);
break
;
case
ECPGt_varchar
:
case
ECPGt_varchar2
:
if
(
siz
==
NULL
)
fprintf
(
o
,
"
\n\t
ECPGt_varchar,&%s,%d,%d,sizeof(struct varchar_%s), "
,
name
,
fprintf
(
o
,
"
\n\t
ECPGt_varchar,&%s%s,%d,%d,sizeof(struct varchar_%s), "
,
prefix
?
prefix
:
""
,
name
,
varcharsize
,
arrsiz
,
name
);
else
fprintf
(
o
,
"
\n\t
ECPGt_varchar,&%s,%d,%d,%s, "
,
name
,
fprintf
(
o
,
"
\n\t
ECPGt_varchar,&%s%s,%d,%d,%s, "
,
prefix
?
prefix
:
""
,
name
,
varcharsize
,
arrsiz
,
siz
);
break
;
...
...
@@ -198,17 +221,15 @@ ECPGdump_a_simple(FILE * o, const char * name, enum ECPGttype typ,
/* Penetrate a record and dump the contents. */
void
ECPGdump_a_record
(
FILE
*
o
,
const
char
*
name
,
unsigned
short
arrsiz
,
struct
ECPGtype
*
typ
,
const
char
*
offsetarg
)
ECPGdump_a_record
(
FILE
*
o
,
const
char
*
name
,
unsigned
short
arrsiz
,
struct
ECPGtype
*
typ
,
const
char
*
offsetarg
,
const
char
*
prefix
)
{
/* If offset is NULL, then this is the first recursive level. If not then
we are in a record in a record and the offset is used as offset.
*/
struct
ECPGrecord_member
**
p
;
struct
ECPGrecord_member
*
p
;
char
obuf
[
BUFSIZ
];
char
buf
[
BUFSIZ
];
const
char
*
offset
;
char
p
buf
[
BUFSIZ
];
const
char
*
offset
;
if
(
offsetarg
==
NULL
)
{
...
...
@@ -220,32 +241,37 @@ ECPGdump_a_record(FILE * o,
offset
=
offsetarg
;
}
for
(
p
=
typ
->
u
.
members
;
*
p
;
p
++
)
sprintf
(
pbuf
,
"%s%s."
,
prefix
?
prefix
:
""
,
name
);
prefix
=
pbuf
;
for
(
p
=
typ
->
u
.
members
;
p
;
p
=
p
->
next
)
{
if
(
IS_SIMPLE_TYPE
((
*
p
)
->
typ
->
typ
))
#if 0
if (IS_SIMPLE_TYPE(p->typ->typ))
{
sprintf
(
buf
,
"%s.%s"
,
name
,
(
*
p
)
->
name
);
ECPGdump_a_simple
(
o
,
buf
,
(
*
p
)
->
typ
->
typ
,
(
*
p
)
->
typ
->
size
,
sprintf(buf, "%s.%s", name, p
->name);
ECPGdump_a_simple(o, buf, p->typ->typ, p
->typ->size,
arrsiz, offset);
}
else
if
((
*
p
)
->
typ
->
typ
==
ECPGt_array
)
else if (p
->typ->typ == ECPGt_array)
{
int i;
for
(
i
=
0
;
i
<
(
*
p
)
->
typ
->
size
;
i
++
)
for (i = 0; i < p
->typ->size; i++)
{
if
(
IS_SIMPLE_TYPE
((
*
p
)
->
typ
->
u
.
element
->
typ
))
if (IS_SIMPLE_TYPE(p
->typ->u.element->typ))
{
sprintf
(
buf
,
"%s.%s[%d]"
,
name
,
(
*
p
)
->
name
,
i
);
ECPGdump_a_simple
(
o
,
buf
,
(
*
p
)
->
typ
->
typ
,
(
*
p
)
->
typ
->
size
,
arrsiz
,
offset
);
/* sprintf(buf, "%s.%s[%d]", name, p->name, i); */
sprintf(buf, "%s.%s", name, p->name);
ECPGdump_a_simple(o, buf, p->typ->u.element->typ, p->typ->u.element->size,
p->typ->u.element->size, offset);
}
else
if
((
*
p
)
->
typ
->
u
.
element
->
typ
==
ECPGt_array
)
else if (p
->typ->u.element->typ == ECPGt_array)
{
/* Array within an array. NOT implemented yet
. */
/* Array within an array. NOT implemented
. */
abort();
}
else
if
((
*
p
)
->
typ
->
u
.
element
->
typ
==
ECPGt_record
)
else if (p
->typ->u.element->typ == ECPGt_record)
{
/* Record within array within record. NOT implemented yet. */
abort();
...
...
@@ -257,17 +283,19 @@ ECPGdump_a_record(FILE * o,
}
}
}
else
if
((
*
p
)
->
typ
->
typ
==
ECPGt_record
)
else if (p
->typ->typ == ECPGt_record)
{
/* Record within a record */
sprintf
(
buf
,
"%s.%s"
,
name
,
(
*
p
)
->
name
);
ECPGdump_a_record
(
o
,
buf
,
arrsiz
,
(
*
p
)
->
typ
,
offset
);
sprintf(buf, "%s.%s", name, p
->name);
ECPGdump_a_record(o, buf, arrsiz, p
->typ, offset);
}
else
{
/* Unknown type */
abort();
}
#endif
ECPGdump_a_type
(
o
,
p
->
name
,
p
->
typ
,
prefix
);
}
}
...
...
@@ -276,11 +304,43 @@ ECPGdump_a_record(FILE * o,
anyway. Lets implement that last! */
void
ECPGfree_record_member
(
struct
ECPGrecord_member
*
rm
)
ECPGfree_record_member
(
struct
ECPGrecord_member
*
rm
)
{
while
(
rm
)
{
struct
ECPGrecord_member
*
p
=
rm
;
rm
=
rm
->
next
;
free
(
p
->
name
);
free
(
p
);
}
}
void
ECPGfree_type
(
struct
ECPGtype
*
typ
)
ECPGfree_type
(
struct
ECPGtype
*
typ
)
{
if
(
!
IS_SIMPLE_TYPE
(
typ
->
typ
))
{
if
(
typ
->
typ
==
ECPGt_array
)
{
if
(
IS_SIMPLE_TYPE
(
typ
->
u
.
element
->
typ
))
free
(
typ
->
u
.
element
);
else
if
(
typ
->
u
.
element
->
typ
==
ECPGt_array
)
abort
();
/* Array of array, */
else
if
(
typ
->
u
.
element
->
typ
==
ECPGt_record
)
/* Array of records. */
ECPGfree_record_member
(
typ
->
u
.
members
);
else
abort
();
}
else
if
(
typ
->
typ
==
ECPGt_record
)
{
ECPGfree_record_member
(
typ
->
u
.
members
);
}
else
{
abort
();
}
}
free
(
typ
);
}
src/interfaces/ecpg/preproc/type.h
View file @
25ad1439
...
...
@@ -4,7 +4,9 @@ struct ECPGtype;
struct
ECPGrecord_member
{
char
*
name
;
struct
ECPGtype
*
typ
;
struct
ECPGrecord_member
*
next
;
};
struct
ECPGtype
{
enum
ECPGttype
typ
;
unsigned
short
size
;
/* For array it is the number of elements.
...
...
@@ -14,17 +16,17 @@ struct ECPGtype {
struct
ECPGtype
*
element
;
/* For an array this is the type of the
* element */
struct
ECPGrecord_member
*
*
members
;
/* A pointer to a
n array
of members. */
struct
ECPGrecord_member
*
members
;
/* A pointer to a
list
of members. */
}
u
;
};
/* 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_varchar_type
(
enum
ECPGttype
,
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. */
void
ECPGfree_record_member
(
struct
ECPGrecord_member
*
);
...
...
@@ -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
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. */
struct
ECPGtemp_type
{
...
...
src/interfaces/ecpg/test/mm.sql
View file @
25ad1439
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
(
'Michael'
,
19660117
);
insert
into
meskes
(
name
,
born
)
values
(
'Carsten'
,
19910103
);
insert
into
meskes
(
name
,
born
)
values
(
'Marc'
,
19930907
);
insert
into
meskes
(
name
,
born
)
values
(
'Chris'
,
19970923
);
insert
into
meskes
(
name
,
born
)
values
(
'Petra'
,
19661202
,
31
);
insert
into
meskes
(
name
,
born
)
values
(
'Michael'
,
19660117
,
32
);
insert
into
meskes
(
name
,
born
)
values
(
'Carsten'
,
19910103
,
7
);
insert
into
meskes
(
name
,
born
)
values
(
'Marc'
,
19930907
,
4
);
insert
into
meskes
(
name
,
born
)
values
(
'Chris'
,
19970923
,
0
);
src/interfaces/ecpg/test/test2.pgc
View file @
25ad1439
...
...
@@ -18,8 +18,11 @@ int
main ()
{
exec sql begin declare section;
varchar name[8];
long born;
struct personal_struct { varchar name[8];
struct birth_struct { long born;
short age;
} birth;
} personal;
exec sql end declare section;
FILE *dbgs;
...
...
@@ -31,7 +34,7 @@ exec sql end declare section;
db_error ("connect");
exec sql declare cur cursor for
select name, born from meskes;
select name, born
, age
from meskes;
if (SQLCODE) db_error ("declare");
exec sql open cur;
...
...
@@ -39,10 +42,10 @@ exec sql end declare section;
db_error ("open");
while (1) {
exec sql fetch in cur into :
name, :born
;
exec sql fetch in cur into :
personal
;
if (SQLCODE)
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)
...
...
src/man/ecpg.1
View file @
25ad1439
...
...
@@ -43,9 +43,6 @@ foo.bar.
.BR "file1, file2, ..."
The files to be processed.
.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
occured by examining the return code.
.SH "RETURN VALUE"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment