diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog index 02fe1e9d41..ba19efc1d3 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 c489f64dcb..880f6f0500 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})+.* \<[^\>]+\>{space}*";"? { parse_include(); } {dquote}{xdinside}{dquote}{space}*";"? { 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 - } +[^;\<\>\"]+";" { parse_include(); } <> { if (yy_buffer == NULL) { diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index 6f0aa04cc5..c1c279550c 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 reserved_keyword unreserved_keyword ecpg_interval %type col_name_keyword func_name_keyword precision opt_scale %type ECPGTypeName variablelist ECPGColLabelCommon c_variable -%type s_struct_union_symbol inf_val_list inf_col_list +%type inf_val_list inf_col_list + +%type s_struct_union_symbol %type 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; } ; diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c index 8bef0b36e2..f9045cfb42 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 * 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 + * 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 28615af8c9..233bde0357 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 b62ba4d2c4..82b749981c 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); + } - 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");