mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-06 15:24:56 +08:00
Parse forward definiton of structs.
This commit is contained in:
parent
9e2a980f62
commit
bbe9902223
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -88,6 +88,12 @@ struct index
|
||||
char *str;
|
||||
};
|
||||
|
||||
struct su_symbol
|
||||
{
|
||||
char *su;
|
||||
char *symbol;
|
||||
};
|
||||
|
||||
struct this_type
|
||||
{
|
||||
enum ECPGttype type_enum;
|
||||
|
@ -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");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user