diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog index ba19efc1d3..9c5c187a27 100644 --- a/src/interfaces/ecpg/ChangeLog +++ b/src/interfaces/ecpg/ChangeLog @@ -1453,6 +1453,11 @@ Tue May 27 16:33:36 CEST 2003 Thu May 29 13:58:25 CEST 2003 - ecpg should now be able to parse forward struct definition. + +Thu May 29 15:45:57 CEST 2003 + + - Changed parsing of variables to be able to reference one attribute + of the n-th entry in an array of structs. - 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/descriptor.c b/src/interfaces/ecpg/preproc/descriptor.c index 1c147820f1..742002b4c0 100644 --- a/src/interfaces/ecpg/preproc/descriptor.c +++ b/src/interfaces/ecpg/preproc/descriptor.c @@ -192,7 +192,7 @@ output_get_descr(char *desc_name, char *index) break; } fprintf(yyout, "%s,", get_dtype(results->value)); - ECPGdump_a_type(yyout, v->name, v->type, NULL, NULL, NULL, NULL, NULL, NULL, make_str("0"), NULL, NULL); + ECPGdump_a_type(yyout, v->name, v->type, NULL, NULL, NULL, NULL, make_str("0"), NULL, NULL); } drop_assignments(); fputs("ECPGd_EODT);\n", yyout); diff --git a/src/interfaces/ecpg/preproc/extern.h b/src/interfaces/ecpg/preproc/extern.h index 7c20ee405d..bc0cceaae9 100644 --- a/src/interfaces/ecpg/preproc/extern.h +++ b/src/interfaces/ecpg/preproc/extern.h @@ -73,8 +73,8 @@ extern void add_descriptor(char *, char *); extern void drop_descriptor(char *, char *); extern struct descriptor *lookup_descriptor(char *, char *); extern struct variable *descriptor_variable(const char *name, int input); -extern void add_variable(struct arguments **, struct variable *, char *i, struct variable *, char *); -extern void append_variable(struct arguments **, struct variable *, char *, struct variable *, char *); +extern void add_variable(struct arguments **, struct variable *, struct variable *); +extern void append_variable(struct arguments **, struct variable *, struct variable *); extern void dump_variables(struct arguments *, int); extern struct typedefs *get_typedef(char *); extern void adjust_array(enum ECPGttype, char **, char **, char *, char *, int); diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l index 880f6f0500..923ca5b3ab 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.112 2003/05/29 12:00:21 meskes Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.113 2003/05/29 13:59:26 meskes Exp $ * *------------------------------------------------------------------------- */ @@ -540,7 +540,7 @@ cppline {space}*#(.*\\{space})+.* yylval.str = mm_strdup(yytext); return FCONST; } -:{identifier}(("->"|\.){identifier})* { +:{identifier}((("->"|\.){identifier})|(\[{array}\]))* { yylval.str = mm_strdup(yytext+1); return(CVARIABLE); } diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index c1c279550c..f001454b2b 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.224 2003/05/29 12:00:21 meskes Exp $ */ +/* $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/Attic/preproc.y,v 1.225 2003/05/29 13:59:26 meskes Exp $ */ /* Copyright comment */ %{ @@ -668,10 +668,10 @@ stmt: AlterDatabaseSetStmt { output_statement($1, 0, connection); } { /* merge variables given in prepare statement with those given here */ for (p = ptr->argsinsert; p; p = p->next) - append_variable(&argsinsert, p->variable, p->var_array_element, p->indicator, p->ind_array_element); + append_variable(&argsinsert, p->variable, p->indicator); for (p = ptr->argsresult; p; p = p->next) - add_variable(&argsresult, p->variable, p->var_array_element, p->indicator, p->ind_array_element); + add_variable(&argsresult, p->variable, p->indicator); output_statement(mm_strdup(ptr->command), 0, ptr->connection ? mm_strdup(ptr->connection) : NULL); } @@ -4234,7 +4234,7 @@ ECPGCursorStmt: DECLARE name cursor_options CURSOR opt_hold FOR ident sprintf(thisquery->name, "ECPGprepared_statement(\"%s\")", $7); this->argsinsert = NULL; - add_variable(&(this->argsinsert), thisquery, NULL, &no_indicator, NULL); + add_variable(&(this->argsinsert), thisquery, &no_indicator); cur = this; @@ -5095,7 +5095,7 @@ ECPGExecute : EXECUTE IMMEDIATE execstring thisquery->next = NULL; thisquery->name = $3; - add_variable(&argsinsert, thisquery, NULL, &no_indicator, NULL); + add_variable(&argsinsert, thisquery, &no_indicator); $$ = make_str("?"); } @@ -5109,7 +5109,7 @@ ECPGExecute : EXECUTE IMMEDIATE execstring thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement(\"\")") + strlen($2)); sprintf(thisquery->name, "ECPGprepared_statement(\"%s\")", $2); - add_variable(&argsinsert, thisquery, NULL, &no_indicator, NULL); + add_variable(&argsinsert, thisquery, &no_indicator); } opt_ecpg_using opt_ecpg_into { @@ -5150,7 +5150,7 @@ ecpg_into: INTO into_list } | INTO opt_sql SQL_DESCRIPTOR quoted_ident_stringvar { - add_variable(&argsresult, descriptor_variable($4,0), NULL, &no_indicator, NULL); + add_variable(&argsresult, descriptor_variable($4,0), &no_indicator); $$ = EMPTY; } ; @@ -5970,57 +5970,26 @@ c_args: /*EMPTY*/ { $$ = EMPTY; } | c_list { $$ = $1; } ; -coutputvariable: CVARIABLE '[' Iresult ']' indicator '[' Iresult ']' - { add_variable(&argsresult, find_variable($1), $3, find_variable($5), $7); } - | CVARIABLE indicator '[' Iresult ']' - { add_variable(&argsresult, find_variable($1), NULL, find_variable($2), $4); } - | CVARIABLE '[' Iresult ']' indicator - { add_variable(&argsresult, find_variable($1), $3, find_variable($5), NULL); } - | CVARIABLE indicator - { add_variable(&argsresult, find_variable($1), NULL, find_variable($2), NULL); } - | CVARIABLE '[' Iresult ']' - { add_variable(&argsresult, find_variable($1), $3, &no_indicator, NULL); } +coutputvariable: CVARIABLE indicator + { add_variable(&argsresult, find_variable($1), find_variable($2)); } | CVARIABLE - { add_variable(&argsresult, find_variable($1), NULL, &no_indicator, NULL); } + { add_variable(&argsresult, find_variable($1), &no_indicator); } ; -civarind: CVARIABLE '[' Iresult ']' indicator '[' Iresult ']' - { - add_variable(&argsinsert, find_variable($1), $3, find_variable($5), $7); - $$ = create_questionmarks($1, true); - } - | CVARIABLE indicator '[' Iresult ']' - { - add_variable(&argsinsert, find_variable($1), NULL, find_variable($2), $4); - $$ = create_questionmarks($1, false); - } - | CVARIABLE '[' Iresult ']' indicator - { - if (find_variable($5)->type->type == ECPGt_array) - mmerror(PARSE_ERROR, ET_ERROR, "arrays of indicators are not allowed on input"); - - add_variable(&argsinsert, find_variable($1), $3, find_variable($5), NULL); - $$ = create_questionmarks($1, true); - } - | CVARIABLE indicator +civarind: CVARIABLE indicator { if (find_variable($2)->type->type == ECPGt_array) mmerror(PARSE_ERROR, ET_ERROR, "arrays of indicators are not allowed on input"); - add_variable(&argsinsert, find_variable($1), NULL, find_variable($2), NULL); + add_variable(&argsinsert, find_variable($1), find_variable($2)); $$ = create_questionmarks($1, false); } ; -civar: CVARIABLE '[' Iresult ']' +civar: CVARIABLE { - add_variable(&argsinsert, find_variable($1), mm_strdup($3), &no_indicator, NULL); - $$ = create_questionmarks($1, true); - } - | CVARIABLE - { - add_variable(&argsinsert, find_variable($1), NULL, &no_indicator, NULL); + add_variable(&argsinsert, find_variable($1), &no_indicator); $$ = create_questionmarks($1, false); } ; diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c index f9045cfb42..7ac5c55a28 100644 --- a/src/interfaces/ecpg/preproc/type.c +++ b/src/interfaces/ecpg/preproc/type.c @@ -214,8 +214,7 @@ static void ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, c void ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * type, - const char *var_array_element, const char *ind_name, - struct ECPGtype * ind_type, const char *ind_array_element, + const char *ind_name, struct ECPGtype * ind_type, const char *prefix, const char *ind_prefix, char *arr_str_siz, const char *struct_sizeof, const char *ind_struct_sizeof) @@ -232,65 +231,20 @@ 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, - type->u.element, - (ind_type->type == ECPGt_NO_INDICATOR) ? ind_type : ind_type->u.element, - NULL, prefix, ind_prefix); - else - { - char *array_element = (char *)mm_alloc(strlen(name) + strlen(var_array_element) + sizeof("[]\0")), *ind_array_element; - - sprintf(array_element, "%s[%s]", name, var_array_element); - - if (ind_type->type != ECPGt_NO_INDICATOR) - { - ind_array_element = (char *)mm_alloc(strlen(ind_name) + strlen(ind_array_element) + sizeof("+\0")); - sprintf(ind_array_element, "%s[%s]", ind_name, ind_array_element); - - ECPGdump_a_struct(o, array_element, ind_array_element, make_str("1"), - type->u.element, ind_type->u.element, - NULL, prefix, ind_prefix); - free(ind_array_element); - } - else - ECPGdump_a_struct(o, array_element, ind_name, make_str("1"), - type->u.element, ind_type, - NULL, prefix, ind_prefix); - - free (array_element); - } + 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); break; default: if (!IS_SIMPLE_TYPE(type->u.element->type)) yyerror("Internal error: unknown datatype, please inform pgsql-bugs@postgresql.org"); - /* 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_simple(o, name, - type->u.element->type, + ECPGdump_a_simple(o, name, + type->u.element->type, type->u.element->size, type->size, NULL, prefix); - else - { - char *array_element = (char *)mm_alloc(strlen(name) + strlen(var_array_element) + sizeof("+\0")); - - sprintf(array_element, "%s+%s", name, var_array_element); - ECPGdump_a_simple(o, array_element, - type->u.element->type, - type->u.element->size, make_str("1"), NULL, prefix); - free(array_element); - - - } if (ind_type != NULL) { @@ -298,20 +252,8 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * type, ECPGdump_a_simple(o, ind_name, ind_type->type, ind_type->size, make_str("-1"), NULL, ind_prefix); else { - if (ind_array_element == NULL) - ECPGdump_a_simple(o, ind_name, ind_type->u.element->type, - ind_type->u.element->size, ind_type->size, NULL, prefix); - else - { - char *array_element = (char *)mm_alloc(strlen(ind_name) + strlen(ind_array_element) + sizeof("+\0")); - - sprintf(array_element, "%s+%s", ind_name, ind_array_element); - ECPGdump_a_simple(o, array_element, - ind_type->u.element->type, - ind_type->u.element->size, - make_str("1"), NULL, prefix); - free(array_element); - } + ECPGdump_a_simple(o, ind_name, ind_type->u.element->type, + ind_type->u.element->size, ind_type->size, NULL, prefix); } } } @@ -516,9 +458,9 @@ ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, char *arrsiz, for (p = type->u.members; p; p = p->next) { - ECPGdump_a_type(o, p->name, p->type, NULL, + ECPGdump_a_type(o, p->name, p->type, (ind_p != NULL) ? ind_p->name : NULL, - (ind_p != NULL) ? ind_p->type : NULL, NULL, + (ind_p != NULL) ? ind_p->type : NULL, prefix, ind_prefix, arrsiz, type->struct_sizeof, (ind_p != NULL) ? ind_type->struct_sizeof : NULL); if (ind_p != NULL && ind_p != &struct_no_indicator) diff --git a/src/interfaces/ecpg/preproc/type.h b/src/interfaces/ecpg/preproc/type.h index 233bde0357..9e8d6cea30 100644 --- a/src/interfaces/ecpg/preproc/type.h +++ b/src/interfaces/ecpg/preproc/type.h @@ -49,8 +49,8 @@ void ECPGfree_type(struct ECPGtype *); size is the maxsize in case it is a varchar. Otherwise it is the size of the variable (required to do array fetches of structs). */ -void ECPGdump_a_type(FILE *, const char *, struct ECPGtype *, const char *, - const char *, struct ECPGtype *, const char *, const char *, +void ECPGdump_a_type(FILE *, const char *, struct ECPGtype *, + const char *, struct ECPGtype *, const char *, const char *, char *, const char *, const char *); /* A simple struct to keep a variable and its type. */ @@ -147,9 +147,7 @@ struct variable struct arguments { struct variable *variable; - char *var_array_element; struct variable *indicator; - char *ind_array_element; struct arguments *next; }; diff --git a/src/interfaces/ecpg/preproc/variable.c b/src/interfaces/ecpg/preproc/variable.c index 82b749981c..83b56ac9dc 100644 --- a/src/interfaces/ecpg/preproc/variable.c +++ b/src/interfaces/ecpg/preproc/variable.c @@ -22,8 +22,8 @@ new_variable(const char *name, struct ECPGtype * type, int brace_level) static struct variable * find_struct_member(char *name, char *str, struct ECPGstruct_member * members, int brace_level) { - char *next = strchr(++str, '.'), - c = '\0'; + char *next = strpbrk(++str, ".-["), + *end, c = '\0'; if (next != NULL) { @@ -35,7 +35,7 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member * members, in { if (strcmp(members->name, str) == 0) { - if (c == '\0') + if (next == NULL) { /* found the end */ switch (members->type->type) @@ -52,13 +52,57 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member * members, in else { *next = c; - if (c == '-') + if (c == '[') { - next++; - return (find_struct_member(name, next, members->type->u.element->u.members, brace_level)); + int count; + + /* 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; + } + } + } + else end = next; + + switch (*end) + { + case '\0': /* found the end, but this time it has to be an array element */ + if (members->type->type != ECPGt_array) + { + snprintf(errortext, sizeof(errortext), "incorrectly formed variable %s", name); + mmerror(PARSE_ERROR, ET_FATAL, errortext); + } + + switch (members->type->u.element->type) + { + case ECPGt_array: + return (new_variable(name, ECPGmake_array_type(members->type->u.element->u.element, members->type->u.element->size), brace_level)); + case ECPGt_struct: + case ECPGt_union: + return (new_variable(name, ECPGmake_struct_type(members->type->u.element->u.members, members->type->u.element->type, members->type->u.element->struct_sizeof), brace_level)); + default: + return (new_variable(name, ECPGmake_simple_type(members->type->u.element->type, members->type->u.element->size), brace_level)); + } + break; + case '-': return (find_struct_member(name, end, members->type->u.element->u.members, brace_level)); + break; + case '.': if (members->type->type != ECPGt_array) + return (find_struct_member(name, end, members->type->u.element->u.members, brace_level)); + else + return (find_struct_member(name, next, members->type->u.members, brace_level)); + break; + default : snprintf(errortext, sizeof(errortext), "incorrectly formed variable %s", name); + mmerror(PARSE_ERROR, ET_FATAL, errortext); + break; } - else - return (find_struct_member(name, next, members->type->u.members, brace_level)); } } } @@ -155,8 +199,6 @@ find_variable(char *name) struct variable *p; int count; - printf("MM: find %s\n", name); - next = strpbrk(name, ".[-"); if (next) { @@ -178,11 +220,21 @@ find_variable(char *name) if (*end == '.') p = find_struct(name, next, end); else { - char c = *next; + char c = *next; - *next = '\0'; - p = find_simple(name); - *next = c; + *next = '\0'; + p = find_simple(name); + *next = c; + switch (p->type->u.element->type) + { + case ECPGt_array: + return (new_variable(name, ECPGmake_array_type(p->type->u.element->u.element, p->type->u.element->size), p->brace_level)); + case ECPGt_struct: + case ECPGt_union: + return (new_variable(name, ECPGmake_struct_type(p->type->u.element->u.members, p->type->u.element->type, p->type->u.element->struct_sizeof), p->brace_level)); + default: + return (new_variable(name, ECPGmake_simple_type(p->type->u.element->type, p->type->u.element->size), p->brace_level)); + } } } else p = find_struct(name, next, next); @@ -243,21 +295,19 @@ reset_variables(void) /* Insert a new variable into our request list. */ void -add_variable(struct arguments ** list, struct variable * var, char * var_array_element, struct variable * ind, char * ind_array_element) +add_variable(struct arguments ** list, struct variable * var, struct variable * ind) { struct arguments *p = (struct arguments *) mm_alloc(sizeof(struct arguments)); p->variable = var; - p->var_array_element = var_array_element; p->indicator = ind; - p->ind_array_element = ind_array_element; p->next = *list; *list = p; } /* Append a new variable to our request list. */ void -append_variable(struct arguments ** list, struct variable * var, char * var_array_element, struct variable * ind, char * ind_array_element) +append_variable(struct arguments ** list, struct variable * var, struct variable * ind) { struct arguments *p, *new = (struct arguments *) mm_alloc(sizeof(struct arguments)); @@ -265,9 +315,7 @@ append_variable(struct arguments ** list, struct variable * var, char * var_arra for (p = *list; p && p->next; p = p->next); new->variable = var; - new->var_array_element = var_array_element; new->indicator = ind; - new->ind_array_element = ind_array_element; new->next = NULL; if (p) @@ -294,8 +342,8 @@ dump_variables(struct arguments * list, int mode) dump_variables(list->next, mode); /* Then the current element and its indicator */ - ECPGdump_a_type(yyout, list->variable->name, list->variable->type, list->var_array_element, - list->indicator->name, list->indicator->type, list->ind_array_element, + ECPGdump_a_type(yyout, list->variable->name, list->variable->type, + list->indicator->name, list->indicator->type, NULL, NULL, 0, NULL, NULL); /* Then release the list element. */ diff --git a/src/interfaces/ecpg/test/num_test.pgc b/src/interfaces/ecpg/test/num_test.pgc index 42eb66d9a0..4e921bb33e 100644 --- a/src/interfaces/ecpg/test/num_test.pgc +++ b/src/interfaces/ecpg/test/num_test.pgc @@ -21,37 +21,37 @@ main() exec sql create table test (text char(5), num decimal(14,7)); value1 = PGTYPESnew(); - PGTYPESnumeric_iton(1407, value1); - text = PGTYPESnumeric_ntoa(value1); + PGTYPESnumeric_from_int(1407, value1); + text = PGTYPESnumeric_to_asc(value1, 0); printf("long = %s\n", text); - value1 = PGTYPESnumeric_aton("2369.7", NULL); - value2 = PGTYPESnumeric_aton("10.0", NULL); + value1 = PGTYPESnumeric_from_asc("2369.7", NULL); + value2 = PGTYPESnumeric_from_asc("10.0", NULL); res = PGTYPESnew(); - decadd(value1, value2, res); - text = PGTYPESnumeric_ntoa(res); + PGTYPESnumeric_add(value1, value2, res); + text = PGTYPESnumeric_to_asc(res, 0); printf("add = %s\n", text); PGTYPESnumeric_sub(res, value2, res); - text = PGTYPESnumeric_ntoa(res); + text = PGTYPESnumeric_to_asc(res, 0); printf("sub = %s\n", text); PGTYPESnumeric_copy(res, &des); exec sql insert into test (text, num) values ('test', :des); - value2 = PGTYPESnumeric_aton("2369.7", NULL); + value2 = PGTYPESnumeric_from_asc("2369.7", NULL); PGTYPESnumeric_mul(value1, value2, res); exec sql select num into :des from test where text = 'test'; PGTYPESnumeric_mul(res, &des, res); - text = PGTYPESnumeric_ntoa(res); + text = PGTYPESnumeric_to_asc(res, 0); printf("mul = %s\n", text); - value2 = PGTYPESnumeric_aton("10000", NULL); + value2 = PGTYPESnumeric_from_asc("10000", NULL); PGTYPESnumeric_div(res, value2, res); - text = PGTYPESnumeric_ntoa(res); - PGTYPESnumeric_ntod(res, &d); + text = PGTYPESnumeric_to_asc(res, 0); + PGTYPESnumeric_to_double(res, &d); printf("div = %s %e\n", text, d); exec sql rollback;