aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/ecpg/preproc/preproc.y
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/ecpg/preproc/preproc.y')
-rw-r--r--src/interfaces/ecpg/preproc/preproc.y144
1 files changed, 108 insertions, 36 deletions
diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y
index 41537eaddab..021988cf52b 100644
--- a/src/interfaces/ecpg/preproc/preproc.y
+++ b/src/interfaces/ecpg/preproc/preproc.y
@@ -17,8 +17,8 @@ static int QueryIsRule = 0;
static enum ECPGttype actual_type[128];
static char *actual_storage[128];
-/* temporarily store record members while creating the data structure */
-struct ECPGrecord_member *record_member_list[128] = { NULL };
+/* temporarily store struct members while creating the data structure */
+struct ECPGstruct_member *struct_member_list[128] = { NULL };
/* keep a list of cursors */
struct cursor *cur = NULL;
@@ -89,10 +89,83 @@ int braces_open;
static struct variable * allvariables = NULL;
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;
- char * errorstring = (char *) mm_alloc(strlen(name) + 100);
for (p = allvariables; p; p = p->next)
{
@@ -100,25 +173,23 @@ find_variable(char * name)
return p;
}
- sprintf(errorstring, "The variable %s is not declared", name);
- yyerror(errorstring);
- free (errorstring);
-
- return NULL;
+ return(NULL);
}
-
-static void
-new_variable(const char * name, struct ECPGtype * type)
+static struct variable *
+find_variable(char * name)
{
- 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);
- p->type = type;
- p->brace_level = braces_open;
+ if (p == NULL)
+ {
+ sprintf(errortext, "The variable %s is not declared", name);
+ yyerror(errortext);
+ }
- p->next = allvariables;
- allvariables = p;
+ return(p);
}
static void
@@ -215,7 +286,7 @@ check_indicator(struct ECPGtype *var)
/* make sure this is a valid indicator variable */
switch (var->typ)
{
- struct ECPGrecord_member *p;
+ struct ECPGstruct_member *p;
case ECPGt_short:
case ECPGt_int:
@@ -225,7 +296,7 @@ check_indicator(struct ECPGtype *var)
case ECPGt_unsigned_long:
break;
- case ECPGt_record:
+ case ECPGt_struct:
for (p = var->u.members; p; p = p->next)
check_indicator(p->typ);
break;
@@ -392,8 +463,8 @@ output_statement(const char * stmt)
/* C token */
%token S_ANYTHING S_AUTO S_BOOL S_CHAR S_CONST S_DOUBLE S_EXTERN
%token S_FLOAT S_INT
-%token S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT S_UNSIGNED
-%token S_VARCHAR
+%token S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT
+%token S_STRUCTPOINTER S_UNSIGNED S_VARCHAR
/* I need this and don't know where it is defined inside the backend */
%token TYPECAST
@@ -3704,7 +3775,7 @@ declaration: storage_clause type
{
actual_storage[struct_level] = $1;
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));
}
variable_list ';' { fputc(';', yyout); }
@@ -3723,11 +3794,13 @@ type: simple_type
struct_type: s_struct '{' variable_declarations '}'
{
struct_level--;
- $$ = actual_type[struct_level] = ECPGt_record;
+ fputs("} ", yyout);
+ $$ = ECPGt_struct;
}
s_struct : S_STRUCT symbol
{
+ struct_member_list[struct_level] = NULL;
struct_level++;
fprintf(yyout, "struct %s {", $2);
}
@@ -3764,14 +3837,13 @@ variable: opt_pointer symbol opt_index opt_initializer
switch (actual_type[struct_level])
{
- case ECPGt_record:
+ case ECPGt_struct:
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
- 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;
case ECPGt_varchar:
@@ -3781,7 +3853,7 @@ variable: opt_pointer symbol opt_index opt_initializer
if (struct_level == 0)
new_variable($2, ECPGmake_varchar_type(actual_type[struct_level], length));
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)
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
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]));
+ 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);
@@ -4230,15 +4302,15 @@ civariableonly : cvariable name {
}
cvariable: CVARIABLE { $$ = $1; }
- | CVARIABLE '.' identlist { $$ = $1; }
- | CVARIABLE '-' '>' identlist { $$ = $1; }
+ | CVARIABLE '.' identlist { $$ = cat3_str($1, ".", $3); }
+ | CVARIABLE S_STRUCTPOINTER identlist { $$ = cat3_str($1, "->", $3); }
identlist: IDENT { $$ = $1; }
- | IDENT '.' identlist { $$ = $1; }
- | IDENT '-' '>' identlist { $$ = $1; }
+ | IDENT '.' identlist { $$ = cat3_str($1, ".", $3); }
+ | IDENT S_STRUCTPOINTER identlist { $$ = cat3_str($1, "->", $3); }
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 name { check_indicator((find_variable($2))->type); $$ = $2; }