From 6ccfc4f4301f38b63e6b94aae458c242631c3421 Mon Sep 17 00:00:00 2001 From: Michael Meskes Date: Wed, 28 Jan 2004 09:52:14 +0000 Subject: [PATCH] - Issue a warning if a cursor is declared but not opened. - Fixed prototype for ECPGprepared_statement to not moan about "const char" - Fixed parsing of nested structures. - Added option to parse header files. --- src/interfaces/ecpg/ChangeLog | 8 ++++++ src/interfaces/ecpg/ecpglib/execute.c | 6 ++-- src/interfaces/ecpg/ecpglib/prepare.c | 4 +-- src/interfaces/ecpg/include/ecpglib.h | 2 +- src/interfaces/ecpg/preproc/ecpg.c | 50 ++++++++++++++++++++++++++-------- src/interfaces/ecpg/preproc/preproc.y | 4 ++- src/interfaces/ecpg/preproc/type.c | 6 +++- src/interfaces/ecpg/preproc/type.h | 1 + src/interfaces/ecpg/preproc/variable.c | 7 +++-- 9 files changed, 67 insertions(+), 21 deletions(-) diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog index df608d25cf..576e6ee03a 100644 --- a/src/interfaces/ecpg/ChangeLog +++ b/src/interfaces/ecpg/ChangeLog @@ -1728,3 +1728,11 @@ Wed Dec 17 16:11:16 CET 2003 - Set pgtypes library to 1.1.0 - Set compat library to 1.1.0 +Mon Jan 26 21:57:14 CET 2004 + + - Issue a warning if a cursor is declared but not opened. + - Fixed prototype for ECPGprepared_statement to not moan about "const + char" + - Fixed parsing of nested structures. + - Added option to parse header files. + diff --git a/src/interfaces/ecpg/ecpglib/execute.c b/src/interfaces/ecpg/ecpglib/execute.c index e540f99e83..758f878ff8 100644 --- a/src/interfaces/ecpg/ecpglib/execute.c +++ b/src/interfaces/ecpg/ecpglib/execute.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.31 2004/01/07 18:56:29 neilc Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/execute.c,v 1.32 2004/01/28 09:52:14 meskes Exp $ */ /* * The aim is to get a simpler inteface to the database routines. @@ -333,7 +333,7 @@ ECPGis_type_an_array(int type, const struct statement * stmt, const struct varia } PQclear(query); ECPGtypeinfocache_push(&(stmt->connection->cache_head), type, isarray, stmt->lineno); - ECPGlog("ECPGexecute line %d: TYPE database: %d C: %d array: %d\n", stmt->lineno, type, var->type, isarray); + ECPGlog("ECPGis_type_an_array line %d: TYPE database: %d C: %d array: %d\n", stmt->lineno, type, var->type, isarray); return isarray; } @@ -356,7 +356,7 @@ ECPGstore_result(const PGresult *results, int act_field, */ if ((var->arrsize > 0 && ntuples > var->arrsize) || (var->ind_arrsize > 0 && ntuples > var->ind_arrsize)) { - ECPGlog("ECPGexecute line %d: Incorrect number of matches: %d don't fit into array of %d\n", + ECPGlog("ECPGstore_result line %d: Incorrect number of matches: %d don't fit into array of %d\n", stmt->lineno, ntuples, var->arrsize); ECPGraise(stmt->lineno, INFORMIX_MODE(stmt->compat)?ECPG_INFORMIX_SUBSELECT_NOT_ONE:ECPG_TOO_MANY_MATCHES, ECPG_SQLSTATE_CARDINALITY_VIOLATION, NULL); return false; diff --git a/src/interfaces/ecpg/ecpglib/prepare.c b/src/interfaces/ecpg/ecpglib/prepare.c index b391327e09..9de1b9bfd8 100644 --- a/src/interfaces/ecpg/ecpglib/prepare.c +++ b/src/interfaces/ecpg/ecpglib/prepare.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/prepare.c,v 1.10 2003/11/29 19:52:08 pgsql Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/ecpglib/prepare.c,v 1.11 2004/01/28 09:52:14 meskes Exp $ */ #define POSTGRES_ECPG_INTERNAL #include "postgres_fe.h" @@ -169,7 +169,7 @@ ECPGdeallocate_all(int lineno) /* return the prepared statement */ char * -ECPGprepared_statement(char *name) +ECPGprepared_statement(const char *name) { struct prepared_statement *this; diff --git a/src/interfaces/ecpg/include/ecpglib.h b/src/interfaces/ecpg/include/ecpglib.h index 317d35e329..6f9938aaf0 100644 --- a/src/interfaces/ecpg/include/ecpglib.h +++ b/src/interfaces/ecpg/include/ecpglib.h @@ -54,7 +54,7 @@ bool ECPGprepare(int, char *, char *); bool ECPGdeallocate(int, int, char *); bool ECPGdeallocate_one(int, char *); bool ECPGdeallocate_all(int); -char *ECPGprepared_statement(char *); +char *ECPGprepared_statement(const char *); void ECPGlog(const char *format,...); char *ECPGerrmsg(void); diff --git a/src/interfaces/ecpg/preproc/ecpg.c b/src/interfaces/ecpg/preproc/ecpg.c index 3c6e1c31b3..e1c99de8d7 100644 --- a/src/interfaces/ecpg/preproc/ecpg.c +++ b/src/interfaces/ecpg/preproc/ecpg.c @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.c,v 1.83 2003/12/18 18:55:09 petere Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/ecpg.c,v 1.84 2004/01/28 09:52:14 meskes Exp $ */ /* New main for ecpg, the PostgreSQL embedded SQL precompiler. */ /* (C) Michael Meskes Feb 5th, 1998 */ @@ -22,6 +22,7 @@ int ret_value = 0, auto_create_c = false, system_includes = false, force_indicator = true; + header_mode = false; enum COMPAT_MODE compat = ECPG_COMPAT_PGSQL; @@ -47,6 +48,7 @@ help(const char *progname) printf(" -d generate parser debug output\n"); #endif printf(" -D SYMBOL define SYMBOL\n"); + printf(" -h parse a header file, this option includes option \"-c\"\n"); printf(" -i parse system include files as well\n"); printf(" -I DIRECTORY search DIRECTORY for include files\n"); printf(" -o OUTFILE write result to OUTFILE\n"); @@ -136,7 +138,7 @@ main(int argc, char *const argv[]) } } - while ((c = getopt(argc, argv, "vcio:I:tD:dC:r:")) != -1) + while ((c = getopt(argc, argv, "vcio:I:tD:dC:r:h")) != -1) { switch (c) { @@ -160,6 +162,10 @@ main(int argc, char *const argv[]) case 'v': verbose = true; break; + case 'h': + header_mode = true; + /* this must include "-c" to make sense */ + /* so do not place a break; here */ case 'c': auto_create_c = true; break; @@ -259,11 +265,11 @@ main(int argc, char *const argv[]) { ptr2ext = input_filename + strlen(input_filename); - /* no extension => add .pgc */ + /* no extension => add .pgc or .pgh */ ptr2ext[0] = '.'; ptr2ext[1] = 'p'; ptr2ext[2] = 'g'; - ptr2ext[3] = 'c'; + ptr2ext[3] = (header_mode == true)? 'h' : 'c'; ptr2ext[4] = '\0'; } @@ -279,8 +285,8 @@ main(int argc, char *const argv[]) output_filename = strdup(input_filename); ptr2ext = strrchr(output_filename, '.'); - /* make extension = .c */ - ptr2ext[1] = 'c'; + /* make extension = .c resp. .h */ + ptr2ext[1] = (header_mode == true)? 'h' : 'c'; ptr2ext[2] = '\0'; yyout = fopen(output_filename, PG_BINARY_W); @@ -383,17 +389,39 @@ main(int argc, char *const argv[]) lex_init(); /* we need several includes */ - fprintf(yyout, "/* Processed by ecpg (%d.%d.%d) */\n/* These include files are added by the preprocessor */\n#include \n#include \n#include \n#include \n#line 1 \"%s\"\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL, input_filename); + /* but not if we are in header mode */ + fprintf(yyout, "/* Processed by ecpg (%d.%d.%d) */\n", MAJOR_VERSION, MINOR_VERSION, PATCHLEVEL); + + if (header_mode == false) + { + fprintf(yyout, "/* These include files are added by the preprocessor */\n#include \n#include \n#include \n#include \n"); - /* add some compatibility headers */ - if (INFORMIX_MODE) - fprintf(yyout, "/* Needed for informix compatibility */\n#include \n"); + /* add some compatibility headers */ + if (INFORMIX_MODE) + fprintf(yyout, "/* Needed for informix compatibility */\n#include \n"); - fprintf(yyout, "/* End of automatic include section */\n"); + fprintf(yyout, "/* End of automatic include section */\n"); + } + fprintf(yyout, "#line 1 \"%s\"\n", input_filename); + /* and parse the source */ yyparse(); + /* check if all cursors were indeed opened */ + for (ptr = cur; ptr != NULL;) + { + char errortext[128]; + + if (!(ptr->opened)) + { + /* Does not really make sense to declare a cursor but not open it */ + snprintf(errortext, sizeof(errortext), "cursor `%s´ has been declared but ot opened\n", ptr->name); + mmerror(PARSE_ERROR, ET_WARNING, errortext); + } + ptr = ptr->next; + } + if (yyin != NULL && yyin != stdin) fclose(yyin); if (out_option == 0 && yyout != stdout) diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index 4d8e3b1726..267950acf9 100644 --- a/src/interfaces/ecpg/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.270 2004/01/21 14:09:34 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.271 2004/01/28 09:52:14 meskes Exp $ */ /* Copyright comment */ %{ @@ -778,6 +778,7 @@ stmt: AlterDatabaseSetStmt { output_statement($1, 0, connection); } if ((ptr = add_additional_variables($1, true)) != NULL) output_statement(mm_strdup(ptr->command), 0, ptr->connection ? mm_strdup(ptr->connection) : NULL); + ptr->opened = true; } | ECPGPrepare { @@ -2780,6 +2781,7 @@ DeclareCursorStmt: DECLARE name cursor_options CURSOR opt_hold FOR SelectStmt this->next = cur; this->name = $2; this->connection = connection; + this->opened = false; this->command = cat_str(7, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for"), $7); this->argsinsert = argsinsert; this->argsresult = argsresult; diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c index e14321d54f..cb0eb27566 100644 --- a/src/interfaces/ecpg/preproc/type.c +++ b/src/interfaces/ecpg/preproc/type.c @@ -47,7 +47,11 @@ ECPGstruct_member_dup(struct ECPGstruct_member * rm) type = ECPGmake_struct_type(rm->type->u.members, rm->type->type, rm->type->struct_sizeof); break; case ECPGt_array: - type = ECPGmake_array_type(ECPGmake_simple_type(rm->type->u.element->type, rm->type->u.element->size), rm->type->size); + /* if this array does contain a struct again, we have to create the struct too */ + if (rm->type->u.element->type == ECPGt_struct) + type = ECPGmake_struct_type(rm->type->u.element->u.members, rm->type->u.element->type, rm->type->u.element->struct_sizeof); + else + type = ECPGmake_array_type(ECPGmake_simple_type(rm->type->u.element->type, rm->type->u.element->size), rm->type->size); break; default: type = ECPGmake_simple_type(rm->type->type, rm->type->size); diff --git a/src/interfaces/ecpg/preproc/type.h b/src/interfaces/ecpg/preproc/type.h index 2dd511ff85..a528b11040 100644 --- a/src/interfaces/ecpg/preproc/type.h +++ b/src/interfaces/ecpg/preproc/type.h @@ -115,6 +115,7 @@ struct cursor char *name; char *command; char *connection; + bool opened; struct arguments *argsinsert; struct arguments *argsresult; struct cursor *next; diff --git a/src/interfaces/ecpg/preproc/variable.c b/src/interfaces/ecpg/preproc/variable.c index be1cb5f0b7..2b98828c79 100644 --- a/src/interfaces/ecpg/preproc/variable.c +++ b/src/interfaces/ecpg/preproc/variable.c @@ -31,9 +31,11 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member * members, in c = *next; *next = '\0'; } + printf("MM: Need to search for %s\n", str); for (; members; members = members->next) { + printf("MM: comparing %s\n§", members->name); if (strcmp(members->name, str) == 0) { if (next == NULL) @@ -104,10 +106,11 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member * members, in return (find_struct_member(name, end, members->type->u.element->u.members, brace_level)); break; case '.': - if (members->type->type != ECPGt_array) + printf("MM: Now searching for %s \n", end); + 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)); + return (find_struct_member(name, end, members->type->u.members, brace_level)); break; default: snprintf(errortext, sizeof(errortext), "incorrectly formed variable %s", name); -- 2.11.0