Commit bbe99022 authored by Michael Meskes's avatar Michael Meskes

Parse forward definiton of structs.

parent 9e2a980f
...@@ -1449,6 +1449,10 @@ Tue May 27 13:29:28 CEST 2003 ...@@ -1449,6 +1449,10 @@ Tue May 27 13:29:28 CEST 2003
Tue May 27 16:33:36 CEST 2003 Tue May 27 16:33:36 CEST 2003
- Accept stdin/stdout as input/output file. - Accept stdin/stdout as input/output file.
Thu May 29 13:58:25 CEST 2003
- ecpg should now be able to parse forward struct definition.
- Set ecpg version to 2.12.0. - Set ecpg version to 2.12.0.
- Set ecpg library to 3.4.2. - Set ecpg library to 3.4.2.
- Set pgtypes library to 1.0.0 - Set pgtypes library to 1.0.0
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.111 2003/05/27 14:36:00 meskes Exp $ * $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.112 2003/05/29 12:00:21 meskes Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -184,6 +184,7 @@ letter_or_digit [\200-\377_A-Za-z0-9] ...@@ -184,6 +184,7 @@ letter_or_digit [\200-\377_A-Za-z0-9]
identifier {letter}{letter_or_digit}* identifier {letter}{letter_or_digit}*
array ({letter_or_digit}|[\+\-\*\%\/\(\)])*
typecast "::" typecast "::"
/* /*
...@@ -949,96 +950,7 @@ cppline {space}*#(.*\\{space})+.* ...@@ -949,96 +950,7 @@ cppline {space}*#(.*\\{space})+.*
<incl>\<[^\>]+\>{space}*";"? { parse_include(); } <incl>\<[^\>]+\>{space}*";"? { parse_include(); }
<incl>{dquote}{xdinside}{dquote}{space}*";"? { parse_include(); } <incl>{dquote}{xdinside}{dquote}{space}*";"? { parse_include(); }
<incl>[^;\<\>\"]+";" { <incl>[^;\<\>\"]+";" { parse_include(); }
parse_include();
#if 0
/* got the include file name */
struct _yy_buffer *yb;
struct _include_path *ip;
char inc_file[MAXPGPATH];
unsigned int i;
yb = mm_alloc(sizeof(struct _yy_buffer));
yb->buffer = YY_CURRENT_BUFFER;
yb->lineno = yylineno;
yb->filename = input_filename;
yb->next = yy_buffer;
yy_buffer = yb;
/*
* skip the ";" and trailing whitespace. Note that yytext contains
* at least one non-space character plus the ";"
*/
for ( i = strlen(yytext)-2;
i > 0 && isspace((unsigned char) yytext[i]);
i-- )
{}
yytext[i+1] = '\0';
yyin = NULL;
/* If file name is enclosed in '"' remove these and look only in '.' */
/* Informix does look into all include paths though, except filename starts with '/' */
if ((yytext[0] == '"' && yytext[i] == '"') && (compat != ECPG_COMPAT_INFORMIX || yytext[0] == '/'))
{
yytext[i] = '\0';
memmove(yytext, yytext+1, strlen(yytext));
strncpy(inc_file, yytext, sizeof(inc_file));
yyin = fopen(inc_file, "r");
if (!yyin)
{
if (strcmp(inc_file + strlen(inc_file) - 2, ".h"))
{
strcat(inc_file, ".h");
yyin = fopen(inc_file, "r");
}
}
}
else
{
if (yytext[0] == '"' && yytext[i] == '"')
{
yytext[i] = '\0';
memmove(yytext, yytext+1, strlen(yytext));
}
for (ip = include_paths; yyin == NULL && ip != NULL; ip = ip->next)
{
if (strlen(ip->path) + strlen(yytext) + 3 > MAXPGPATH)
{
fprintf(stderr, "Error: Path %s/%s is too long in line %d, skipping.\n", ip->path, yytext, yylineno);
continue;
}
snprintf (inc_file, sizeof(inc_file), "%s/%s", ip->path, yytext);
yyin = fopen(inc_file, "r");
if (!yyin)
{
if (strcmp(inc_file + strlen(inc_file) - 2, ".h"))
{
strcat(inc_file, ".h");
yyin = fopen( inc_file, "r" );
}
}
}
}
if (!yyin)
{
snprintf(errortext, sizeof(errortext), "Cannot open include file %s in line %d\n", yytext, yylineno);
mmerror(NO_INCLUDE_FILE, ET_FATAL, errortext);
}
input_filename = mm_strdup(inc_file);
yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE ));
yylineno = 1;
output_line_number();
BEGIN C;
#endif
}
<<EOF>> { <<EOF>> {
if (yy_buffer == NULL) { if (yy_buffer == NULL) {
......
/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Attic/preproc.y,v 1.223 2003/05/27 11:31:52 meskes Exp $ */ /* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Attic/preproc.y,v 1.224 2003/05/29 12:00:21 meskes Exp $ */
/* Copyright comment */ /* Copyright comment */
%{ %{
...@@ -27,6 +27,9 @@ struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH] = { NULL }; ...@@ -27,6 +27,9 @@ struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH] = { NULL };
/* also store struct type so we can do a sizeof() later */ /* also store struct type so we can do a sizeof() later */
static char *ECPGstruct_sizeof = NULL; static char *ECPGstruct_sizeof = NULL;
/* for forward declarations we have to store some data as well */
static char *forward_name = NULL;
struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, 0L, NULL, {NULL}}; struct ECPGtype ecpg_no_indicator = {ECPGt_NO_INDICATOR, 0L, NULL, {NULL}};
struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL}; struct variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL};
...@@ -196,6 +199,7 @@ create_questionmarks(char *name, bool array) ...@@ -196,6 +199,7 @@ create_questionmarks(char *name, bool array)
enum ECPGttype type_enum; enum ECPGttype type_enum;
enum ECPGdtype dtype_enum; enum ECPGdtype dtype_enum;
struct fetch_desc descriptor; struct fetch_desc descriptor;
struct su_symbol struct_union;
} }
/* special embedded SQL token */ /* special embedded SQL token */
...@@ -440,7 +444,9 @@ create_questionmarks(char *name, bool array) ...@@ -440,7 +444,9 @@ create_questionmarks(char *name, bool array)
%type <str> reserved_keyword unreserved_keyword ecpg_interval %type <str> reserved_keyword unreserved_keyword ecpg_interval
%type <str> col_name_keyword func_name_keyword precision opt_scale %type <str> col_name_keyword func_name_keyword precision opt_scale
%type <str> ECPGTypeName variablelist ECPGColLabelCommon c_variable %type <str> ECPGTypeName variablelist ECPGColLabelCommon c_variable
%type <str> s_struct_union_symbol inf_val_list inf_col_list %type <str> inf_val_list inf_col_list
%type <struct_union> s_struct_union_symbol
%type <descriptor> ECPGGetDescriptor %type <descriptor> ECPGGetDescriptor
...@@ -4039,7 +4045,6 @@ connection_target: database_name opt_server opt_port ...@@ -4039,7 +4045,6 @@ connection_target: database_name opt_server opt_port
} }
| StringConst | StringConst
{ {
printf("MM: %s\n", $1);
if ($1[0] == '\"') if ($1[0] == '\"')
$$ = $1; $$ = $1;
else if (strcmp($1, " ?") == 0) /* variable */ else if (strcmp($1, " ?") == 0) /* variable */
...@@ -4425,16 +4430,34 @@ single_vt_type: common_type ...@@ -4425,16 +4430,34 @@ single_vt_type: common_type
| s_struct_union_symbol | s_struct_union_symbol
{ {
/* this is for named structs/unions */ /* this is for named structs/unions */
char *name = $1; char *name;
struct typedefs *this = get_typedef(name); struct typedefs *this;
bool forward = (strcmp($1.symbol, forward_name) == 0 && strcmp($1.su, "struct") == 0);
$$.type_str = mm_strdup(this->name);
$$.type_enum = this->type->type_enum; name = cat2_str($1.su, $1.symbol);
$$.type_dimension = this->type->type_dimension; /* Do we have a forward definition? */
$$.type_index = this->type->type_index; if (!forward)
$$.type_sizeof = this->type->type_sizeof; {
struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list); /* No */
free(name);
this = get_typedef(name);
$$.type_str = mm_strdup(this->name);
$$.type_enum = this->type->type_enum;
$$.type_dimension = this->type->type_dimension;
$$.type_index = this->type->type_index;
$$.type_sizeof = this->type->type_sizeof;
struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
free(name);
}
else
{
$$.type_str = name;
$$.type_enum = ECPGt_long;
$$.type_dimension = make_str("-1");
$$.type_index = make_str("-1");
$$.type_sizeof = make_str("");
struct_member_list[struct_level] = NULL;
}
} }
; ;
...@@ -4761,15 +4784,34 @@ var_type: common_type ...@@ -4761,15 +4784,34 @@ var_type: common_type
| s_struct_union_symbol | s_struct_union_symbol
{ {
/* this is for named structs/unions */ /* this is for named structs/unions */
char *name = $1; char *name;
struct typedefs *this = get_typedef(name); struct typedefs *this;
$$.type_str = mm_strdup(this->name); bool forward = (strcmp($1.symbol, forward_name) == 0 && strcmp($1.su, "struct") == 0);
$$.type_enum = this->type->type_enum;
$$.type_dimension = this->type->type_dimension; name = cat2_str($1.su, $1.symbol);
$$.type_index = this->type->type_index; /* Do we have a forward definition? */
$$.type_sizeof = this->type->type_sizeof; if (!forward)
struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list); {
free(name); /* No */
this = get_typedef(name);
$$.type_str = mm_strdup(this->name);
$$.type_enum = this->type->type_enum;
$$.type_dimension = this->type->type_dimension;
$$.type_index = this->type->type_index;
$$.type_sizeof = this->type->type_sizeof;
struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list);
free(name);
}
else
{
$$.type_str = name;
$$.type_enum = ECPGt_long;
$$.type_dimension = make_str("-1");
$$.type_index = make_str("-1");
$$.type_sizeof = make_str("");
struct_member_list[struct_level] = NULL;
}
} }
; ;
...@@ -4789,18 +4831,21 @@ struct_union_type_with_symbol: s_struct_union_symbol ...@@ -4789,18 +4831,21 @@ struct_union_type_with_symbol: s_struct_union_symbol
struct_member_list[struct_level++] = NULL; struct_member_list[struct_level++] = NULL;
if (struct_level >= STRUCT_DEPTH) if (struct_level >= STRUCT_DEPTH)
mmerror(PARSE_ERROR, ET_ERROR, "Too many levels in nested structure/union definition"); mmerror(PARSE_ERROR, ET_ERROR, "Too many levels in nested structure/union definition");
forward_name = mm_strdup($1.symbol);
} }
'{' variable_declarations '}' '{' variable_declarations '}'
{ {
ECPGfree_struct_member(struct_member_list[struct_level]); ECPGfree_struct_member(struct_member_list[struct_level]);
struct_member_list[struct_level] = NULL; struct_member_list[struct_level] = NULL;
free(actual_storage[struct_level--]); free(actual_storage[struct_level--]);
if (strncmp($1, "struct", sizeof("struct")-1) == 0) if (strncmp($1.su, "struct", sizeof("struct")-1) == 0)
$$.type_enum = ECPGt_struct; $$.type_enum = ECPGt_struct;
else else
$$.type_enum = ECPGt_union; $$.type_enum = ECPGt_union;
$$.type_str = mm_strdup($1); $$.type_str = cat2_str($1.su, $1.symbol);
$$.type_sizeof = cat_str(4, $1, make_str("{"), $4, make_str("}")); $$.type_sizeof = cat_str(4, mm_strdup($$.type_str), make_str("{"), $4, make_str("}"));
free(forward_name);
forward_name = NULL;
} }
; ;
...@@ -4822,12 +4867,14 @@ struct_union_type: struct_union_type_with_symbol { $$ = $1.type_sizeof; } ...@@ -4822,12 +4867,14 @@ struct_union_type: struct_union_type_with_symbol { $$ = $1.type_sizeof; }
s_struct_union_symbol: SQL_STRUCT symbol s_struct_union_symbol: SQL_STRUCT symbol
{ {
$$ = cat2_str(make_str("struct"), $2); $$.su = make_str("struct");
ECPGstruct_sizeof = cat_str(3, make_str("sizeof("), strdup($$), make_str(")")); $$.symbol = $2;
ECPGstruct_sizeof = cat_str(3, make_str("sizeof("), cat2_str(mm_strdup($$.su), mm_strdup($$.symbol)), make_str(")"));
} }
| UNION symbol | UNION symbol
{ {
$$ = cat2_str(make_str("union"), $2); $$.su = make_str("union");
$$.symbol = $2;
} }
; ;
......
...@@ -225,7 +225,6 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * type, ...@@ -225,7 +225,6 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * type,
case ECPGt_array: case ECPGt_array:
if (indicator_set && ind_type->type != ECPGt_array) if (indicator_set && ind_type->type != ECPGt_array)
mmerror(INDICATOR_NOT_ARRAY, ET_FATAL, "Indicator for array/pointer has to be array/pointer.\n"); mmerror(INDICATOR_NOT_ARRAY, ET_FATAL, "Indicator for array/pointer has to be array/pointer.\n");
switch (type->u.element->type) switch (type->u.element->type)
{ {
case ECPGt_array: case ECPGt_array:
...@@ -233,8 +232,14 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * type, ...@@ -233,8 +232,14 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * type,
break; break;
case ECPGt_struct: case ECPGt_struct:
case ECPGt_union: case ECPGt_union:
/* If var_array_element is not equal * NULL, we have to use the * <var_array_element>th entry and not * the whole array */ if (var_array_element == NULL) /* If var_array_element is not equal
ECPGdump_a_struct(o, name, ind_name, type->size, * NULL, we have to use the
* <var_array_element>th entry and
* not the whole array */
if (var_array_element == NULL)
ECPGdump_a_struct(o, name,
ind_name,
type->size,
type->u.element, type->u.element,
(ind_type->type == ECPGt_NO_INDICATOR) ? ind_type : ind_type->u.element, (ind_type->type == ECPGt_NO_INDICATOR) ? ind_type : ind_type->u.element,
NULL, prefix, ind_prefix); NULL, prefix, ind_prefix);
......
...@@ -88,6 +88,12 @@ struct index ...@@ -88,6 +88,12 @@ struct index
char *str; char *str;
}; };
struct su_symbol
{
char *su;
char *symbol;
};
struct this_type struct this_type
{ {
enum ECPGttype type_enum; enum ECPGttype type_enum;
......
...@@ -67,7 +67,7 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member * members, in ...@@ -67,7 +67,7 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member * members, in
} }
static struct variable * static struct variable *
find_struct(char *name, char *next) find_struct(char *name, char *next, char *end)
{ {
struct variable *p; struct variable *p;
char c = *next; char c = *next;
...@@ -90,24 +90,45 @@ find_struct(char *name, char *next) ...@@ -90,24 +90,45 @@ find_struct(char *name, char *next)
mmerror(PARSE_ERROR, ET_FATAL, errortext); mmerror(PARSE_ERROR, ET_FATAL, errortext);
} }
/* restore the name, we will need it later on */ /* restore the name, we will need it later */
*next = c; *next = c;
next++;
return find_struct_member(name, next, p->type->u.element->u.members, p->brace_level); return find_struct_member(name, end, p->type->u.element->u.members, p->brace_level);
} }
else else
{ {
if (p->type->type != ECPGt_struct && p->type->type != ECPGt_union) if (next == end)
{ {
snprintf(errortext, sizeof(errortext), "variable %s is neither a structure nor a union", name); if (p->type->type != ECPGt_struct && p->type->type != ECPGt_union)
mmerror(PARSE_ERROR, ET_FATAL, errortext); {
snprintf(errortext, sizeof(errortext), "variable %s is neither a structure nor a union", name);
mmerror(PARSE_ERROR, ET_FATAL, errortext);
}
/* restore the name, we will need it later */
*next = c;
return find_struct_member(name, end, p->type->u.members, p->brace_level);
} }
else
{
if (p->type->type != ECPGt_array)
{
snprintf(errortext, sizeof(errortext), "variable %s is not an array", name);
mmerror(PARSE_ERROR, ET_FATAL, errortext);
}
/* restore the name, we will need it later on */ if (p->type->u.element->type != ECPGt_struct && p->type->u.element->type != ECPGt_union)
*next = c; {
snprintf(errortext, sizeof(errortext), "variable %s is not a pointer to a structure or a union", name);
mmerror(PARSE_ERROR, ET_FATAL, errortext);
}
/* restore the name, we will need it later */
*next = c;
return find_struct_member(name, next, p->type->u.members, p->brace_level); return find_struct_member(name, end, p->type->u.element->u.members, p->brace_level);
}
} }
} }
...@@ -130,15 +151,43 @@ find_simple(char *name) ...@@ -130,15 +151,43 @@ find_simple(char *name)
struct variable * struct variable *
find_variable(char *name) find_variable(char *name)
{ {
char *next; char *next, *end;
struct variable *p; struct variable *p;
int count;
if ((next = strchr(name, '.')) != NULL) printf("MM: find %s\n", name);
p = find_struct(name, next);
else if ((next = strstr(name, "->")) != NULL) next = strpbrk(name, ".[-");
p = find_struct(name, next); if (next)
else {
p = find_simple(name); if (*next == '[')
{
/* We don't care about what's inside the array braces
* so just eat up the character */
for (count=1, end=next+1; count; end++)
{
switch (*end)
{
case '[': count++;
break;
case ']': count--;
break;
default : break;
}
}
if (*end == '.') p = find_struct(name, next, end);
else
{
char c = *next;
*next = '\0';
p = find_simple(name);
*next = c;
}
}
else p = find_struct(name, next, next);
}
else p = find_simple(name);
if (p == NULL) if (p == NULL)
{ {
...@@ -330,6 +379,7 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty ...@@ -330,6 +379,7 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty
mmerror(PARSE_ERROR, ET_FATAL, errortext); mmerror(PARSE_ERROR, ET_FATAL, errortext);
/* mmerror(PARSE_ERROR, ET_FATAL, "No multilevel (more than 2) pointer supported %d",pointer_len);*/ /* mmerror(PARSE_ERROR, ET_FATAL, "No multilevel (more than 2) pointer supported %d",pointer_len);*/
} }
if (pointer_len > 1 && type_enum != ECPGt_char && type_enum != ECPGt_unsigned_char) if (pointer_len > 1 && type_enum != ECPGt_char && type_enum != ECPGt_unsigned_char)
mmerror(PARSE_ERROR, ET_FATAL, "No pointer to pointer supported for this type"); mmerror(PARSE_ERROR, ET_FATAL, "No pointer to pointer supported for this type");
......
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