Parse forward definiton of structs.

This commit is contained in:
Michael Meskes 2003-05-29 12:00:22 +00:00
parent 9e2a980f62
commit bbe9902223
6 changed files with 162 additions and 138 deletions

View File

@ -1449,6 +1449,10 @@ Tue May 27 13:29:28 CEST 2003
Tue May 27 16:33:36 CEST 2003
- 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 library to 3.4.2.
- Set pgtypes library to 1.0.0

View File

@ -12,7 +12,7 @@
*
*
* 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]
identifier {letter}{letter_or_digit}*
array ({letter_or_digit}|[\+\-\*\%\/\(\)])*
typecast "::"
/*
@ -949,96 +950,7 @@ cppline {space}*#(.*\\{space})+.*
<incl>\<[^\>]+\>{space}*";"? { parse_include(); }
<incl>{dquote}{xdinside}{dquote}{space}*";"? { parse_include(); }
<incl>[^;\<\>\"]+";" {
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
}
<incl>[^;\<\>\"]+";" { parse_include(); }
<<EOF>> {
if (yy_buffer == NULL) {

View File

@ -1,4 +1,4 @@
/* $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 */
%{
@ -27,6 +27,9 @@ struct ECPGstruct_member *struct_member_list[STRUCT_DEPTH] = { NULL };
/* also store struct type so we can do a sizeof() later */
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 variable no_indicator = {"no_indicator", &ecpg_no_indicator, 0, NULL};
@ -196,6 +199,7 @@ create_questionmarks(char *name, bool array)
enum ECPGttype type_enum;
enum ECPGdtype dtype_enum;
struct fetch_desc descriptor;
struct su_symbol struct_union;
}
/* special embedded SQL token */
@ -440,7 +444,9 @@ create_questionmarks(char *name, bool array)
%type <str> reserved_keyword unreserved_keyword ecpg_interval
%type <str> col_name_keyword func_name_keyword precision opt_scale
%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
@ -4039,7 +4045,6 @@ connection_target: database_name opt_server opt_port
}
| StringConst
{
printf("MM: %s\n", $1);
if ($1[0] == '\"')
$$ = $1;
else if (strcmp($1, " ?") == 0) /* variable */
@ -4425,16 +4430,34 @@ single_vt_type: common_type
| s_struct_union_symbol
{
/* this is for named structs/unions */
char *name = $1;
struct typedefs *this = get_typedef(name);
char *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;
$$.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);
name = cat2_str($1.su, $1.symbol);
/* Do we have a forward definition? */
if (!forward)
{
/* 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;
}
}
;
@ -4761,15 +4784,34 @@ var_type: common_type
| s_struct_union_symbol
{
/* this is for named structs/unions */
char *name = $1;
struct typedefs *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);
char *name;
struct typedefs *this;
bool forward = (strcmp($1.symbol, forward_name) == 0 && strcmp($1.su, "struct") == 0);
name = cat2_str($1.su, $1.symbol);
/* Do we have a forward definition? */
if (!forward)
{
/* 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
struct_member_list[struct_level++] = NULL;
if (struct_level >= STRUCT_DEPTH)
mmerror(PARSE_ERROR, ET_ERROR, "Too many levels in nested structure/union definition");
forward_name = mm_strdup($1.symbol);
}
'{' variable_declarations '}'
{
ECPGfree_struct_member(struct_member_list[struct_level]);
struct_member_list[struct_level] = NULL;
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;
else
$$.type_enum = ECPGt_union;
$$.type_str = mm_strdup($1);
$$.type_sizeof = cat_str(4, $1, make_str("{"), $4, make_str("}"));
$$.type_str = cat2_str($1.su, $1.symbol);
$$.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; }
s_struct_union_symbol: SQL_STRUCT symbol
{
$$ = cat2_str(make_str("struct"), $2);
ECPGstruct_sizeof = cat_str(3, make_str("sizeof("), strdup($$), make_str(")"));
$$.su = make_str("struct");
$$.symbol = $2;
ECPGstruct_sizeof = cat_str(3, make_str("sizeof("), cat2_str(mm_strdup($$.su), mm_strdup($$.symbol)), make_str(")"));
}
| UNION symbol
{
$$ = cat2_str(make_str("union"), $2);
$$.su = make_str("union");
$$.symbol = $2;
}
;

View File

@ -225,7 +225,6 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * type,
case 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");
switch (type->u.element->type)
{
case ECPGt_array:
@ -233,8 +232,14 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * type,
break;
case ECPGt_struct:
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)
ECPGdump_a_struct(o, name, ind_name, type->size,
/* 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)
ECPGdump_a_struct(o, name,
ind_name,
type->size,
type->u.element,
(ind_type->type == ECPGt_NO_INDICATOR) ? ind_type : ind_type->u.element,
NULL, prefix, ind_prefix);

View File

@ -88,6 +88,12 @@ struct index
char *str;
};
struct su_symbol
{
char *su;
char *symbol;
};
struct this_type
{
enum ECPGttype type_enum;

View File

@ -67,7 +67,7 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member * members, in
}
static struct variable *
find_struct(char *name, char *next)
find_struct(char *name, char *next, char *end)
{
struct variable *p;
char c = *next;
@ -90,24 +90,45 @@ find_struct(char *name, char *next)
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++;
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
{
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);
mmerror(PARSE_ERROR, ET_FATAL, errortext);
if (p->type->type != ECPGt_struct && p->type->type != ECPGt_union)
{
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 */
*next = c;
if (p->type->u.element->type != ECPGt_struct && p->type->u.element->type != ECPGt_union)
{
snprintf(errortext, sizeof(errortext), "variable %s is not a pointer to a structure or a union", name);
mmerror(PARSE_ERROR, ET_FATAL, errortext);
}
return find_struct_member(name, next, p->type->u.members, p->brace_level);
/* restore the name, we will need it later */
*next = c;
return find_struct_member(name, end, p->type->u.element->u.members, p->brace_level);
}
}
}
@ -130,15 +151,43 @@ find_simple(char *name)
struct variable *
find_variable(char *name)
{
char *next;
char *next, *end;
struct variable *p;
int count;
if ((next = strchr(name, '.')) != NULL)
p = find_struct(name, next);
else if ((next = strstr(name, "->")) != NULL)
p = find_struct(name, next);
else
p = find_simple(name);
printf("MM: find %s\n", name);
next = strpbrk(name, ".[-");
if (next)
{
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)
{
@ -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, "No multilevel (more than 2) pointer supported %d",pointer_len);*/
}
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");