aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Meskes <meskes@postgresql.org>2003-05-29 12:00:22 +0000
committerMichael Meskes <meskes@postgresql.org>2003-05-29 12:00:22 +0000
commitbbe990222365aa4a8dfdf2b203ea185b92df6a1c (patch)
treef55b019248f1f46dcc01ca5cf0eaf4cf87db2cc4
parent9e2a980f62ad805b72088c6eed7604b603a33388 (diff)
downloadpostgresql-bbe990222365aa4a8dfdf2b203ea185b92df6a1c.tar.gz
postgresql-bbe990222365aa4a8dfdf2b203ea185b92df6a1c.zip
Parse forward definiton of structs.
-rw-r--r--src/interfaces/ecpg/ChangeLog4
-rw-r--r--src/interfaces/ecpg/preproc/pgc.l94
-rw-r--r--src/interfaces/ecpg/preproc/preproc.y103
-rw-r--r--src/interfaces/ecpg/preproc/type.c11
-rw-r--r--src/interfaces/ecpg/preproc/type.h6
-rw-r--r--src/interfaces/ecpg/preproc/variable.c84
6 files changed, 163 insertions, 139 deletions
diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog
index 02fe1e9d41f..ba19efc1d36 100644
--- a/src/interfaces/ecpg/ChangeLog
+++ b/src/interfaces/ecpg/ChangeLog
@@ -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
diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l
index c489f64dcb9..880f6f05006 100644
--- a/src/interfaces/ecpg/preproc/pgc.l
+++ b/src/interfaces/ecpg/preproc/pgc.l
@@ -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) {
diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y
index 6f0aa04cc55..c1c279550cd 100644
--- a/src/interfaces/ecpg/preproc/preproc.y
+++ b/src/interfaces/ecpg/preproc/preproc.y
@@ -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);
-
- $$.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;
+ }
}
;
@@ -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;
}
;
diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c
index 8bef0b36e20..f9045cfb425 100644
--- a/src/interfaces/ecpg/preproc/type.c
+++ b/src/interfaces/ecpg/preproc/type.c
@@ -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);
diff --git a/src/interfaces/ecpg/preproc/type.h b/src/interfaces/ecpg/preproc/type.h
index 28615af8c9c..233bde03573 100644
--- a/src/interfaces/ecpg/preproc/type.h
+++ b/src/interfaces/ecpg/preproc/type.h
@@ -88,6 +88,12 @@ struct index
char *str;
};
+struct su_symbol
+{
+ char *su;
+ char *symbol;
+};
+
struct this_type
{
enum ECPGttype type_enum;
diff --git a/src/interfaces/ecpg/preproc/variable.c b/src/interfaces/ecpg/preproc/variable.c
index b62ba4d2c4d..82b749981cf 100644
--- a/src/interfaces/ecpg/preproc/variable.c
+++ b/src/interfaces/ecpg/preproc/variable.c
@@ -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);
+ }
+
+ /* 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)
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");