Commit 718430ea authored by Marc G. Fournier's avatar Marc G. Fournier

From: Michael Meskes <meskes@topsystem.de>

And the next update. Now you can use only parts of a struct like this:

exec sql select a into :struct.string from foo;
parent 3e3477f5
...@@ -142,3 +142,10 @@ Fri Apr 24 13:50:15 CEST 1998 ...@@ -142,3 +142,10 @@ Fri Apr 24 13:50:15 CEST 1998
- Fixed some bugs. - Fixed some bugs.
- Set version to 2.1.1 - Set version to 2.1.1
Mon Apr 27 14:26:55 CEST 1998
- Parser now able to understand and process syntax like :foo->bar
and :foo.bar as variables.
- Set version to 2.2.0
...@@ -53,6 +53,3 @@ exec sql disconnect {current|default|all|connectionname|connection_hostvar}; ...@@ -53,6 +53,3 @@ exec sql disconnect {current|default|all|connectionname|connection_hostvar};
commit release|commit work release auch disconnect commit release|commit work release auch disconnect
It is not neccessary to check for "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.
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* Complex types: * Complex types:
* VARCHAR, VARCHAR2 - Strings with length (maxlen is given in the declaration) * VARCHAR, VARCHAR2 - Strings with length (maxlen is given in the declaration)
* Arrays of simple types and of VARCHAR, VARCHAR2 (size given in declaration) * Arrays of simple types and of VARCHAR, VARCHAR2 (size given in declaration)
* Records build of simple types, arrays and other records. * Records build of simple types, arrays and other structs.
* *
* Complicating things: * Complicating things:
* typedefs and struct names! * typedefs and struct names!
...@@ -41,7 +41,7 @@ enum ECPGttype ...@@ -41,7 +41,7 @@ enum ECPGttype
ECPGt_float, ECPGt_double, ECPGt_float, ECPGt_double,
ECPGt_varchar, ECPGt_varchar2, ECPGt_varchar, ECPGt_varchar2,
ECPGt_array, ECPGt_array,
ECPGt_record, ECPGt_struct,
ECPGt_EOIT, /* End of insert types. */ ECPGt_EOIT, /* End of insert types. */
ECPGt_EORT, /* End of result types. */ ECPGt_EORT, /* End of result types. */
ECPGt_NO_INDICATOR /* no indicator */ ECPGt_NO_INDICATOR /* no indicator */
......
...@@ -2,8 +2,8 @@ SRCDIR= ../../.. ...@@ -2,8 +2,8 @@ SRCDIR= ../../..
include $(SRCDIR)/Makefile.global include $(SRCDIR)/Makefile.global
MAJOR_VERSION=2 MAJOR_VERSION=2
MINOR_VERSION=1 MINOR_VERSION=2
PATCHLEVEL=1 PATCHLEVEL=0
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) \
......
...@@ -306,6 +306,7 @@ sql [sS][qQ][lL] ...@@ -306,6 +306,7 @@ sql [sS][qQ][lL]
return (yytext[0]); return (yytext[0]);
} }
<SQL>{self} { return (yytext[0]); } <SQL>{self} { return (yytext[0]); }
<SQL>"->" { return S_STRUCTPOINTER; }
<SQL>{operator}/-[\.0-9] { <SQL>{operator}/-[\.0-9] {
yylval.str = strdup((char*)yytext); yylval.str = strdup((char*)yytext);
return (Op); return (Op);
......
...@@ -17,8 +17,8 @@ static int QueryIsRule = 0; ...@@ -17,8 +17,8 @@ static int QueryIsRule = 0;
static enum ECPGttype actual_type[128]; static enum ECPGttype actual_type[128];
static char *actual_storage[128]; static char *actual_storage[128];
/* temporarily store record members while creating the data structure */ /* temporarily store struct members while creating the data structure */
struct ECPGrecord_member *record_member_list[128] = { NULL }; struct ECPGstruct_member *struct_member_list[128] = { NULL };
/* keep a list of cursors */ /* keep a list of cursors */
struct cursor *cur = NULL; struct cursor *cur = NULL;
...@@ -89,10 +89,83 @@ int braces_open; ...@@ -89,10 +89,83 @@ int braces_open;
static struct variable * allvariables = NULL; static struct variable * allvariables = NULL;
static struct variable * static struct variable *
find_variable(char * name) new_variable(const char * name, struct ECPGtype * type)
{
struct variable * p = (struct variable*) mm_alloc(sizeof(struct variable));
p->name = strdup(name);
p->type = type;
p->brace_level = braces_open;
p->next = allvariables;
allvariables = p;
return(p);
}
static struct variable * find_variable(char * name);
static struct variable *
find_struct_member(char *name, char *str, struct ECPGstruct_member *members)
{
char *next = strpbrk(++str, ".-"), c = '\0';
if (next != NULL)
{
c = *next;
*next = '\0';
}
for (; members; members = members->next)
{
if (strcmp(members->name, str) == 0)
{
if (c == '\0')
{
/* found the end */
switch (members->typ->typ)
{
case ECPGt_struct:
return(new_variable(name, ECPGmake_struct_type(members->typ->u.members)));
case ECPGt_varchar:
return(new_variable(name, ECPGmake_varchar_type(members->typ->typ, members->typ->size)));
default:
return(new_variable(name, ECPGmake_simple_type(members->typ->typ, members->typ->size)));
}
}
else
{
*next = c;
if (c == '-') next++;
return(find_struct_member(name, next, members->typ->u.members));
}
}
}
return(NULL);
}
static struct variable *
find_struct(char * name, char *next)
{
struct variable * p;
char c = *next;
/* first get the mother structure entry */
*next = '\0';
p = find_variable(name);
/* restore the name, we will need it later on */
*next = c;
if (*next == '-') next++;
return (find_struct_member(name, next, p->type->u.members));
}
static struct variable *
find_simple(char * name)
{ {
struct variable * p; struct variable * p;
char * errorstring = (char *) mm_alloc(strlen(name) + 100);
for (p = allvariables; p; p = p->next) for (p = allvariables; p; p = p->next)
{ {
...@@ -100,25 +173,23 @@ find_variable(char * name) ...@@ -100,25 +173,23 @@ find_variable(char * name)
return p; return p;
} }
sprintf(errorstring, "The variable %s is not declared", name); return(NULL);
yyerror(errorstring);
free (errorstring);
return NULL;
} }
static struct variable *
static void find_variable(char * name)
new_variable(const char * name, struct ECPGtype * type)
{ {
struct variable * p = (struct variable*) mm_alloc(sizeof(struct variable)); char * next;
struct variable * p =
((next = strpbrk(name, ".-")) != NULL) ? find_struct(name, next) : find_simple(name);
p->name = strdup(name); if (p == NULL)
p->type = type; {
p->brace_level = braces_open; sprintf(errortext, "The variable %s is not declared", name);
yyerror(errortext);
}
p->next = allvariables; return(p);
allvariables = p;
} }
static void static void
...@@ -215,7 +286,7 @@ check_indicator(struct ECPGtype *var) ...@@ -215,7 +286,7 @@ check_indicator(struct ECPGtype *var)
/* make sure this is a valid indicator variable */ /* make sure this is a valid indicator variable */
switch (var->typ) switch (var->typ)
{ {
struct ECPGrecord_member *p; struct ECPGstruct_member *p;
case ECPGt_short: case ECPGt_short:
case ECPGt_int: case ECPGt_int:
...@@ -225,7 +296,7 @@ check_indicator(struct ECPGtype *var) ...@@ -225,7 +296,7 @@ check_indicator(struct ECPGtype *var)
case ECPGt_unsigned_long: case ECPGt_unsigned_long:
break; break;
case ECPGt_record: case ECPGt_struct:
for (p = var->u.members; p; p = p->next) for (p = var->u.members; p; p = p->next)
check_indicator(p->typ); check_indicator(p->typ);
break; break;
...@@ -392,8 +463,8 @@ output_statement(const char * stmt) ...@@ -392,8 +463,8 @@ output_statement(const char * stmt)
/* C token */ /* C token */
%token S_ANYTHING S_AUTO S_BOOL S_CHAR S_CONST S_DOUBLE S_EXTERN %token S_ANYTHING S_AUTO S_BOOL S_CHAR S_CONST S_DOUBLE S_EXTERN
%token S_FLOAT S_INT %token S_FLOAT S_INT
%token S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT S_UNSIGNED %token S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT
%token S_VARCHAR %token S_STRUCTPOINTER S_UNSIGNED S_VARCHAR
/* I need this and don't know where it is defined inside the backend */ /* I need this and don't know where it is defined inside the backend */
%token TYPECAST %token TYPECAST
...@@ -3704,7 +3775,7 @@ declaration: storage_clause type ...@@ -3704,7 +3775,7 @@ declaration: storage_clause type
{ {
actual_storage[struct_level] = $1; actual_storage[struct_level] = $1;
actual_type[struct_level] = $2; actual_type[struct_level] = $2;
if ($2 != ECPGt_varchar && $2 != ECPGt_record) if ($2 != ECPGt_varchar && $2 != ECPGt_struct)
fprintf(yyout, "%s %s", $1, ECPGtype_name($2)); fprintf(yyout, "%s %s", $1, ECPGtype_name($2));
} }
variable_list ';' { fputc(';', yyout); } variable_list ';' { fputc(';', yyout); }
...@@ -3723,11 +3794,13 @@ type: simple_type ...@@ -3723,11 +3794,13 @@ type: simple_type
struct_type: s_struct '{' variable_declarations '}' struct_type: s_struct '{' variable_declarations '}'
{ {
struct_level--; struct_level--;
$$ = actual_type[struct_level] = ECPGt_record; fputs("} ", yyout);
$$ = ECPGt_struct;
} }
s_struct : S_STRUCT symbol s_struct : S_STRUCT symbol
{ {
struct_member_list[struct_level] = NULL;
struct_level++; struct_level++;
fprintf(yyout, "struct %s {", $2); fprintf(yyout, "struct %s {", $2);
} }
...@@ -3764,14 +3837,13 @@ variable: opt_pointer symbol opt_index opt_initializer ...@@ -3764,14 +3837,13 @@ variable: opt_pointer symbol opt_index opt_initializer
switch (actual_type[struct_level]) switch (actual_type[struct_level])
{ {
case ECPGt_record: case ECPGt_struct:
if (struct_level == 0) if (struct_level == 0)
new_variable($2, ECPGmake_record_type(record_member_list[struct_level])); new_variable($2, ECPGmake_struct_type(struct_member_list[struct_level]));
else else
ECPGmake_record_member($2, ECPGmake_record_type(record_member_list[struct_level]), &(record_member_list[struct_level-1])); ECPGmake_struct_member($2, ECPGmake_struct_type(struct_member_list[struct_level]), &(struct_member_list[struct_level-1]));
record_member_list[struct_level] = NULL; fprintf(yyout, "%s%s%s%s", $1, $2, $3.str, $4);
fprintf(yyout, "} %s%s%s%s", $1, $2, $3.str, $4);
break; break;
case ECPGt_varchar: case ECPGt_varchar:
...@@ -3781,7 +3853,7 @@ variable: opt_pointer symbol opt_index opt_initializer ...@@ -3781,7 +3853,7 @@ variable: opt_pointer symbol opt_index opt_initializer
if (struct_level == 0) if (struct_level == 0)
new_variable($2, ECPGmake_varchar_type(actual_type[struct_level], length)); new_variable($2, ECPGmake_varchar_type(actual_type[struct_level], length));
else else
ECPGmake_record_member($2, ECPGmake_varchar_type(actual_type[struct_level], length), &(record_member_list[struct_level-1])); ECPGmake_struct_member($2, ECPGmake_varchar_type(actual_type[struct_level], length), &(struct_member_list[struct_level-1]));
if (length > 0) if (length > 0)
fprintf(yyout, "%s struct varchar_%s { int len; char arr[%d]; } %s", actual_storage[struct_level], $2, length, $2); fprintf(yyout, "%s struct varchar_%s { int len; char arr[%d]; } %s", actual_storage[struct_level], $2, length, $2);
...@@ -3794,7 +3866,7 @@ variable: opt_pointer symbol opt_index opt_initializer ...@@ -3794,7 +3866,7 @@ variable: opt_pointer symbol opt_index opt_initializer
if (struct_level == 0) if (struct_level == 0)
new_variable($2, ECPGmake_simple_type(actual_type[struct_level], length)); new_variable($2, ECPGmake_simple_type(actual_type[struct_level], length));
else else
ECPGmake_record_member($2, ECPGmake_simple_type(actual_type[struct_level], length), &(record_member_list[struct_level-1])); ECPGmake_struct_member($2, ECPGmake_simple_type(actual_type[struct_level], length), &(struct_member_list[struct_level-1]));
fprintf(yyout, "%s%s%s%s", $1, $2, $3.str, $4); fprintf(yyout, "%s%s%s%s", $1, $2, $3.str, $4);
...@@ -4230,15 +4302,15 @@ civariableonly : cvariable name { ...@@ -4230,15 +4302,15 @@ civariableonly : cvariable name {
} }
cvariable: CVARIABLE { $$ = $1; } cvariable: CVARIABLE { $$ = $1; }
| CVARIABLE '.' identlist { $$ = $1; } | CVARIABLE '.' identlist { $$ = cat3_str($1, ".", $3); }
| CVARIABLE '-' '>' identlist { $$ = $1; } | CVARIABLE S_STRUCTPOINTER identlist { $$ = cat3_str($1, "->", $3); }
identlist: IDENT { $$ = $1; } identlist: IDENT { $$ = $1; }
| IDENT '.' identlist { $$ = $1; } | IDENT '.' identlist { $$ = cat3_str($1, ".", $3); }
| IDENT '-' '>' identlist { $$ = $1; } | IDENT S_STRUCTPOINTER identlist { $$ = cat3_str($1, "->", $3); }
indicator: /* empty */ { $$ = NULL; } indicator: /* empty */ { $$ = NULL; }
| cvariable { check_indicator((find_variable($1))->type); $$ = $1; } | cvariable { printf("## %s\n", $1); check_indicator((find_variable($1))->type); $$ = $1; }
| SQL_INDICATOR cvariable { check_indicator((find_variable($2))->type); $$ = $2; } | 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; }
......
...@@ -40,12 +40,12 @@ mm_realloc(void *ptr, size_t size) ...@@ -40,12 +40,12 @@ mm_realloc(void *ptr, size_t size)
*/ */
/* The NAME argument is copied. The type argument is preserved as a pointer. */ /* The NAME argument is copied. The type argument is preserved as a pointer. */
struct ECPGrecord_member * struct ECPGstruct_member *
ECPGmake_record_member(char *name, struct ECPGtype * type, struct ECPGrecord_member ** start) ECPGmake_struct_member(char *name, struct ECPGtype * type, struct ECPGstruct_member ** start)
{ {
struct ECPGrecord_member *ptr, struct ECPGstruct_member *ptr,
*ne = *ne =
(struct ECPGrecord_member *) mm_alloc(sizeof(struct ECPGrecord_member)); (struct ECPGstruct_member *) mm_alloc(sizeof(struct ECPGstruct_member));
ne->name = strdup(name); ne->name = strdup(name);
ne->typ = type; ne->typ = type;
...@@ -94,9 +94,9 @@ ECPGmake_array_type(struct ECPGtype * typ, long siz) ...@@ -94,9 +94,9 @@ ECPGmake_array_type(struct ECPGtype * typ, long siz)
} }
struct ECPGtype * struct ECPGtype *
ECPGmake_record_type(struct ECPGrecord_member * rm) ECPGmake_struct_type(struct ECPGstruct_member * rm)
{ {
struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_record, 1); struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_struct, 1);
ne->u.members = rm; ne->u.members = rm;
...@@ -116,14 +116,14 @@ ECPGmake_record_type(struct ECPGrecord_member * rm) ...@@ -116,14 +116,14 @@ ECPGmake_record_type(struct ECPGrecord_member * rm)
reference-to-variable can be a reference to a struct element. reference-to-variable can be a reference to a struct element.
arrsize is the size of the array in case of array fetches. Otherwise 0. arrsize is the size of the array in case of array fetches. Otherwise 0.
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 structs).
*/ */
void void
ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
long varcharsize, long varcharsize,
long arrsiz, const char *siz, const char *prefix); long arrsiz, const char *siz, const char *prefix);
void void
ECPGdump_a_record(FILE *o, const char *name, const char *ind_name, long arrsiz, ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, long arrsiz,
struct ECPGtype * typ, struct ECPGtype * ind_typ, const char *offset, const char *prefix, const char * ind_prefix); struct ECPGtype * typ, struct ECPGtype * ind_typ, const char *offset, const char *prefix, const char * ind_prefix);
...@@ -154,19 +154,19 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in ...@@ -154,19 +154,19 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in
{ {
abort(); /* Array of array, */ abort(); /* Array of array, */
} }
else if (typ->u.element->typ == ECPGt_record) else if (typ->u.element->typ == ECPGt_struct)
{ {
/* Array of records. */ /* Array of structs. */
ECPGdump_a_record(o, name, ind_name, typ->size, typ->u.element, ind_typ->u.element, 0, prefix, ind_prefix); ECPGdump_a_struct(o, name, ind_name, typ->size, typ->u.element, ind_typ->u.element, 0, prefix, ind_prefix);
} }
else else
{ {
abort(); abort();
} }
} }
else if (typ->typ == ECPGt_record) else if (typ->typ == ECPGt_struct)
{ {
ECPGdump_a_record(o, name, ind_name, 0, typ, ind_typ, 0, prefix, ind_prefix); ECPGdump_a_struct(o, name, ind_name, 0, typ, ind_typ, 0, prefix, ind_prefix);
} }
else else
{ {
...@@ -176,7 +176,7 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in ...@@ -176,7 +176,7 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in
/* If siz is NULL, then the offset is 0, if not use siz as a /* 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. */ string, it represents the offset needed if we are in an array of structs. */
void void
ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
long varcharsize, long varcharsize,
...@@ -189,66 +189,66 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, ...@@ -189,66 +189,66 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
{ {
case ECPGt_char: case ECPGt_char:
if (varcharsize == 0) /* pointer */ if (varcharsize == 0) /* pointer */
fprintf(o, "\n\tECPGt_char,%s%s,%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz, fprintf(o, "\n\tECPGt_char,(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
siz == NULL ? "sizeof(char)" : siz); siz == NULL ? "sizeof(char)" : siz);
else else
fprintf(o, "\n\tECPGt_char,&%s%s,%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz, fprintf(o, "\n\tECPGt_char,&(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
siz == NULL ? "sizeof(char)" : siz); siz == NULL ? "sizeof(char)" : siz);
break; break;
case ECPGt_unsigned_char: case ECPGt_unsigned_char:
if (varcharsize == 0) /* pointer */ if (varcharsize == 0) /* pointer */
fprintf(o, "\n\tECPGt_unsigned_char,%s%s,%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz, fprintf(o, "\n\tECPGt_unsigned_char,(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
siz == NULL ? "sizeof(char)" : siz); siz == NULL ? "sizeof(char)" : siz);
else else
fprintf(o, "\n\tECPGt_unsigned_char,&%s%s,%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz, fprintf(o, "\n\tECPGt_unsigned_char,&(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz,
siz == NULL ? "sizeof(unsigned char)" : siz); siz == NULL ? "sizeof(unsigned char)" : siz);
break; break;
case ECPGt_short: case ECPGt_short:
fprintf(o, "\n\tECPGt_short,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, fprintf(o, "\n\tECPGt_short,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(short)" : siz); siz == NULL ? "sizeof(short)" : siz);
break; break;
case ECPGt_unsigned_short: case ECPGt_unsigned_short:
fprintf(o, fprintf(o,
"\n\tECPGt_unsigned_short,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, "\n\tECPGt_unsigned_short,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(unsigned short)" : siz); siz == NULL ? "sizeof(unsigned short)" : siz);
break; break;
case ECPGt_int: case ECPGt_int:
fprintf(o, "\n\tECPGt_int,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, fprintf(o, "\n\tECPGt_int,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(int)" : siz); siz == NULL ? "sizeof(int)" : siz);
break; break;
case ECPGt_unsigned_int: case ECPGt_unsigned_int:
fprintf(o, "\n\tECPGt_unsigned_int,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, fprintf(o, "\n\tECPGt_unsigned_int,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(unsigned int)" : siz); siz == NULL ? "sizeof(unsigned int)" : siz);
break; break;
case ECPGt_long: case ECPGt_long:
fprintf(o, "\n\tECPGt_long,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, fprintf(o, "\n\tECPGt_long,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(long)" : siz); siz == NULL ? "sizeof(long)" : siz);
break; break;
case ECPGt_unsigned_long: case ECPGt_unsigned_long:
fprintf(o, "\n\tECPGt_unsigned_int,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, fprintf(o, "\n\tECPGt_unsigned_int,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(unsigned int)" : siz); siz == NULL ? "sizeof(unsigned int)" : siz);
break; break;
case ECPGt_float: case ECPGt_float:
fprintf(o, "\n\tECPGt_float,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, fprintf(o, "\n\tECPGt_float,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(float)" : siz); siz == NULL ? "sizeof(float)" : siz);
break; break;
case ECPGt_double: case ECPGt_double:
fprintf(o, "\n\tECPGt_double,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, fprintf(o, "\n\tECPGt_double,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(double)" : siz); siz == NULL ? "sizeof(double)" : siz);
break; break;
case ECPGt_bool: case ECPGt_bool:
fprintf(o, "\n\tECPGt_bool,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, fprintf(o, "\n\tECPGt_bool,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz,
siz == NULL ? "sizeof(bool)" : siz); siz == NULL ? "sizeof(bool)" : siz);
break; break;
case ECPGt_varchar: case ECPGt_varchar:
case ECPGt_varchar2: case ECPGt_varchar2:
if (siz == NULL) if (siz == NULL)
fprintf(o, "\n\tECPGt_varchar,&%s%s,%ldL,%ldL,sizeof(struct varchar_%s), ", fprintf(o, "\n\tECPGt_varchar,&(%s%s),%ldL,%ldL,sizeof(struct varchar_%s), ",
prefix ? prefix : "", name, prefix ? prefix : "", name,
varcharsize, varcharsize,
arrsiz, name); arrsiz, name);
else else
fprintf(o, "\n\tECPGt_varchar,&%s%s,%ldL,%ldL,%s, ", fprintf(o, "\n\tECPGt_varchar,&(%s%s),%ldL,%ldL,%s, ",
prefix ? prefix : "", name, prefix ? prefix : "", name,
varcharsize, varcharsize,
arrsiz, siz); arrsiz, siz);
...@@ -263,17 +263,17 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, ...@@ -263,17 +263,17 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ,
} }
/* Penetrate a record and dump the contents. */ /* Penetrate a struct and dump the contents. */
void void
ECPGdump_a_record(FILE *o, const char *name, const char * ind_name, long arrsiz, struct ECPGtype * typ, struct ECPGtype * ind_typ, const char *offsetarg, const char *prefix, const char *ind_prefix) ECPGdump_a_struct(FILE *o, const char *name, const char * ind_name, long arrsiz, struct ECPGtype * typ, struct ECPGtype * ind_typ, const char *offsetarg, const char *prefix, const char *ind_prefix)
{ {
/* /*
* If offset is NULL, then this is the first recursive level. If not * 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 * then we are in a struct in a struct and the offset is used as
* offset. * offset.
*/ */
struct ECPGrecord_member *p, *ind_p = NULL; struct ECPGstruct_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;
...@@ -306,18 +306,19 @@ ECPGdump_a_record(FILE *o, const char *name, const char * ind_name, long arrsiz, ...@@ -306,18 +306,19 @@ ECPGdump_a_record(FILE *o, const char *name, const char * ind_name, long arrsiz,
/* Freeing is not really that important. Since we throw away the process /* Freeing is not really that important. Since we throw away the process
anyway. Lets implement that last! */ anyway. Lets implement that last! */
void /* won't work anymore because a list of members may appear in several locations */
ECPGfree_record_member(struct ECPGrecord_member * rm) /*void
ECPGfree_struct_member(struct ECPGstruct_member * rm)
{ {
while (rm) while (rm)
{ {
struct ECPGrecord_member *p = rm; struct ECPGstruct_member *p = rm;
rm = rm->next; rm = rm->next;
free(p->name); free(p->name);
free(p); free(p);
} }
} }*/
void void
ECPGfree_type(struct ECPGtype * typ) ECPGfree_type(struct ECPGtype * typ)
...@@ -330,15 +331,17 @@ ECPGfree_type(struct ECPGtype * typ) ...@@ -330,15 +331,17 @@ ECPGfree_type(struct ECPGtype * typ)
free(typ->u.element); free(typ->u.element);
else if (typ->u.element->typ == ECPGt_array) else if (typ->u.element->typ == ECPGt_array)
abort(); /* Array of array, */ abort(); /* Array of array, */
else if (typ->u.element->typ == ECPGt_record) else if (typ->u.element->typ == ECPGt_struct)
/* Array of records. */ /* Array of structs. */
ECPGfree_record_member(typ->u.members); free(typ->u.members);
/* ECPGfree_struct_member(typ->u.members);*/
else else
abort(); abort();
} }
else if (typ->typ == ECPGt_record) else if (typ->typ == ECPGt_struct)
{ {
ECPGfree_record_member(typ->u.members); free(typ->u.members);
/* ECPGfree_struct_member(typ->u.members);*/
} }
else else
{ {
......
#include <ecpgtype.h> #include <ecpgtype.h>
struct ECPGtype; struct ECPGtype;
struct ECPGrecord_member struct ECPGstruct_member
{ {
char *name; char *name;
struct ECPGtype *typ; struct ECPGtype *typ;
struct ECPGrecord_member *next; struct ECPGstruct_member *next;
}; };
struct ECPGtype struct ECPGtype
...@@ -19,20 +19,20 @@ struct ECPGtype ...@@ -19,20 +19,20 @@ struct ECPGtype
struct ECPGtype *element; /* For an array this is the type struct ECPGtype *element; /* For an array this is the type
* of the element */ * of the element */
struct ECPGrecord_member *members; struct ECPGstruct_member *members;
/* A pointer to a list 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 **); struct ECPGstruct_member *ECPGmake_struct_member(char *, struct ECPGtype *, struct ECPGstruct_member **);
struct ECPGtype *ECPGmake_simple_type(enum ECPGttype, long); struct ECPGtype *ECPGmake_simple_type(enum ECPGttype, long);
struct ECPGtype *ECPGmake_varchar_type(enum ECPGttype, long); struct ECPGtype *ECPGmake_varchar_type(enum ECPGttype, long);
struct ECPGtype *ECPGmake_array_type(struct ECPGtype *, long); struct ECPGtype *ECPGmake_array_type(struct ECPGtype *, long);
struct ECPGtype *ECPGmake_record_type(struct ECPGrecord_member *); struct ECPGtype *ECPGmake_struct_type(struct ECPGstruct_member *);
/* Frees a type. */ /* Frees a type. */
void ECPGfree_record_member(struct ECPGrecord_member *); void ECPGfree_struct_member(struct ECPGstruct_member *);
void ECPGfree_type(struct ECPGtype *); void ECPGfree_type(struct ECPGtype *);
/* Dump a type. /* Dump a type.
...@@ -43,7 +43,7 @@ void ECPGfree_type(struct ECPGtype *); ...@@ -43,7 +43,7 @@ void ECPGfree_type(struct ECPGtype *);
reference-to-variable can be a reference to a struct element. reference-to-variable can be a reference to a struct element.
arrsize is the size of the array in case of array fetches. Otherwise 0. arrsize is the size of the array in case of array fetches. Otherwise 0.
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 structs).
*/ */
void ECPGdump_a_type(FILE *, const char *, struct ECPGtype *, const char *, struct ECPGtype *, const char *, const char *); void ECPGdump_a_type(FILE *, const char *, struct ECPGtype *, const char *, struct ECPGtype *, const char *, const char *);
......
...@@ -60,7 +60,7 @@ exec sql end declare section; ...@@ -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, :personal.birth.born; exec sql fetch cur into :personal:ind_personal, :married:ind_married;
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);
} }
......
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