From a4420c497039c5cba5eae332ccee4830d9879f3c Mon Sep 17 00:00:00 2001 From: Michael Meskes Date: Sun, 9 Dec 2001 15:27:49 +0000 Subject: [PATCH] Fixed several bugs concerning indicators and added error messages instead of segfaults. --- src/interfaces/ecpg/ChangeLog | 5 ++ src/interfaces/ecpg/preproc/extern.h | 4 +- src/interfaces/ecpg/preproc/pgc.l | 30 ++++----- src/interfaces/ecpg/preproc/preproc.y | 116 +++++++++++++++++----------------- src/interfaces/ecpg/preproc/type.c | 47 +++++++------- 5 files changed, 103 insertions(+), 99 deletions(-) diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog index 6f742a65cf..454ddcd2bd 100644 --- a/src/interfaces/ecpg/ChangeLog +++ b/src/interfaces/ecpg/ChangeLog @@ -1170,5 +1170,10 @@ Thu Dec 6 14:02:56 CET 2001 Sat Dec 8 21:35:45 CET 2001 - Fix ecpg to allow pointer to structs. + +Sun Dec 9 16:21:30 CET 2001 + + - Fixed several bugs concerning indicators and added error messages + instead of segfaults. - Set ecpg version to 2.9.0. - Set library version to 3.3.0. diff --git a/src/interfaces/ecpg/preproc/extern.h b/src/interfaces/ecpg/preproc/extern.h index 1fd27655db..985971647b 100644 --- a/src/interfaces/ecpg/preproc/extern.h +++ b/src/interfaces/ecpg/preproc/extern.h @@ -55,7 +55,7 @@ extern int yylex(void); extern void yyerror(char *); extern void *mm_alloc(size_t), *mm_realloc(void *, size_t); extern char *mm_strdup(const char *); -extern void mmerror(enum errortype, char *); +extern void mmerror(int, enum errortype, char *); extern ScanKeyword *ScanECPGKeywordLookup(char *); extern ScanKeyword *ScanCKeywordLookup(char *); extern void output_get_descr_header(char *); @@ -85,3 +85,5 @@ extern ScanKeyword *ScanKeywordLookup(char *text); #define PARSE_ERROR 3 #define INDICATOR_NOT_ARRAY 4 #define OUT_OF_MEMORY 5 +#define INDICATOR_NOT_STRUCT 6 +#define INDICATOR_NOT_SIMPLE 7 diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l index 7b5a2eb392..95898478e2 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.81 2001/09/19 14:09:32 meskes Exp $ + * $Header: /cvsroot/pgsql/src/interfaces/ecpg/preproc/pgc.l,v 1.82 2001/12/09 15:27:49 meskes Exp $ * *------------------------------------------------------------------------- */ @@ -306,7 +306,7 @@ cppline {space}*#(.*\\{line_end})*.* {xcinside} { ECHO; } {op_chars} { ECHO; } -<> { mmerror(ET_ERROR, "Unterminated /* comment"); } +<> { mmerror(PARSE_ERROR, ET_ERROR, "Unterminated /* comment"); } {xbitstart} { BEGIN(xbit); @@ -315,7 +315,7 @@ cppline {space}*#(.*\\{line_end})*.* {xbitstop} { BEGIN(SQL); if (literalbuf[strspn(literalbuf, "01") + 1] != '\0') - mmerror(ET_ERROR, "invalid bit string input."); + mmerror(PARSE_ERROR, ET_ERROR, "invalid bit string input."); yylval.str = literalbuf; return BITCONST; } @@ -328,7 +328,7 @@ cppline {space}*#(.*\\{line_end})*.* {xbitcat} { /* ignore */ } -<> { mmerror(ET_ERROR, "Unterminated bit string"); } +<> { mmerror(PARSE_ERROR, ET_ERROR, "Unterminated bit string"); } {xhstart} { BEGIN(xh); @@ -347,12 +347,12 @@ cppline {space}*#(.*\\{line_end})*.* || val != (long) ((int32) val) #endif ) - mmerror(ET_ERROR, "Bad hexadecimal integer input"); + mmerror(PARSE_ERROR, ET_ERROR, "Bad hexadecimal integer input"); yylval.ival = val; return ICONST; } -<> { mmerror(ET_ERROR, "Unterminated hexadecimal integer"); } +<> { mmerror(PARSE_ERROR, ET_ERROR, "Unterminated hexadecimal integer"); } {xqstart} { state_before = YYSTATE; @@ -373,7 +373,7 @@ cppline {space}*#(.*\\{line_end})*.* /* ignore */ } -<> { mmerror(ET_ERROR, "Unterminated quoted string"); } +<> { mmerror(PARSE_ERROR, ET_ERROR, "Unterminated quoted string"); } {xdstart} { state_before = YYSTATE; @@ -396,7 +396,7 @@ cppline {space}*#(.*\\{line_end})*.* literalbuf, NAMEDATALEN-1, literalbuf); literalbuf[NAMEDATALEN-1] = '\0'; #endif - mmerror(ET_NOTICE, errortext); + mmerror(PARSE_ERROR, ET_NOTICE, errortext); } yylval.str = mm_strdup(literalbuf); @@ -413,7 +413,7 @@ cppline {space}*#(.*\\{line_end})*.* {xdinside} { addlit(yytext, yyleng); } -<> { mmerror(ET_ERROR, "Unterminated quoted identifier"); } +<> { mmerror(PARSE_ERROR, ET_ERROR, "Unterminated quoted identifier"); } {xdstart} { state_before = YYSTATE; BEGIN(xdc); @@ -687,10 +687,10 @@ cppline {space}*#(.*\\{line_end})*.* {exec_sql}{elif}{space_or_nl}* { /* pop stack */ if ( preproc_tos == 0 ) { - mmerror(ET_FATAL, "Missing matching 'EXEC SQL IFDEF / EXEC SQL IFNDEF'"); + mmerror(PARSE_ERROR, ET_FATAL, "Missing matching 'EXEC SQL IFDEF / EXEC SQL IFNDEF'"); } else if ( stacked_if_value[preproc_tos].else_branch ) { - mmerror(ET_FATAL, "Missing 'EXEC SQL ENDIF;'"); + mmerror(PARSE_ERROR, ET_FATAL, "Missing 'EXEC SQL ENDIF;'"); } else { preproc_tos--; @@ -701,7 +701,7 @@ cppline {space}*#(.*\\{line_end})*.* {exec_sql}{else}{space_or_nl}*";" { /* only exec sql endif pops the stack, so take care of duplicated 'else' */ if ( stacked_if_value[preproc_tos].else_branch ) { - mmerror(ET_FATAL, "Duplicated 'EXEC SQL ELSE;'"); + mmerror(PARSE_ERROR, ET_FATAL, "Duplicated 'EXEC SQL ELSE;'"); } else { stacked_if_value[preproc_tos].else_branch = TRUE; @@ -719,7 +719,7 @@ cppline {space}*#(.*\\{line_end})*.* } {exec_sql}{endif}{space_or_nl}*";" { if ( preproc_tos == 0 ) { - mmerror(ET_FATAL, "Unmatched 'EXEC SQL ENDIF;'"); + mmerror(PARSE_ERROR, ET_FATAL, "Unmatched 'EXEC SQL ENDIF;'"); } else { preproc_tos--; @@ -737,7 +737,7 @@ cppline {space}*#(.*\\{line_end})*.* {identifier}{space_or_nl}*";" { if ( preproc_tos >= MAX_NESTED_IF-1 ) { - mmerror(ET_FATAL, "Too many nested 'EXEC SQL IFDEF' conditions"); + mmerror(PARSE_ERROR, ET_FATAL, "Too many nested 'EXEC SQL IFDEF' conditions"); } else { struct _defines *defptr; @@ -864,7 +864,7 @@ cppline {space}*#(.*\\{line_end})*.* if ( preproc_tos > 0 ) { preproc_tos = 0; - mmerror(ET_FATAL, "Missing 'EXEC SQL ENDIF;'"); + mmerror(PARSE_ERROR, ET_FATAL, "Missing 'EXEC SQL ENDIF;'"); } if (yy_buffer == NULL) diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index 7afe02d161..4884ae6b61 100644 --- a/src/interfaces/ecpg/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -31,7 +31,7 @@ struct ECPGtype ecpg_query = {ECPGt_char_variable, 0L, {NULL}}; * Handle parsing errors and warnings */ void -mmerror(enum errortype type, char * error) +mmerror(int error_code, enum errortype type, char * error) { switch(type) { @@ -40,11 +40,11 @@ mmerror(enum errortype type, char * error) break; case ET_ERROR: fprintf(stderr, "%s:%d: ERROR: %s\n", input_filename, yylineno, error); - ret_value = PARSE_ERROR; + ret_value = error_code; break; case ET_FATAL: fprintf(stderr, "%s:%d: ERROR: %s\n", input_filename, yylineno, error); - exit(PARSE_ERROR); + exit(error_code); } } @@ -471,7 +471,7 @@ stmt: AlterSchemaStmt { output_statement($1, 0, connection); } } | ECPGConnect { if (connection) - mmerror(ET_ERROR, "no at option for connect statement.\n"); + mmerror(PARSE_ERROR, ET_ERROR, "no at option for connect statement.\n"); fprintf(yyout, "{ ECPGconnect(__LINE__, %s, %d); ", $1, autocommit); @@ -485,7 +485,7 @@ stmt: AlterSchemaStmt { output_statement($1, 0, connection); } } | ECPGDeallocate { if (connection) - mmerror(ET_ERROR, "no at option for connect statement.\n"); + mmerror(PARSE_ERROR, ET_ERROR, "no at option for connect statement.\n"); fputc('{', yyout); fputs($1, yyout); @@ -501,7 +501,7 @@ stmt: AlterSchemaStmt { output_statement($1, 0, connection); } } | ECPGDisconnect { if (connection) - mmerror(ET_ERROR, "no at option for disconnect statement.\n"); + mmerror(PARSE_ERROR, ET_ERROR, "no at option for disconnect statement.\n"); fprintf(yyout, "{ ECPGdisconnect(__LINE__, %s);", $1); whenever_action(2); @@ -538,7 +538,7 @@ stmt: AlterSchemaStmt { output_statement($1, 0, connection); } if (ptr == NULL) { sprintf(errortext, "trying to open undeclared cursor %s\n", $1); - mmerror(ET_ERROR, errortext); + mmerror(PARSE_ERROR, ET_ERROR, errortext); } /* merge variables given in prepare statement with those given here */ @@ -552,7 +552,7 @@ stmt: AlterSchemaStmt { output_statement($1, 0, connection); } } | ECPGPrepare { if (connection) - mmerror(ET_ERROR, "no at option for set connection statement.\n"); + mmerror(PARSE_ERROR, ET_ERROR, "no at option for set connection statement.\n"); fprintf(yyout, "{ ECPGprepare(__LINE__, %s);", $1); whenever_action(2); @@ -566,7 +566,7 @@ stmt: AlterSchemaStmt { output_statement($1, 0, connection); } } | ECPGSetConnection { if (connection) - mmerror(ET_ERROR, "no at option for set connection statement.\n"); + mmerror(PARSE_ERROR, ET_ERROR, "no at option for set connection statement.\n"); fprintf(yyout, "{ ECPGsetconn(__LINE__, %s);", $1); whenever_action(2); @@ -574,19 +574,19 @@ stmt: AlterSchemaStmt { output_statement($1, 0, connection); } } | ECPGTypedef { if (connection) - mmerror(ET_ERROR, "no at option for typedef statement.\n"); + mmerror(PARSE_ERROR, ET_ERROR, "no at option for typedef statement.\n"); output_simple_statement($1); } | ECPGVar { if (connection) - mmerror(ET_ERROR, "no at option for var statement.\n"); + mmerror(PARSE_ERROR, ET_ERROR, "no at option for var statement.\n"); output_simple_statement($1); } | ECPGWhenever { if (connection) - mmerror(ET_ERROR, "no at option for whenever statement.\n"); + mmerror(PARSE_ERROR, ET_ERROR, "no at option for whenever statement.\n"); output_simple_statement($1); } @@ -831,7 +831,7 @@ var_value: opt_boolean { $$ = $1; } | AllConst { $$ = $1; } | name_list { if (strlen($1) == 0) - mmerror(ET_ERROR, "SET must have at least one argument."); + mmerror(PARSE_ERROR, ET_ERROR, "SET must have at least one argument."); $$ = $1; } @@ -1098,11 +1098,11 @@ OptTemp: TEMPORARY { $$ = make_str("temporary"); } | LOCAL TEMPORARY { $$ = make_str("local temporary"); } | LOCAL TEMP { $$ = make_str("local temp"); } | GLOBAL TEMPORARY { - mmerror(ET_NOTICE, "Currently unsupported CREATE TABLE / GLOBAL TEMPORARY will be passed to backend"); + mmerror(PARSE_ERROR, ET_NOTICE, "Currently unsupported CREATE TABLE / GLOBAL TEMPORARY will be passed to backend"); $$ = make_str("global temporary"); } | GLOBAL TEMP { - mmerror(ET_NOTICE, "Currently unsupported CREATE TABLE / GLOBAL TEMP will be passed to backend"); + mmerror(PARSE_ERROR, ET_NOTICE, "Currently unsupported CREATE TABLE / GLOBAL TEMP will be passed to backend"); $$ = make_str("global temp"); } | /*EMPTY*/ { $$ = EMPTY; } @@ -1128,7 +1128,7 @@ columnDef: ColId Typename ColQualList opt_collate if (strlen($4) > 0) { sprintf(errortext, "Currently unsupported CREATE TABLE / COLLATE %s will be passed to backend", $4); - mmerror(ET_NOTICE, errortext); + mmerror(PARSE_ERROR, ET_NOTICE, errortext); } $$ = cat_str(4, $1, $2, $3, $4); } @@ -1243,7 +1243,7 @@ key_match: MATCH FULL } | MATCH PARTIAL { - mmerror(ET_NOTICE, "Currently unsupported FOREIGN KEY/MATCH PARTIAL will be passed to backend"); + mmerror(PARSE_ERROR, ET_NOTICE, "Currently unsupported FOREIGN KEY/MATCH PARTIAL will be passed to backend"); $$ = make_str("match partial"); } | /*EMPTY*/ @@ -1289,7 +1289,7 @@ CreateAsStmt: CREATE OptTemp TABLE relation_name OptCreateAs AS { FoundInto = 0; } SelectStmt { if (FoundInto == 1) - mmerror(ET_ERROR, "CREATE TABLE / AS SELECT may not specify INTO"); + mmerror(PARSE_ERROR, ET_ERROR, "CREATE TABLE / AS SELECT may not specify INTO"); $$ = cat_str(7, make_str("create"), $2, make_str("table"), $4, $5, make_str("as"), $8); } @@ -1474,7 +1474,7 @@ ConstraintAttributeSpec: ConstraintDeferrabilitySpec | ConstraintDeferrabilitySpec ConstraintTimeSpec { if (strcmp($1, "deferrable") != 0 && strcmp($2, "initially deferrable") == 0 ) - mmerror(ET_ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE"); + mmerror(PARSE_ERROR, ET_ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE"); $$ = cat2_str($1, $2); } @@ -1483,7 +1483,7 @@ ConstraintAttributeSpec: ConstraintDeferrabilitySpec | ConstraintTimeSpec ConstraintDeferrabilitySpec { if (strcmp($2, "deferrable") != 0 && strcmp($1, "initially deferrable") == 0 ) - mmerror(ET_ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE"); + mmerror(PARSE_ERROR, ET_ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE"); $$ = cat2_str($1, $2); } @@ -1592,7 +1592,7 @@ TruncateStmt: TRUNCATE opt_table relation_name FetchStmt: FETCH direction fetch_how_many from_in name ecpg_into { if (strcmp($2, "relative") == 0 && atol($3) == 0L) - mmerror(ET_ERROR, "FETCH/RELATIVE at current position is not supported"); + mmerror(PARSE_ERROR, ET_ERROR, "FETCH/RELATIVE at current position is not supported"); $$ = cat_str(5, make_str("fetch"), $2, $3, $4, $5); } @@ -1638,7 +1638,7 @@ direction: FORWARD { $$ = make_str("forward"); } | BACKWARD { $$ = make_str("backward"); } | RELATIVE { $$ = make_str("relative"); } | ABSOLUTE { - mmerror(ET_NOTICE, "Currently unsupported FETCH/ABSOLUTE will be passed to backend, backend will use RELATIVE"); + mmerror(PARSE_ERROR, ET_NOTICE, "Currently unsupported FETCH/ABSOLUTE will be passed to backend, backend will use RELATIVE"); $$ = make_str("absolute"); } ; @@ -1795,7 +1795,7 @@ grantee_list: grantee { $$ = $1; } opt_with_grant: WITH GRANT OPTION { - mmerror(ET_NOTICE, "Currently unsupported GRANT/WITH GRANT OPTION will be passed to backend"); + mmerror(PARSE_ERROR, ET_NOTICE, "Currently unsupported GRANT/WITH GRANT OPTION will be passed to backend"); $$ = make_str("with grant option"); } | /*EMPTY*/ { $$ = EMPTY; } @@ -1947,12 +1947,12 @@ func_arg: opt_arg func_type opt_arg: IN { $$ = make_str("in"); } | OUT { - mmerror(ET_NOTICE, "Currently unsupported CREATE FUNCTION/OUT will be passed to backend"); + mmerror(PARSE_ERROR, ET_NOTICE, "Currently unsupported CREATE FUNCTION/OUT will be passed to backend"); $$ = make_str("out"); } | INOUT { - mmerror(ET_NOTICE, "Currently unsupported CREATE FUNCTION/INOUT will be passed to backend"); + mmerror(PARSE_ERROR, ET_NOTICE, "Currently unsupported CREATE FUNCTION/INOUT will be passed to backend"); $$ = make_str("inout"); } @@ -2021,7 +2021,7 @@ RemoveOperStmt: DROP OPERATOR all_Op '(' oper_argtypes ')' oper_argtypes: Typename { - mmerror(ET_ERROR, "parser: argument type missing (use NONE for unary operators)"); + mmerror(PARSE_ERROR, ET_ERROR, "parser: argument type missing (use NONE for unary operators)"); } | Typename ',' Typename { $$ = cat_str(3, $1, make_str(","), $3); } @@ -2192,7 +2192,7 @@ opt_trans: WORK { $$ = ""; } opt_chain: AND NO CHAIN { $$ = make_str("and no chain"); } | AND CHAIN { - mmerror(ET_NOTICE, "Currently unsupported COMMIT/CHAIN will be passed to backend"); + mmerror(PARSE_ERROR, ET_NOTICE, "Currently unsupported COMMIT/CHAIN will be passed to backend"); $$ = make_str("and chain"); } @@ -2505,7 +2505,7 @@ CursorStmt: DECLARE name opt_cursor CURSOR FOR SelectStmt { /* re-definition is a bug */ sprintf(errortext, "cursor %s already defined", $2); - mmerror(ET_ERROR, errortext); + mmerror(PARSE_ERROR, ET_ERROR, errortext); } } @@ -2637,12 +2637,12 @@ OptTempTableName: TEMPORARY opt_table relation_name } | GLOBAL TEMPORARY opt_table relation_name { - mmerror(ET_NOTICE, "Currently unsupported CREATE TABLE / GLOBAL TEMPORARY will be passed to backend"); + mmerror(PARSE_ERROR, ET_NOTICE, "Currently unsupported CREATE TABLE / GLOBAL TEMPORARY will be passed to backend"); $$ = cat_str(3, make_str("global temporary"), $3, $4); } | GLOBAL TEMP opt_table relation_name { - mmerror(ET_NOTICE, "Currently unsupported CREATE TABLE / GLOBAL TEMP will be passed to backend"); + mmerror(PARSE_ERROR, ET_NOTICE, "Currently unsupported CREATE TABLE / GLOBAL TEMP will be passed to backend"); $$ = cat_str(3, make_str("global temp"), $3, $4); } | TABLE relation_name @@ -2701,7 +2701,7 @@ select_limit: LIMIT select_limit_value OFFSET select_offset_value | LIMIT select_limit_value ',' select_offset_value { $$ = cat_str(4, make_str("limit"), $2, make_str(","), $4); } /* enable this in 7.3, bjm 2001-10-22 - { mmerror(ET_NOTICE, "No longer supported LIMIT #,# syntax passed to backend."); } + { mmerror(PARSE_ERROR, ET_NOTICE, "No longer supported LIMIT #,# syntax passed to backend."); } */ ; @@ -2711,7 +2711,7 @@ opt_select_limit: select_limit { $$ = $1; } select_limit_value: PosIntConst { if (atoi($1) < 0) - mmerror(ET_ERROR, "LIMIT must not be negative"); + mmerror(PARSE_ERROR, ET_ERROR, "LIMIT must not be negative"); $$ = $1; } | ALL { $$ = make_str("all"); } @@ -2720,7 +2720,7 @@ select_limit_value: PosIntConst { select_offset_value: PosIntConst { if (atoi($1) < 0) - mmerror(ET_ERROR, "OFFSET must not be negative"); + mmerror(PARSE_ERROR, ET_ERROR, "OFFSET must not be negative"); $$ = $1; } | PARAM { $$ = make_name(); } @@ -2809,7 +2809,7 @@ table_ref: relation_expr } | select_with_parens { - mmerror(ET_ERROR, "sub-SELECT in FROM must have an alias"); + mmerror(PARSE_ERROR, ET_ERROR, "sub-SELECT in FROM must have an alias"); } | select_with_parens alias_clause { @@ -3838,14 +3838,14 @@ UserId: ColId { $$ = $1;}; SpecialRuleRelation: OLD { if (!QueryIsRule) - mmerror(ET_ERROR, "OLD used in non-rule query"); + mmerror(PARSE_ERROR, ET_ERROR, "OLD used in non-rule query"); $$ = make_str("old"); } | NEW { if (!QueryIsRule) - mmerror(ET_ERROR, "NEW used in non-rule query"); + mmerror(PARSE_ERROR, ET_ERROR, "NEW used in non-rule query"); $$ = make_str("new"); } @@ -3878,7 +3878,7 @@ connection_target: database_name opt_server opt_port if (strlen($2) > 0 && *($2) != '@') { sprintf(errortext, "Expected '@', found '%s'", $2); - mmerror(ET_ERROR, errortext); + mmerror(PARSE_ERROR, ET_ERROR, errortext); } $$ = make3_str(make_str("\""), make3_str($1, $2, $3), make_str("\"")); @@ -3889,13 +3889,13 @@ connection_target: database_name opt_server opt_port if (strncmp($1, "unix:postgresql", strlen("unix:postgresql")) != 0 && strncmp($1, "tcp:postgresql", strlen("tcp:postgresql")) != 0) { sprintf(errortext, "only protocols 'tcp' and 'unix' and database type 'postgresql' are supported"); - mmerror(ET_ERROR, errortext); + mmerror(PARSE_ERROR, ET_ERROR, errortext); } if (strncmp($3, "//", strlen("//")) != 0) { sprintf(errortext, "Expected '://', found '%s'", $3); - mmerror(ET_ERROR, errortext); + mmerror(PARSE_ERROR, ET_ERROR, errortext); } if (strncmp($1, "unix", strlen("unix")) == 0 && @@ -3903,7 +3903,7 @@ connection_target: database_name opt_server opt_port strncmp($3 + strlen("//"), "127.0.0.1", strlen("127.0.0.1")) != 0) { sprintf(errortext, "unix domain sockets only work on 'localhost' but not on '%9.9s'", $3 + strlen("//")); - mmerror(ET_ERROR, errortext); + mmerror(PARSE_ERROR, ET_ERROR, errortext); } $$ = make3_str(make3_str(make_str("\""), $1, make_str(":")), $3, make3_str(make3_str($4, make_str("/"), $6), $7, make_str("\""))); @@ -3935,13 +3935,13 @@ db_prefix: ident cvariable if (strcmp($2, "postgresql") != 0 && strcmp($2, "postgres") != 0) { sprintf(errortext, "Expected 'postgresql', found '%s'", $2); - mmerror(ET_ERROR, errortext); + mmerror(PARSE_ERROR, ET_ERROR, errortext); } if (strcmp($1, "tcp") != 0 && strcmp($1, "unix") != 0) { sprintf(errortext, "Illegal connection type %s", $1); - mmerror(ET_ERROR, errortext); + mmerror(PARSE_ERROR, ET_ERROR, errortext); } $$ = make3_str($1, make_str(":"), $2); @@ -3952,7 +3952,7 @@ server: Op server_name if (strcmp($1, "@") != 0 && strcmp($1, "//") != 0) { sprintf(errortext, "Expected '@' or '://', found '%s'", $1); - mmerror(ET_ERROR, errortext); + mmerror(PARSE_ERROR, ET_ERROR, errortext); } $$ = make2_str($1, $2); @@ -4037,7 +4037,7 @@ char_variable: cvariable $$ = make2_str($1, make_str(".arr")); break; default: - mmerror(ET_ERROR, "invalid datatype"); + mmerror(PARSE_ERROR, ET_ERROR, "invalid datatype"); break; } } @@ -4045,12 +4045,12 @@ char_variable: cvariable opt_options: Op ColId { if (strlen($1) == 0) - mmerror(ET_ERROR, "incomplete statement"); + mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement"); if (strcmp($1, "?") != 0) { sprintf(errortext, "unrecognised token '%s'", $1); - mmerror(ET_ERROR, errortext); + mmerror(PARSE_ERROR, ET_ERROR, errortext); } $$ = make2_str(make_str("?"), $2); @@ -4073,7 +4073,7 @@ ECPGCursorStmt: DECLARE name opt_cursor CURSOR FOR ident { /* re-definition is a bug */ sprintf(errortext, "cursor %s already defined", $2); - mmerror(ET_ERROR, errortext); + mmerror(PARSE_ERROR, ET_ERROR, errortext); } } @@ -4268,7 +4268,7 @@ s_struct: SQL_STRUCT opt_symbol { struct_member_list[struct_level++] = NULL; if (struct_level >= STRUCT_DEPTH) - mmerror(ET_ERROR, "Too many levels in nested structure definition"); + mmerror(PARSE_ERROR, ET_ERROR, "Too many levels in nested structure definition"); $$ = cat2_str(make_str("struct"), $2); }; @@ -4277,7 +4277,7 @@ s_union: UNION opt_symbol { struct_member_list[struct_level++] = NULL; if (struct_level >= STRUCT_DEPTH) - mmerror(ET_ERROR, "Too many levels in nested structure definition"); + mmerror(PARSE_ERROR, ET_ERROR, "Too many levels in nested structure definition"); $$ = cat2_str(make_str("union"), $2); }; @@ -4386,7 +4386,7 @@ variable: opt_pointer ECPGColLabel opt_array_bounds opt_initializer sprintf(ascii_len, "%d", length); if (length == 0) - mmerror(ET_ERROR, "pointer to varchar are not implemented"); + mmerror(PARSE_ERROR, ET_ERROR, "pointer to varchar are not implemented"); if (dimension == 0) $$ = cat_str(7, mm_strdup(actual_storage[struct_level]), make2_str(make_str(" struct varchar_"), mm_strdup($2)), make_str(" { int len; char arr["), mm_strdup(ascii_len), make_str("]; } *"), mm_strdup($2), $4); @@ -4615,7 +4615,7 @@ ECPGGetDescriptor: SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar SQL_VALUE cvari ECPGRelease: TransactionStmt SQL_RELEASE { if (strcmp($1, "begin") == 0) - mmerror(ET_ERROR, "RELEASE does not make sense when beginning a transaction"); + mmerror(PARSE_ERROR, ET_ERROR, "RELEASE does not make sense when beginning a transaction"); fprintf(yyout, "ECPGtrans(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1); @@ -4669,7 +4669,7 @@ ECPGTypedef: TYPE_P $5.type_enum == ECPGt_union) && initializer == 1) { - mmerror(ET_ERROR, "Initializer not allowed in EXEC SQL VAR command"); + mmerror(PARSE_ERROR, ET_ERROR, "Initializer not allowed in EXEC SQL VAR command"); } else { @@ -4679,7 +4679,7 @@ ECPGTypedef: TYPE_P { /* re-definition is a bug */ sprintf(errortext, "Type %s already defined", $3); - mmerror(ET_ERROR, errortext); + mmerror(PARSE_ERROR, ET_ERROR, errortext); } } @@ -4702,7 +4702,7 @@ ECPGTypedef: TYPE_P $5.type_enum != ECPGt_char && $5.type_enum != ECPGt_unsigned_char && this->type->type_index >= 0) - mmerror(ET_ERROR, "No multi-dimensional array support for simple data types"); + mmerror(PARSE_ERROR, ET_ERROR, "No multi-dimensional array support for simple data types"); types = this; } @@ -4772,7 +4772,7 @@ ECPGVar: SQL_VAR $5.type_enum == ECPGt_union) && initializer == 1) { - mmerror(ET_ERROR, "Initializer not allowed in EXEC SQL VAR command"); + mmerror(PARSE_ERROR, ET_ERROR, "Initializer not allowed in EXEC SQL VAR command"); } else { @@ -4804,7 +4804,7 @@ ECPGVar: SQL_VAR break; default: if (length >= 0) - mmerror(ET_ERROR, "No multi-dimensional array support for simple data types"); + mmerror(PARSE_ERROR, ET_ERROR, "No multi-dimensional array support for simple data types"); if (dimension < 0) type = ECPGmake_simple_type($5.type_enum, 1); @@ -5338,7 +5338,7 @@ coutputvariable: cvariable indicator civarind: cvariable indicator { if ($2 != NULL && (find_variable($2))->type->typ == ECPGt_array) - mmerror(ET_ERROR, "arrays of indicators are not allowed on input"); + mmerror(PARSE_ERROR, ET_ERROR, "arrays of indicators are not allowed on input"); add_variable(&argsinsert, find_variable($1), ($2 == NULL) ? &no_indicator : find_variable($2)); }; @@ -5472,5 +5472,5 @@ void yyerror( char * error) { char buf[1024]; snprintf(buf,sizeof buf,"%s at or near \"%s\"",error,yytext); buf[sizeof(buf)-1]=0; - mmerror(ET_ERROR, buf); + mmerror(PARSE_ERROR, ET_ERROR, buf); } diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c index c0cfad9ff2..8d2b7a5925 100644 --- a/src/interfaces/ecpg/preproc/type.c +++ b/src/interfaces/ecpg/preproc/type.c @@ -2,6 +2,8 @@ #include "extern.h" +#define indicator_set ind_typ != NULL && ind_typ->typ != ECPGt_NO_INDICATOR + struct ECPGstruct_member struct_no_indicator = {"no_indicator", &ecpg_no_indicator, NULL}; /* malloc + error check */ @@ -11,10 +13,7 @@ mm_alloc(size_t size) void *ptr = malloc(size); if (ptr == NULL) - { - fprintf(stderr, "Out of memory\n"); - exit(OUT_OF_MEMORY); - } + mmerror(OUT_OF_MEMORY, ET_FATAL, "Out of memory\n"); return ptr; } @@ -26,11 +25,8 @@ mm_strdup(const char *string) char *new = strdup(string); if (new == NULL) - { - fprintf(stderr, "Out of memory\n"); - exit(OUT_OF_MEMORY); - } - + mmerror(OUT_OF_MEMORY, ET_FATAL, "Out of memory\n"); + return new; } @@ -202,23 +198,19 @@ static void ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, static void ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, long arrsiz, struct ECPGtype * typ, struct ECPGtype * ind_typ, const char *offset, const char *prefix, const char *ind_prefix); - void ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *ind_name, struct ECPGtype * ind_typ, const char *prefix, const char *ind_prefix) { -/* if (ind_typ == NULL) - { - ind_typ = &ecpg_no_indicator; - ind_name = "no_indicator"; - }*/ - switch (typ->typ) { case ECPGt_array: + if (indicator_set && ind_typ->typ != ECPGt_array) + mmerror(INDICATOR_NOT_ARRAY, ET_FATAL, "Indicator for array/pointer has to be array/pointer.\n"); + switch (typ->u.element->typ) { case ECPGt_array: - yyerror("No nested arrays allowed (except strings)"); /* array of array */ + mmerror(PARSE_ERROR, ET_ERROR, "No nested arrays allowed (except strings)"); /* array of array */ break; case ECPGt_struct: case ECPGt_union: @@ -235,33 +227,38 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in if (ind_typ->typ == ECPGt_NO_INDICATOR) ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, -1, NULL, ind_prefix); else - { - if (ind_typ->typ != ECPGt_array) - { - fprintf(stderr, "Indicator for an array has to be array too.\n"); - exit(INDICATOR_NOT_ARRAY); - } ECPGdump_a_simple(o, ind_name, ind_typ->u.element->typ, ind_typ->u.element->size, ind_typ->size, NULL, prefix); - } } } break; case ECPGt_struct: + if (indicator_set && ind_typ->typ != ECPGt_struct) + mmerror(INDICATOR_NOT_STRUCT, ET_FATAL, "Indicator for struct has to be struct.\n"); + ECPGdump_a_struct(o, name, ind_name, 1, typ, ind_typ, NULL, prefix, ind_prefix); break; case ECPGt_union: /* cannot dump a complete union */ yyerror("Type of union has to be specified"); break; case ECPGt_char_variable: + if (indicator_set && (ind_typ->typ == ECPGt_struct || ind_typ->typ == ECPGt_array)) + mmerror(INDICATOR_NOT_SIMPLE, ET_FATAL, "Indicator for simple datatype has to be simple.\n"); + ECPGdump_a_simple(o, name, typ->typ, 1, 1, NULL, prefix); ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, -1, NULL, ind_prefix); break; case ECPGt_descriptor: + if (indicator_set && (ind_typ->typ == ECPGt_struct || ind_typ->typ == ECPGt_array)) + mmerror(INDICATOR_NOT_SIMPLE, ET_FATAL, "Indicator for simple datatype has to be simple.\n"); + ECPGdump_a_simple(o, name, typ->typ, 0, -1, NULL, prefix); ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, -1, NULL, ind_prefix); break; default: + if (indicator_set && (ind_typ->typ == ECPGt_struct || ind_typ->typ == ECPGt_array)) + mmerror(INDICATOR_NOT_SIMPLE, ET_FATAL, "Indicator for simple datatype has to be simple.\n"); + ECPGdump_a_simple(o, name, typ->typ, typ->size, -1, NULL, prefix); if (ind_typ != NULL) ECPGdump_a_simple(o, ind_name, ind_typ->typ, ind_typ->size, -1, NULL, ind_prefix); @@ -361,7 +358,7 @@ ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, long arrsiz, struct ECPGstruct_member *p, *ind_p = NULL; char obuf[BUFSIZ]; - char pbuf[BUFSIZ*2], + char pbuf[BUFSIZ], ind_pbuf[BUFSIZ]; const char *offset; -- 2.11.0