From: Tom Lane Date: Mon, 14 Oct 2024 17:55:08 +0000 (-0400) Subject: ecpg: improve preprocessor's memory management. X-Git-Tag: REL_18_BETA1~1715 X-Git-Url: http://git.postgresql.org/gitweb/?a=commitdiff_plain;h=1acd0f55274fab8c936779a0f2b738f6005cc48f;p=postgresql.git ecpg: improve preprocessor's memory management. Invent a notion of "local" storage that will automatically be reclaimed at the end of each statement. Use this for location strings as well as other visibly short-lived data within the parser. Also, make cat_str and make_str return local storage and not free their inputs, which allows dispensing with a whole lot of retail mm_strdup calls. We do have to add some new ones in places where a local-lifetime string needs to be added to a longer-lived data structure, but on balance there are a lot less mm_strdup calls than before. In hopes of flushing out places where changes were necessary, I changed YYLTYPE from "char *" to "const char *", which forced const-ification of various function arguments that probably should've been like that all along. This still leaks somewhat more memory than v17, but that will be cleaned up in future commits. Discussion: https://postgr.es/m/2011420.1713493114@sss.pgh.pa.us --- diff --git a/src/interfaces/ecpg/preproc/descriptor.c b/src/interfaces/ecpg/preproc/descriptor.c index f4b1878289c..9b87d07d09f 100644 --- a/src/interfaces/ecpg/preproc/descriptor.c +++ b/src/interfaces/ecpg/preproc/descriptor.c @@ -18,13 +18,12 @@ static struct assignment *assignments; void -push_assignment(char *var, enum ECPGdtype value) +push_assignment(const char *var, enum ECPGdtype value) { struct assignment *new = (struct assignment *) mm_alloc(sizeof(struct assignment)); new->next = assignments; - new->variable = mm_alloc(strlen(var) + 1); - strcpy(new->variable, var); + new->variable = mm_strdup(var); new->value = value; assignments = new; } @@ -73,7 +72,7 @@ ECPGnumeric_lvalue(char *name) static struct descriptor *descriptors; void -add_descriptor(char *name, char *connection) +add_descriptor(const char *name, const char *connection) { struct descriptor *new; @@ -83,20 +82,16 @@ add_descriptor(char *name, char *connection) new = (struct descriptor *) mm_alloc(sizeof(struct descriptor)); new->next = descriptors; - new->name = mm_alloc(strlen(name) + 1); - strcpy(new->name, name); + new->name = mm_strdup(name); if (connection) - { - new->connection = mm_alloc(strlen(connection) + 1); - strcpy(new->connection, connection); - } + new->connection = mm_strdup(connection); else - new->connection = connection; + new->connection = NULL; descriptors = new; } void -drop_descriptor(char *name, char *connection) +drop_descriptor(const char *name, const char *connection) { struct descriptor *i; struct descriptor **lastptr = &descriptors; @@ -126,9 +121,8 @@ drop_descriptor(char *name, char *connection) mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to the default connection does not exist", name); } -struct descriptor - * -lookup_descriptor(char *name, char *connection) +struct descriptor * +lookup_descriptor(const char *name, const char *connection) { struct descriptor *i; @@ -159,7 +153,7 @@ lookup_descriptor(char *name, char *connection) } void -output_get_descr_header(char *desc_name) +output_get_descr_header(const char *desc_name) { struct assignment *results; @@ -178,7 +172,7 @@ output_get_descr_header(char *desc_name) } void -output_get_descr(char *desc_name, char *index) +output_get_descr(const char *desc_name, const char *index) { struct assignment *results; @@ -211,7 +205,7 @@ output_get_descr(char *desc_name, char *index) } void -output_set_descr_header(char *desc_name) +output_set_descr_header(const char *desc_name) { struct assignment *results; @@ -272,7 +266,7 @@ descriptor_item_name(enum ECPGdtype itemcode) } void -output_set_descr(char *desc_name, char *index) +output_set_descr(const char *desc_name, const char *index) { struct assignment *results; diff --git a/src/interfaces/ecpg/preproc/ecpg.addons b/src/interfaces/ecpg/preproc/ecpg.addons index 24ee54554e3..9c120fead24 100644 --- a/src/interfaces/ecpg/preproc/ecpg.addons +++ b/src/interfaces/ecpg/preproc/ecpg.addons @@ -45,18 +45,16 @@ ECPG: stmtExecuteStmt block else { /* case of ecpg_ident or CSTRING */ - char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); - char *str = mm_strdup($1.name + 1); + char length[32]; + char *str; - /* - * It must be cut off double quotation because new_variable() - * double-quotes. - */ + /* Remove double quotes from name */ + str = loc_strdup($1.name + 1); str[strlen(str) - 1] = '\0'; - sprintf(length, "%zu", strlen(str)); + snprintf(length, sizeof(length), "%zu", strlen(str)); add_variable_to_tail(&argsinsert, new_variable(str, ECPGmake_simple_type(ECPGt_const, length, 0), 0), &no_indicator); } - output_statement(cat_str(3, mm_strdup("execute"), mm_strdup("$0"), $1.type), 0, ECPGst_exec_with_exprlist); + output_statement(cat_str(3, "execute", "$0", $1.type), 0, ECPGst_exec_with_exprlist); } } ECPG: stmtPrepareStmt block @@ -66,7 +64,7 @@ ECPG: stmtPrepareStmt block output_prepare_statement($1.name, $1.stmt); else if (strlen($1.type) == 0) { - char *stmt = cat_str(3, mm_strdup("\""), $1.stmt, mm_strdup("\"")); + char *stmt = cat_str(3, "\"", $1.stmt, "\""); output_prepare_statement($1.name, stmt); } @@ -77,18 +75,16 @@ ECPG: stmtPrepareStmt block add_variable_to_tail(&argsinsert, find_variable($1.name), &no_indicator); else { - char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); - char *str = mm_strdup($1.name + 1); + char length[32]; + char *str; - /* - * It must be cut off double quotation because new_variable() - * double-quotes. - */ + /* Remove double quotes from name */ + str = loc_strdup($1.name + 1); str[strlen(str) - 1] = '\0'; - sprintf(length, "%zu", strlen(str)); + snprintf(length, sizeof(length), "%zu", strlen(str)); add_variable_to_tail(&argsinsert, new_variable(str, ECPGmake_simple_type(ECPGt_const, length, 0), 0), &no_indicator); } - output_statement(cat_str(5, mm_strdup("prepare"), mm_strdup("$0"), $1.type, mm_strdup("as"), $1.stmt), 0, ECPGst_prepare); + output_statement(cat_str(5, "prepare", "$0", $1.type, "as", $1.stmt), 0, ECPGst_prepare); } } ECPG: stmtTransactionStmt block @@ -142,8 +138,6 @@ ECPG: stmtViewStmt rule fputs("ECPGt_EORT);", base_yyout); fprintf(base_yyout, "}"); output_line_number(); - - free($1.stmt_name); } | ECPGDisconnect { @@ -175,8 +169,6 @@ ECPG: stmtViewStmt rule { lookup_descriptor($1.name, connection); output_get_descr($1.name, $1.str); - free($1.name); - free($1.str); } | ECPGGetDescriptorHeader { @@ -190,7 +182,7 @@ ECPG: stmtViewStmt rule if ((ptr = add_additional_variables(@1, true)) != NULL) { connection = ptr->connection ? mm_strdup(ptr->connection) : NULL; - output_statement(mm_strdup(ptr->command), 0, ECPGst_normal); + output_statement(ptr->command, 0, ECPGst_normal); ptr->opened = true; } } @@ -211,8 +203,6 @@ ECPG: stmtViewStmt rule { lookup_descriptor($1.name, connection); output_set_descr($1.name, $1.str); - free($1.name); - free($1.str); } | ECPGSetDescriptorHeader { @@ -243,9 +233,9 @@ ECPG: stmtViewStmt rule } ECPG: where_or_current_clauseWHERECURRENT_POFcursor_name block { - char *cursor_marker = @4[0] == ':' ? mm_strdup("$0") : @4; + const char *cursor_marker = @4[0] == ':' ? "$0" : @4; - @$ = cat_str(2, mm_strdup("where current of"), cursor_marker); + @$ = cat_str(2, "where current of", cursor_marker); } ECPG: CopyStmtCOPYopt_binaryqualified_nameopt_column_listcopy_fromopt_programcopy_file_namecopy_delimiteropt_withcopy_optionswhere_clause addon if (strcmp(@6, "from") == 0 && @@ -253,21 +243,21 @@ ECPG: CopyStmtCOPYopt_binaryqualified_nameopt_column_listcopy_fromopt_programcop mmerror(PARSE_ERROR, ET_WARNING, "COPY FROM STDIN is not implemented"); ECPG: var_valueNumericOnly addon if (@1[0] == '$') - @$ = mm_strdup("$0"); + @$ = "$0"; ECPG: fetch_argscursor_name addon struct cursor *ptr = add_additional_variables(@1, false); if (ptr->connection) connection = mm_strdup(ptr->connection); if (@1[0] == ':') - @$ = mm_strdup("$0"); + @$ = "$0"; ECPG: fetch_argsfrom_incursor_name addon struct cursor *ptr = add_additional_variables(@2, false); if (ptr->connection) connection = mm_strdup(ptr->connection); if (@2[0] == ':') - @$ = cat2_str(mm_strdup(@1), mm_strdup("$0")); + @$ = cat2_str(@1, "$0"); ECPG: fetch_argsNEXTopt_from_incursor_name addon ECPG: fetch_argsPRIORopt_from_incursor_name addon ECPG: fetch_argsFIRST_Popt_from_incursor_name addon @@ -278,7 +268,7 @@ ECPG: fetch_argsALLopt_from_incursor_name addon if (ptr->connection) connection = mm_strdup(ptr->connection); if (@3[0] == ':') - @$ = cat_str(3, mm_strdup(@1), mm_strdup(@2), mm_strdup("$0")); + @$ = cat_str(3, @1, @2, "$0"); ECPG: fetch_argsSignedIconstopt_from_incursor_name addon struct cursor *ptr = add_additional_variables(@3, false); bool replace = false; @@ -287,16 +277,16 @@ ECPG: fetch_argsSignedIconstopt_from_incursor_name addon connection = mm_strdup(ptr->connection); if (@3[0] == ':') { - @3 = mm_strdup("$0"); + @3 = "$0"; replace = true; } if (@1[0] == '$') { - @1 = mm_strdup("$0"); + @1 = "$0"; replace = true; } if (replace) - @$ = cat_str(3, mm_strdup(@1), mm_strdup(@2), mm_strdup(@3)); + @$ = cat_str(3, @1, @2, @3); ECPG: fetch_argsFORWARDALLopt_from_incursor_name addon ECPG: fetch_argsBACKWARDALLopt_from_incursor_name addon struct cursor *ptr = add_additional_variables(@4, false); @@ -304,7 +294,7 @@ ECPG: fetch_argsBACKWARDALLopt_from_incursor_name addon if (ptr->connection) connection = mm_strdup(ptr->connection); if (@4[0] == ':') - @$ = cat_str(4, mm_strdup(@1), mm_strdup(@2), mm_strdup(@3), mm_strdup("$0")); + @$ = cat_str(4, @1, @2, @3, "$0"); ECPG: fetch_argsABSOLUTE_PSignedIconstopt_from_incursor_name addon ECPG: fetch_argsRELATIVE_PSignedIconstopt_from_incursor_name addon ECPG: fetch_argsFORWARDSignedIconstopt_from_incursor_name addon @@ -316,20 +306,20 @@ ECPG: fetch_argsBACKWARDSignedIconstopt_from_incursor_name addon connection = mm_strdup(ptr->connection); if (@4[0] == ':') { - @4 = mm_strdup("$0"); + @4 = "$0"; replace = true; } if (@2[0] == '$') { - @2 = mm_strdup("$0"); + @2 = "$0"; replace = true; } if (replace) - @$ = cat_str(4, mm_strdup(@1), mm_strdup(@2), mm_strdup(@3), mm_strdup(@4)); + @$ = cat_str(4, @1, @2, @3, @4); ECPG: cursor_namename block | char_civar { - char *curname = mm_alloc(strlen(@1) + 2); + char *curname = loc_alloc(strlen(@1) + 2); sprintf(curname, ":%s", @1); @$ = curname; @@ -367,7 +357,7 @@ ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectSt { struct cursor *ptr, *this; - char *cursor_marker = @2[0] == ':' ? mm_strdup("$0") : mm_strdup(@2); + const char *cursor_marker = @2[0] == ':' ? "$0" : @2; char *comment, *c1, *c2; @@ -394,7 +384,7 @@ ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectSt this->function = (current_function ? mm_strdup(current_function) : NULL); this->connection = connection ? mm_strdup(connection) : NULL; this->opened = false; - this->command = cat_str(7, mm_strdup("declare"), cursor_marker, @3, mm_strdup("cursor"), @5, mm_strdup("for"), @7); + this->command = mm_strdup(cat_str(7, "declare", cursor_marker, @3, "cursor", @5, "for", @7)); this->argsinsert = argsinsert; this->argsinsert_oos = NULL; this->argsresult = argsresult; @@ -402,20 +392,20 @@ ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectSt argsinsert = argsresult = NULL; cur = this; - c1 = mm_strdup(this->command); - if ((c2 = strstr(c1, "*/")) != NULL) + c1 = loc_strdup(this->command); + while ((c2 = strstr(c1, "*/")) != NULL) { /* We put this text into a comment, so we better remove [*][/]. */ c2[0] = '.'; c2[1] = '.'; } - comment = cat_str(3, mm_strdup("/*"), c1, mm_strdup("*/")); + comment = cat_str(3, "/*", c1, "*/"); @$ = cat2_str(adjust_outofscope_cursor_vars(this), comment); } ECPG: ClosePortalStmtCLOSEcursor_name block { - char *cursor_marker = @2[0] == ':' ? mm_strdup("$0") : @2; + const char *cursor_marker = @2[0] == ':' ? "$0" : @2; struct cursor *ptr = NULL; for (ptr = cur; ptr != NULL; ptr = ptr->next) @@ -427,23 +417,23 @@ ECPG: ClosePortalStmtCLOSEcursor_name block break; } } - @$ = cat2_str(mm_strdup("close"), cursor_marker); + @$ = cat2_str("close", cursor_marker); } ECPG: opt_hold block { if (compat == ECPG_COMPAT_INFORMIX_SE && autocommit) - @$ = mm_strdup("with hold"); + @$ = "with hold"; else - @$ = EMPTY; + @$ = ""; } ECPG: into_clauseINTOOptTempTableName block { FoundInto = 1; - @$ = cat2_str(mm_strdup("into"), @2); + @$ = cat2_str("into", @2); } | ecpg_into { - @$ = EMPTY; + @$ = ""; } ECPG: TypenameSimpleTypenameopt_array_bounds block { @@ -451,37 +441,33 @@ ECPG: TypenameSimpleTypenameopt_array_bounds block } ECPG: TypenameSETOFSimpleTypenameopt_array_bounds block { - @$ = cat_str(3, mm_strdup("setof"), @2, $3.str); + @$ = cat_str(3, "setof", @2, $3.str); } ECPG: opt_array_boundsopt_array_bounds'['']' block { $$.index1 = $1.index1; $$.index2 = $1.index2; if (strcmp($$.index1, "-1") == 0) - $$.index1 = mm_strdup("0"); + $$.index1 = "0"; else if (strcmp($1.index2, "-1") == 0) - $$.index2 = mm_strdup("0"); - $$.str = cat_str(2, $1.str, mm_strdup("[]")); + $$.index2 = "0"; + $$.str = cat_str(2, $1.str, "[]"); } | opt_array_bounds '[' Iresult ']' { $$.index1 = $1.index1; $$.index2 = $1.index2; if (strcmp($1.index1, "-1") == 0) - $$.index1 = mm_strdup(@3); + $$.index1 = @3; else if (strcmp($1.index2, "-1") == 0) - $$.index2 = mm_strdup(@3); - $$.str = cat_str(4, $1.str, mm_strdup("["), @3, mm_strdup("]")); + $$.index2 = @3; + $$.str = cat_str(4, $1.str, "[", @3, "]"); } ECPG: opt_array_bounds block { - $$.index1 = mm_strdup("-1"); - $$.index2 = mm_strdup("-1"); - $$.str = EMPTY; - } -ECPG: IconstICONST block - { - @$ = make_name(); + $$.index1 = "-1"; + $$.index2 = "-1"; + $$.str = ""; } ECPG: AexprConstNULL_P rule | civar @@ -494,83 +480,83 @@ ECPG: FetchStmtMOVEfetch_args rule | FETCH fetch_args ecpg_fetch_into | FETCH FORWARD cursor_name opt_ecpg_fetch_into { - char *cursor_marker = @3[0] == ':' ? mm_strdup("$0") : @3; + const char *cursor_marker = @3[0] == ':' ? "$0" : @3; struct cursor *ptr = add_additional_variables(@3, false); if (ptr->connection) connection = mm_strdup(ptr->connection); - @$ = cat_str(2, mm_strdup("fetch forward"), cursor_marker); + @$ = cat_str(2, "fetch forward", cursor_marker); } | FETCH FORWARD from_in cursor_name opt_ecpg_fetch_into { - char *cursor_marker = @4[0] == ':' ? mm_strdup("$0") : @4; + const char *cursor_marker = @4[0] == ':' ? "$0" : @4; struct cursor *ptr = add_additional_variables(@4, false); if (ptr->connection) connection = mm_strdup(ptr->connection); - @$ = cat_str(2, mm_strdup("fetch forward from"), cursor_marker); + @$ = cat_str(2, "fetch forward from", cursor_marker); } | FETCH BACKWARD cursor_name opt_ecpg_fetch_into { - char *cursor_marker = @3[0] == ':' ? mm_strdup("$0") : @3; + const char *cursor_marker = @3[0] == ':' ? "$0" : @3; struct cursor *ptr = add_additional_variables(@3, false); if (ptr->connection) connection = mm_strdup(ptr->connection); - @$ = cat_str(2, mm_strdup("fetch backward"), cursor_marker); + @$ = cat_str(2, "fetch backward", cursor_marker); } | FETCH BACKWARD from_in cursor_name opt_ecpg_fetch_into { - char *cursor_marker = @4[0] == ':' ? mm_strdup("$0") : @4; + const char *cursor_marker = @4[0] == ':' ? "$0" : @4; struct cursor *ptr = add_additional_variables(@4, false); if (ptr->connection) connection = mm_strdup(ptr->connection); - @$ = cat_str(2, mm_strdup("fetch backward from"), cursor_marker); + @$ = cat_str(2, "fetch backward from", cursor_marker); } | MOVE FORWARD cursor_name { - char *cursor_marker = @3[0] == ':' ? mm_strdup("$0") : @3; + const char *cursor_marker = @3[0] == ':' ? "$0" : @3; struct cursor *ptr = add_additional_variables(@3, false); if (ptr->connection) connection = mm_strdup(ptr->connection); - @$ = cat_str(2, mm_strdup("move forward"), cursor_marker); + @$ = cat_str(2, "move forward", cursor_marker); } | MOVE FORWARD from_in cursor_name { - char *cursor_marker = @4[0] == ':' ? mm_strdup("$0") : @4; + const char *cursor_marker = @4[0] == ':' ? "$0" : @4; struct cursor *ptr = add_additional_variables(@4, false); if (ptr->connection) connection = mm_strdup(ptr->connection); - @$ = cat_str(2, mm_strdup("move forward from"), cursor_marker); + @$ = cat_str(2, "move forward from", cursor_marker); } | MOVE BACKWARD cursor_name { - char *cursor_marker = @3[0] == ':' ? mm_strdup("$0") : @3; + const char *cursor_marker = @3[0] == ':' ? "$0" : @3; struct cursor *ptr = add_additional_variables(@3, false); if (ptr->connection) connection = mm_strdup(ptr->connection); - @$ = cat_str(2, mm_strdup("move backward"), cursor_marker); + @$ = cat_str(2, "move backward", cursor_marker); } | MOVE BACKWARD from_in cursor_name { - char *cursor_marker = @4[0] == ':' ? mm_strdup("$0") : @4; + const char *cursor_marker = @4[0] == ':' ? "$0" : @4; struct cursor *ptr = add_additional_variables(@4, false); if (ptr->connection) connection = mm_strdup(ptr->connection); - @$ = cat_str(2, mm_strdup("move backward from"), cursor_marker); + @$ = cat_str(2, "move backward from", cursor_marker); } ECPG: limit_clauseLIMITselect_limit_value','select_offset_value block { diff --git a/src/interfaces/ecpg/preproc/ecpg.header b/src/interfaces/ecpg/preproc/ecpg.header index 929ffa97aa0..d3df8eabbb7 100644 --- a/src/interfaces/ecpg/preproc/ecpg.header +++ b/src/interfaces/ecpg/preproc/ecpg.header @@ -39,8 +39,6 @@ char *input_filename = NULL; static int FoundInto = 0; static int initializer = 0; static int pacounter = 1; -static char pacounter_buffer[sizeof(int) * CHAR_BIT * 10 / 3]; /* a rough guess at the - * size we need */ static struct this_type actual_type[STRUCT_DEPTH]; static char *actual_startline[STRUCT_DEPTH]; static int varchar_counter = 1; @@ -95,7 +93,7 @@ yylloc_default(YYLTYPE *target, YYLTYPE *rhs, int N) needed++; needed += thislen; } - result = (char *) mm_alloc(needed + 1); + result = (char *) loc_alloc(needed + 1); ptr = result; for (int i = 1; i <= N; i++) { @@ -115,22 +113,19 @@ yylloc_default(YYLTYPE *target, YYLTYPE *rhs, int N) *target = rhs[1]; } else - *target = EMPTY; + { + /* No need to allocate any space */ + *target = ""; + } } /* and the rest */ static char * -make_name(void) -{ - return mm_strdup(base_yytext); -} - -static char * -create_questionmarks(char *name, bool array) +create_questionmarks(const char *name, bool array) { struct variable *p = find_variable(name); int count; - char *result = EMPTY; + char *result = ""; /* * In case we have a struct, we have to print as many "?" as there are @@ -158,12 +153,13 @@ create_questionmarks(char *name, bool array) for (; count > 0; count--) { - sprintf(pacounter_buffer, "$%d", pacounter++); - result = cat_str(3, result, mm_strdup(pacounter_buffer), mm_strdup(" , ")); - } + char buf[32]; - /* removed the trailing " ," */ + snprintf(buf, sizeof(buf), "$%d", pacounter++); + result = cat_str(3, result, buf, " , "); + } + /* remove the trailing " ," */ result[strlen(result) - 3] = '\0'; return result; } @@ -183,8 +179,7 @@ adjust_outofscope_cursor_vars(struct cursor *cur) * pointer instead of the variable. Do it only for local variables, not * for globals. */ - - char *result = EMPTY; + char *result = ""; int insert; for (insert = 1; insert >= 0; insert--) @@ -206,7 +201,7 @@ adjust_outofscope_cursor_vars(struct cursor *cur) /* change variable name to "ECPGget_var()" */ original_var = ptr->variable->name; - sprintf(var_text, "%d))", ecpg_internal_var); + snprintf(var_text, sizeof(var_text), "%d))", ecpg_internal_var); /* Don't emit ECPGset_var() calls for global variables */ if (ptr->variable->brace_level == 0) @@ -227,12 +222,12 @@ adjust_outofscope_cursor_vars(struct cursor *cur) && ptr->variable->type->type != ECPGt_bytea) && atoi(ptr->variable->type->size) > 1) { - newvar = new_variable(cat_str(4, mm_strdup("("), - mm_strdup(ecpg_type_name(ptr->variable->type->u.element->type)), - mm_strdup(" *)(ECPGget_var("), - mm_strdup(var_text)), + newvar = new_variable(cat_str(4, "(", + ecpg_type_name(ptr->variable->type->u.element->type), + " *)(ECPGget_var(", + var_text), ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type, - mm_strdup("1"), + "1", ptr->variable->type->u.element->counter), ptr->variable->type->size), 0); @@ -244,10 +239,10 @@ adjust_outofscope_cursor_vars(struct cursor *cur) || ptr->variable->type->type == ECPGt_bytea) && atoi(ptr->variable->type->size) > 1) { - newvar = new_variable(cat_str(4, mm_strdup("("), - mm_strdup(ecpg_type_name(ptr->variable->type->type)), - mm_strdup(" *)(ECPGget_var("), - mm_strdup(var_text)), + newvar = new_variable(cat_str(4, "(", + ecpg_type_name(ptr->variable->type->type), + " *)(ECPGget_var(", + var_text), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->counter), @@ -259,11 +254,11 @@ adjust_outofscope_cursor_vars(struct cursor *cur) else if (ptr->variable->type->type == ECPGt_struct || ptr->variable->type->type == ECPGt_union) { - newvar = new_variable(cat_str(5, mm_strdup("(*("), - mm_strdup(ptr->variable->type->type_name), - mm_strdup(" *)(ECPGget_var("), - mm_strdup(var_text), - mm_strdup(")")), + newvar = new_variable(cat_str(5, "(*(", + ptr->variable->type->type_name, + " *)(ECPGget_var(", + var_text, + ")"), ECPGmake_struct_type(ptr->variable->type->u.members, ptr->variable->type->type, ptr->variable->type->type_name, @@ -276,11 +271,11 @@ adjust_outofscope_cursor_vars(struct cursor *cur) if (ptr->variable->type->u.element->type == ECPGt_struct || ptr->variable->type->u.element->type == ECPGt_union) { - newvar = new_variable(cat_str(5, mm_strdup("(*("), - mm_strdup(ptr->variable->type->u.element->type_name), - mm_strdup(" *)(ECPGget_var("), - mm_strdup(var_text), - mm_strdup(")")), + newvar = new_variable(cat_str(5, "(*(", + ptr->variable->type->u.element->type_name, + " *)(ECPGget_var(", + var_text, + ")"), ECPGmake_struct_type(ptr->variable->type->u.element->u.members, ptr->variable->type->u.element->type, ptr->variable->type->u.element->type_name, @@ -289,10 +284,10 @@ adjust_outofscope_cursor_vars(struct cursor *cur) } else { - newvar = new_variable(cat_str(4, mm_strdup("("), - mm_strdup(ecpg_type_name(ptr->variable->type->u.element->type)), - mm_strdup(" *)(ECPGget_var("), - mm_strdup(var_text)), + newvar = new_variable(cat_str(4, "(", + ecpg_type_name(ptr->variable->type->u.element->type), + " *)(ECPGget_var(", + var_text), ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type, ptr->variable->type->u.element->size, ptr->variable->type->u.element->counter), @@ -303,10 +298,10 @@ adjust_outofscope_cursor_vars(struct cursor *cur) } else { - newvar = new_variable(cat_str(4, mm_strdup("*("), - mm_strdup(ecpg_type_name(ptr->variable->type->type)), - mm_strdup(" *)(ECPGget_var("), - mm_strdup(var_text)), + newvar = new_variable(cat_str(4, "*(", + ecpg_type_name(ptr->variable->type->type), + " *)(ECPGget_var(", + var_text), ECPGmake_simple_type(ptr->variable->type->type, ptr->variable->type->size, ptr->variable->type->counter), @@ -320,10 +315,11 @@ adjust_outofscope_cursor_vars(struct cursor *cur) */ if (!skip_set_var) { - sprintf(var_text, "%d, %s", ecpg_internal_var++, var_ptr ? "&(" : "("); - result = cat_str(5, result, mm_strdup("ECPGset_var("), - mm_strdup(var_text), mm_strdup(original_var), - mm_strdup("), __LINE__);\n")); + snprintf(var_text, sizeof(var_text), "%d, %s", + ecpg_internal_var++, var_ptr ? "&(" : "("); + result = cat_str(5, result, "ECPGset_var(", + var_text, original_var, + "), __LINE__);\n"); } /* @@ -338,17 +334,17 @@ adjust_outofscope_cursor_vars(struct cursor *cur) { /* change variable name to "ECPGget_var()" */ original_var = ptr->indicator->name; - sprintf(var_text, "%d))", ecpg_internal_var); + snprintf(var_text, sizeof(var_text), "%d))", ecpg_internal_var); var_ptr = false; if (ptr->indicator->type->type == ECPGt_struct || ptr->indicator->type->type == ECPGt_union) { - newind = new_variable(cat_str(5, mm_strdup("(*("), - mm_strdup(ptr->indicator->type->type_name), - mm_strdup(" *)(ECPGget_var("), - mm_strdup(var_text), - mm_strdup(")")), + newind = new_variable(cat_str(5, "(*(", + ptr->indicator->type->type_name, + " *)(ECPGget_var(", + var_text, + ")"), ECPGmake_struct_type(ptr->indicator->type->u.members, ptr->indicator->type->type, ptr->indicator->type->type_name, @@ -361,11 +357,11 @@ adjust_outofscope_cursor_vars(struct cursor *cur) if (ptr->indicator->type->u.element->type == ECPGt_struct || ptr->indicator->type->u.element->type == ECPGt_union) { - newind = new_variable(cat_str(5, mm_strdup("(*("), - mm_strdup(ptr->indicator->type->u.element->type_name), - mm_strdup(" *)(ECPGget_var("), - mm_strdup(var_text), - mm_strdup(")")), + newind = new_variable(cat_str(5, "(*(", + ptr->indicator->type->u.element->type_name, + " *)(ECPGget_var(", + var_text, + ")"), ECPGmake_struct_type(ptr->indicator->type->u.element->u.members, ptr->indicator->type->u.element->type, ptr->indicator->type->u.element->type_name, @@ -374,9 +370,10 @@ adjust_outofscope_cursor_vars(struct cursor *cur) } else { - newind = new_variable(cat_str(4, mm_strdup("("), - mm_strdup(ecpg_type_name(ptr->indicator->type->u.element->type)), - mm_strdup(" *)(ECPGget_var("), mm_strdup(var_text)), + newind = new_variable(cat_str(4, "(", + ecpg_type_name(ptr->indicator->type->u.element->type), + " *)(ECPGget_var(", + var_text), ECPGmake_array_type(ECPGmake_simple_type(ptr->indicator->type->u.element->type, ptr->indicator->type->u.element->size, ptr->indicator->type->u.element->counter), @@ -387,10 +384,10 @@ adjust_outofscope_cursor_vars(struct cursor *cur) } else if (atoi(ptr->indicator->type->size) > 1) { - newind = new_variable(cat_str(4, mm_strdup("("), - mm_strdup(ecpg_type_name(ptr->indicator->type->type)), - mm_strdup(" *)(ECPGget_var("), - mm_strdup(var_text)), + newind = new_variable(cat_str(4, "(", + ecpg_type_name(ptr->indicator->type->type), + " *)(ECPGget_var(", + var_text), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size, ptr->variable->type->counter), @@ -398,10 +395,10 @@ adjust_outofscope_cursor_vars(struct cursor *cur) } else { - newind = new_variable(cat_str(4, mm_strdup("*("), - mm_strdup(ecpg_type_name(ptr->indicator->type->type)), - mm_strdup(" *)(ECPGget_var("), - mm_strdup(var_text)), + newind = new_variable(cat_str(4, "*(", + ecpg_type_name(ptr->indicator->type->type), + " *)(ECPGget_var(", + var_text), ECPGmake_simple_type(ptr->indicator->type->type, ptr->indicator->type->size, ptr->variable->type->counter), @@ -413,10 +410,11 @@ adjust_outofscope_cursor_vars(struct cursor *cur) * create call to "ECPGset_var(, . )" */ - sprintf(var_text, "%d, %s", ecpg_internal_var++, var_ptr ? "&(" : "("); - result = cat_str(5, result, mm_strdup("ECPGset_var("), - mm_strdup(var_text), mm_strdup(original_var), - mm_strdup("), __LINE__);\n")); + snprintf(var_text, sizeof(var_text), "%d, %s", + ecpg_internal_var++, var_ptr ? "&(" : "("); + result = cat_str(5, result, "ECPGset_var(", + var_text, original_var, + "), __LINE__);\n"); } add_variable_to_tail(&newlist, newvar, newind); @@ -437,7 +435,7 @@ adjust_outofscope_cursor_vars(struct cursor *cur) (cur->function != NULL && strcmp(cur->function, current_function) == 0)) static struct cursor * -add_additional_variables(char *name, bool insert) +add_additional_variables(const char *name, bool insert) { struct cursor *ptr; struct arguments *p; @@ -475,8 +473,10 @@ add_additional_variables(char *name, bool insert) } static void -add_typedef(char *name, char *dimension, char *length, enum ECPGttype type_enum, - char *type_dimension, char *type_index, int initializer, int array) +add_typedef(const char *name, const char *dimension, const char *length, + enum ECPGttype type_enum, + const char *type_dimension, const char *type_index, + int initializer, int array) { /* add entry to list */ struct typedefs *ptr, @@ -496,19 +496,20 @@ add_typedef(char *name, char *dimension, char *length, enum ECPGttype type_enum, /* re-definition is a bug */ mmerror(PARSE_ERROR, ET_ERROR, "type \"%s\" is already defined", name); } - adjust_array(type_enum, &dimension, &length, type_dimension, type_index, array, true); + adjust_array(type_enum, &dimension, &length, + type_dimension, type_index, array, true); this = (struct typedefs *) mm_alloc(sizeof(struct typedefs)); /* initial definition */ this->next = types; - this->name = name; + this->name = mm_strdup(name); this->brace_level = braces_open; this->type = (struct this_type *) mm_alloc(sizeof(struct this_type)); this->type->type_enum = type_enum; this->type->type_str = mm_strdup(name); - this->type->type_dimension = dimension; /* dimension of array */ - this->type->type_index = length; /* length of string */ + this->type->type_dimension = mm_strdup(dimension); /* dimension of array */ + this->type->type_index = mm_strdup(length); /* length of string */ this->type->type_sizeof = ECPGstruct_sizeof; this->struct_member_list = (type_enum == ECPGt_struct || type_enum == ECPGt_union) ? ECPGstruct_member_dup(struct_member_list[struct_level]) : NULL; diff --git a/src/interfaces/ecpg/preproc/ecpg.trailer b/src/interfaces/ecpg/preproc/ecpg.trailer index 2a3949ca035..0a77559e83b 100644 --- a/src/interfaces/ecpg/preproc/ecpg.trailer +++ b/src/interfaces/ecpg/preproc/ecpg.trailer @@ -2,6 +2,12 @@ statements: /* EMPTY */ | statements statement + { + /* Reclaim local storage used while processing statement */ + reclaim_local_storage(); + /* Clean up now-dangling location pointer */ + @$ = ""; + } ; statement: ecpgstart at toplevel_stmt ';' @@ -68,7 +74,7 @@ CreateAsStmt: CREATE OptTemp TABLE create_as_target AS at: AT connection_object { - connection = @2; + connection = mm_strdup(@2); /* * Do we have a variable as connection target? Remove the variable @@ -84,20 +90,20 @@ at: AT connection_object */ ECPGConnect: SQL_CONNECT TO connection_target opt_connection_name opt_user { - @$ = cat_str(5, @3, mm_strdup(","), @5, mm_strdup(","), @4); + @$ = cat_str(5, @3, ",", @5, ",", @4); } | SQL_CONNECT TO DEFAULT { - @$ = mm_strdup("NULL, NULL, NULL, \"DEFAULT\""); + @$ = "NULL, NULL, NULL, \"DEFAULT\""; } /* also allow ORACLE syntax */ | SQL_CONNECT ora_user { - @$ = cat_str(3, mm_strdup("NULL,"), @2, mm_strdup(", NULL")); + @$ = cat_str(3, "NULL,", @2, ", NULL"); } | DATABASE connection_target { - @$ = cat2_str(@2, mm_strdup(", NULL, NULL, NULL")); + @$ = cat2_str(@2, ", NULL, NULL, NULL"); } ; @@ -111,7 +117,7 @@ connection_target: opt_database_name opt_server opt_port if (@1[0] == '\"') @$ = @1; else - @$ = make3_str(mm_strdup("\""), make3_str(@1, @2, @3), mm_strdup("\"")); + @$ = make3_str("\"", make3_str(@1, @2, @3), "\""); } | db_prefix ':' server opt_port '/' opt_database_name opt_options { @@ -127,19 +133,21 @@ connection_target: opt_database_name opt_server opt_port strncmp(@3 + strlen("//"), "127.0.0.1", strlen("127.0.0.1")) != 0) mmerror(PARSE_ERROR, ET_ERROR, "Unix-domain sockets only work on \"localhost\" but not on \"%s\"", @3 + strlen("//")); - @$ = make3_str(make3_str(mm_strdup("\""), @1, mm_strdup(":")), @3, make3_str(make3_str(@4, mm_strdup("/"), @6), @7, mm_strdup("\""))); + @$ = make3_str(make3_str("\"", @1, ":"), @3, make3_str(make3_str(@4, "/", @6), @7, "\"")); } | char_variable | ecpg_sconst { /* - * We can only process double quoted strings not single quotes ones, - * so we change the quotes. Note, that the rule for ecpg_sconst adds + * We can only process double quoted strings not single quoted ones, + * so we change the quotes. Note that the rule for ecpg_sconst adds * these single quotes. */ - @1[0] = '\"'; - @1[strlen(@1) - 1] = '\"'; - @$ = @1; + char *str = loc_strdup(@1); + + str[0] = '\"'; + str[strlen(str) - 1] = '\"'; + @$ = str; } ; @@ -155,7 +163,7 @@ db_prefix: ecpg_ident cvariable if (strcmp(@1, "tcp") != 0 && strcmp(@1, "unix") != 0) mmerror(PARSE_ERROR, ET_ERROR, "invalid connection type: %s", @1); - @$ = make3_str(@1, mm_strdup(":"), @2); + @$ = make3_str(@1, ":", @2); } ; @@ -175,14 +183,11 @@ opt_server: server server_name: ColId | ColId '.' server_name | IP - { - @$ = make_name(); - } ; opt_port: ':' Iconst { - @$ = make2_str(mm_strdup(":"), @2); + @$ = make2_str(":", @2); } | /* EMPTY */ ; @@ -193,7 +198,7 @@ opt_connection_name: AS connection_object } | /* EMPTY */ { - @$ = mm_strdup("NULL"); + @$ = "NULL"; } ; @@ -203,25 +208,25 @@ opt_user: USER ora_user } | /* EMPTY */ { - @$ = mm_strdup("NULL, NULL"); + @$ = "NULL, NULL"; } ; ora_user: user_name { - @$ = cat2_str(@1, mm_strdup(", NULL")); + @$ = cat2_str(@1, ", NULL"); } | user_name '/' user_name { - @$ = cat_str(3, @1, mm_strdup(","), @3); + @$ = cat_str(3, @1, ",", @3); } | user_name SQL_IDENTIFIED BY user_name { - @$ = cat_str(3, @1, mm_strdup(","), @4); + @$ = cat_str(3, @1, ",", @4); } | user_name USING user_name { - @$ = cat_str(3, @1, mm_strdup(","), @3); + @$ = cat_str(3, @1, ",", @3); } ; @@ -230,14 +235,14 @@ user_name: RoleId if (@1[0] == '\"') @$ = @1; else - @$ = make3_str(mm_strdup("\""), @1, mm_strdup("\"")); + @$ = make3_str("\"", @1, "\""); } | ecpg_sconst { if (@1[0] == '\"') @$ = @1; else - @$ = make3_str(mm_strdup("\""), @1, mm_strdup("\"")); + @$ = make3_str("\"", @1, "\""); } | civar { @@ -249,9 +254,9 @@ user_name: RoleId /* handle varchars */ if (type == ECPGt_varchar) - @$ = make2_str(mm_strdup(argsinsert->variable->name), mm_strdup(".arr")); + @$ = make2_str(argsinsert->variable->name, ".arr"); else - @$ = mm_strdup(argsinsert->variable->name); + @$ = argsinsert->variable->name; } ; @@ -278,7 +283,7 @@ char_variable: cvariable @$ = @1; break; case ECPGt_varchar: - @$ = make2_str(@1, mm_strdup(".arr")); + @$ = make2_str(@1, ".arr"); break; default: mmerror(PARSE_ERROR, ET_ERROR, "invalid data type"); @@ -297,7 +302,7 @@ opt_options: Op connect_options if (strcmp(@1, "?") != 0) mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", @1); - @$ = make2_str(mm_strdup("?"), @2); + @$ = make2_str("?", @2); } | /* EMPTY */ ; @@ -321,30 +326,34 @@ connect_options: ColId opt_opt_value opt_opt_value: /* EMPTY */ | '=' Iconst { - @$ = make2_str(mm_strdup("="), @2); + @$ = make2_str("=", @2); } | '=' ecpg_ident { - @$ = make2_str(mm_strdup("="), @2); + @$ = make2_str("=", @2); } | '=' civar { - @$ = make2_str(mm_strdup("="), @2); + @$ = make2_str("=", @2); } ; prepared_name: name { - if (@1[0] == '\"' && @1[strlen(@1) - 1] == '\"') /* already quoted? */ + size_t slen = strlen(@1); + + if (@1[0] == '\"' && @1[slen - 1] == '\"') /* already quoted? */ @$ = @1; else /* not quoted => convert to lowercase */ { - size_t i; - - for (i = 0; i < strlen(@1); i++) - @1[i] = tolower((unsigned char) @1[i]); - - @$ = make3_str(mm_strdup("\""), @1, mm_strdup("\"")); + char *str = loc_alloc(slen + 3); + + str[0] = '\"'; + for (size_t i = 0; i < slen; i++) + str[i + 1] = tolower((unsigned char) @1[i]); + str[slen + 1] = '\"'; + str[slen + 2] = '\0'; + @$ = str; } } | char_variable @@ -355,7 +364,7 @@ prepared_name: name */ ECPGDeclareStmt: DECLARE prepared_name STATEMENT { - struct declared_list *ptr = NULL; + struct declared_list *ptr; /* Check whether the declared name has been defined or not */ for (ptr = g_declared_list; ptr != NULL; ptr = ptr->next) @@ -368,12 +377,11 @@ ECPGDeclareStmt: DECLARE prepared_name STATEMENT } /* Add a new declared name into the g_declared_list */ - ptr = NULL; ptr = (struct declared_list *) mm_alloc(sizeof(struct declared_list)); if (ptr) { /* initial definition */ - ptr->name = @2; + ptr->name = mm_strdup(@2); if (connection) ptr->connection = mm_strdup(connection); else @@ -383,7 +391,7 @@ ECPGDeclareStmt: DECLARE prepared_name STATEMENT g_declared_list = ptr; } - @$ = cat_str(3, mm_strdup("/* declare "), mm_strdup(@2), mm_strdup(" as an SQL identifier */")); + @$ = cat_str(3, "/* declare ", @2, " as an SQL identifier */"); } ; @@ -395,7 +403,7 @@ ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared_ { struct cursor *ptr, *this; - char *cursor_marker = @2[0] == ':' ? mm_strdup("$0") : mm_strdup(@2); + const char *cursor_marker = @2[0] == ':' ? "$0" : @2; int (*strcmp_fn) (const char *, const char *) = ((@2[0] == ':' || @2[0] == '"') ? strcmp : pg_strcasecmp); struct variable *thisquery = (struct variable *) mm_alloc(sizeof(struct variable)); char *comment; @@ -422,10 +430,10 @@ ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared_ /* initial definition */ this->next = cur; - this->name = @2; + this->name = mm_strdup(@2); this->function = (current_function ? mm_strdup(current_function) : NULL); this->connection = connection ? mm_strdup(connection) : NULL; - this->command = cat_str(6, mm_strdup("declare"), cursor_marker, @3, mm_strdup("cursor"), @5, mm_strdup("for $1")); + this->command = mm_strdup(cat_str(6, "declare", cursor_marker, @3, "cursor", @5, "for $1")); this->argsresult = NULL; this->argsresult_oos = NULL; @@ -448,7 +456,7 @@ ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared_ cur = this; - comment = cat_str(3, mm_strdup("/*"), mm_strdup(this->command), mm_strdup("*/")); + comment = cat_str(3, "/*", this->command, "*/"); @$ = cat_str(2, adjust_outofscope_cursor_vars(this), comment); @@ -541,45 +549,44 @@ type_declaration: S_TYPEDEF fprintf(base_yyout, "typedef %s %s %s %s;\n", $3.type_str, *@4 ? "*" : "", @5, $6.str); output_line_number(); - @$ = EMPTY; + @$ = ""; } ; var_declaration: storage_declaration var_type { - actual_type[struct_level].type_storage = @1; + actual_type[struct_level].type_storage = mm_strdup(@1); actual_type[struct_level].type_enum = $2.type_enum; - actual_type[struct_level].type_str = $2.type_str; - actual_type[struct_level].type_dimension = $2.type_dimension; - actual_type[struct_level].type_index = $2.type_index; - actual_type[struct_level].type_sizeof = $2.type_sizeof; + actual_type[struct_level].type_str = mm_strdup($2.type_str); + actual_type[struct_level].type_dimension = mm_strdup($2.type_dimension); + actual_type[struct_level].type_index = mm_strdup($2.type_index); + actual_type[struct_level].type_sizeof = + $2.type_sizeof ? mm_strdup($2.type_sizeof) : NULL; actual_startline[struct_level] = hashline_number(); } variable_list ';' { - @$ = cat_str(5, actual_startline[struct_level], @1, $2.type_str, @4, mm_strdup(";\n")); + @$ = cat_str(5, actual_startline[struct_level], @1, $2.type_str, @4, ";\n"); } | var_type { - actual_type[struct_level].type_storage = EMPTY; + actual_type[struct_level].type_storage = mm_strdup(""); actual_type[struct_level].type_enum = $1.type_enum; - actual_type[struct_level].type_str = $1.type_str; - actual_type[struct_level].type_dimension = $1.type_dimension; - actual_type[struct_level].type_index = $1.type_index; - actual_type[struct_level].type_sizeof = $1.type_sizeof; + actual_type[struct_level].type_str = mm_strdup($1.type_str); + actual_type[struct_level].type_dimension = mm_strdup($1.type_dimension); + actual_type[struct_level].type_index = mm_strdup($1.type_index); + actual_type[struct_level].type_sizeof = + $1.type_sizeof ? mm_strdup($1.type_sizeof) : NULL; actual_startline[struct_level] = hashline_number(); } variable_list ';' { - @$ = cat_str(4, actual_startline[struct_level], $1.type_str, @3, mm_strdup(";\n")); + @$ = cat_str(4, actual_startline[struct_level], $1.type_str, @3, ";\n"); } | struct_union_type_with_symbol ';' - { - @$ = cat2_str(@1, mm_strdup(";")); - } ; opt_bit_field: ':' Iconst @@ -604,16 +611,16 @@ storage_modifier: S_CONST var_type: simple_type { $$.type_enum = $1; - $$.type_str = mm_strdup(ecpg_type_name($1)); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = loc_strdup(ecpg_type_name($1)); + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } | struct_union_type { - $$.type_str = @1; - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = loc_strdup(@1); + $$.type_dimension = "-1"; + $$.type_index = "-1"; if (strncmp(@1, "struct", sizeof("struct") - 1) == 0) { @@ -628,26 +635,26 @@ var_type: simple_type } | enum_type { - $$.type_str = @1; + $$.type_str = loc_strdup(@1); $$.type_enum = ECPGt_int; - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } | NUMERIC '(' precision opt_scale ')' { $$.type_enum = ECPGt_numeric; - $$.type_str = mm_strdup("numeric"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = "numeric"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } | DECIMAL_P '(' precision opt_scale ')' { $$.type_enum = ECPGt_decimal; - $$.type_str = mm_strdup("decimal"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = "decimal"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } | IDENT '(' precision opt_scale ')' @@ -660,63 +667,63 @@ var_type: simple_type if (strcmp(@1, "numeric") == 0) { $$.type_enum = ECPGt_numeric; - $$.type_str = mm_strdup("numeric"); + $$.type_str = "numeric"; } else if (strcmp(@1, "decimal") == 0) { $$.type_enum = ECPGt_decimal; - $$.type_str = mm_strdup("decimal"); + $$.type_str = "decimal"; } else { mmerror(PARSE_ERROR, ET_ERROR, "only data types numeric and decimal have precision/scale argument"); $$.type_enum = ECPGt_numeric; - $$.type_str = mm_strdup("numeric"); + $$.type_str = "numeric"; } - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } | VARCHAR { $$.type_enum = ECPGt_varchar; - $$.type_str = EMPTY; /* mm_strdup("varchar"); */ - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = ""; /* "varchar"; */ + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } | FLOAT_P { /* Note: DOUBLE is handled in simple_type */ $$.type_enum = ECPGt_float; - $$.type_str = mm_strdup("float"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = "float"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } | NUMERIC { $$.type_enum = ECPGt_numeric; - $$.type_str = mm_strdup("numeric"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = "numeric"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } | DECIMAL_P { $$.type_enum = ECPGt_decimal; - $$.type_str = mm_strdup("decimal"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = "decimal"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } | TIMESTAMP { $$.type_enum = ECPGt_timestamp; - $$.type_str = mm_strdup("timestamp"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = "timestamp"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } | STRING_P @@ -725,9 +732,9 @@ var_type: simple_type { /* In Informix mode, "string" is automatically a typedef */ $$.type_enum = ECPGt_string; - $$.type_str = mm_strdup("char"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = "char"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } else @@ -735,14 +742,14 @@ var_type: simple_type /* Otherwise, legal only if user typedef'ed it */ struct typedefs *this = get_typedef("string", false); - $$.type_str = (this->type->type_enum == ECPGt_varchar || this->type->type_enum == ECPGt_bytea) ? EMPTY : mm_strdup(this->name); + $$.type_str = (this->type->type_enum == ECPGt_varchar || this->type->type_enum == ECPGt_bytea) ? mm_strdup("") : mm_strdup(this->name); $$.type_enum = this->type->type_enum; $$.type_dimension = this->type->type_dimension; $$.type_index = this->type->type_index; if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0) $$.type_sizeof = this->type->type_sizeof; else - $$.type_sizeof = cat_str(3, mm_strdup("sizeof("), mm_strdup(this->name), mm_strdup(")")); + $$.type_sizeof = cat_str(3, "sizeof(", this->name, ")"); struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list); } @@ -750,9 +757,9 @@ var_type: simple_type | INTERVAL ecpg_interval { $$.type_enum = ECPGt_interval; - $$.type_str = mm_strdup("interval"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = "interval"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } | IDENT ecpg_interval @@ -772,89 +779,89 @@ var_type: simple_type if (strcmp(@1, "varchar") == 0) { $$.type_enum = ECPGt_varchar; - $$.type_str = EMPTY; /* mm_strdup("varchar"); */ - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = ""; /* "varchar"; */ + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } else if (strcmp(@1, "bytea") == 0) { $$.type_enum = ECPGt_bytea; - $$.type_str = EMPTY; - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = ""; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } else if (strcmp(@1, "float") == 0) { $$.type_enum = ECPGt_float; - $$.type_str = mm_strdup("float"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = "float"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } else if (strcmp(@1, "double") == 0) { $$.type_enum = ECPGt_double; - $$.type_str = mm_strdup("double"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = "double"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } else if (strcmp(@1, "numeric") == 0) { $$.type_enum = ECPGt_numeric; - $$.type_str = mm_strdup("numeric"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = "numeric"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } else if (strcmp(@1, "decimal") == 0) { $$.type_enum = ECPGt_decimal; - $$.type_str = mm_strdup("decimal"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = "decimal"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } else if (strcmp(@1, "date") == 0) { $$.type_enum = ECPGt_date; - $$.type_str = mm_strdup("date"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = "date"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } else if (strcmp(@1, "timestamp") == 0) { $$.type_enum = ECPGt_timestamp; - $$.type_str = mm_strdup("timestamp"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = "timestamp"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } else if (strcmp(@1, "interval") == 0) { $$.type_enum = ECPGt_interval; - $$.type_str = mm_strdup("interval"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = "interval"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } else if (strcmp(@1, "datetime") == 0) { $$.type_enum = ECPGt_timestamp; - $$.type_str = mm_strdup("timestamp"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = "timestamp"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } else if ((strcmp(@1, "string") == 0) && INFORMIX_MODE) { $$.type_enum = ECPGt_string; - $$.type_str = mm_strdup("char"); - $$.type_dimension = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); + $$.type_str = "char"; + $$.type_dimension = "-1"; + $$.type_index = "-1"; $$.type_sizeof = NULL; } else @@ -862,14 +869,14 @@ var_type: simple_type /* Otherwise, it must be a user-defined typedef name */ struct typedefs *this = get_typedef(@1, false); - $$.type_str = (this->type->type_enum == ECPGt_varchar || this->type->type_enum == ECPGt_bytea) ? EMPTY : mm_strdup(this->name); + $$.type_str = (this->type->type_enum == ECPGt_varchar || this->type->type_enum == ECPGt_bytea) ? mm_strdup("") : mm_strdup(this->name); $$.type_enum = this->type->type_enum; $$.type_dimension = this->type->type_dimension; $$.type_index = this->type->type_index; if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0) $$.type_sizeof = this->type->type_sizeof; else - $$.type_sizeof = cat_str(3, mm_strdup("sizeof("), mm_strdup(this->name), mm_strdup(")")); + $$.type_sizeof = cat_str(3, "sizeof(", this->name, ")"); struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list); } @@ -888,21 +895,20 @@ var_type: simple_type /* No */ this = get_typedef(name, false); - $$.type_str = mm_strdup(this->name); + $$.type_str = 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 = mm_strdup("-1"); - $$.type_index = mm_strdup("-1"); - $$.type_sizeof = mm_strdup(""); + $$.type_dimension = "-1"; + $$.type_index = "-1"; + $$.type_sizeof = ""; struct_member_list[struct_level] = NULL; } } @@ -932,7 +938,7 @@ struct_union_type_with_symbol: s_struct_union_symbol ECPGfree_struct_member(struct_member_list[struct_level]); struct_member_list[struct_level] = NULL; struct_level--; - if (strncmp($1.su, "struct", sizeof("struct") - 1) == 0) + if (strcmp($1.su, "struct") == 0) su_type.type_enum = ECPGt_struct; else su_type.type_enum = ECPGt_union; @@ -967,7 +973,7 @@ struct_union_type_with_symbol: s_struct_union_symbol this->struct_member_list = struct_member_list[struct_level]; types = this; - @$ = cat_str(4, su_type.type_str, mm_strdup("{"), @4, mm_strdup("}")); + @$ = cat_str(4, su_type.type_str, "{", @4, "}"); } ; @@ -983,19 +989,21 @@ struct_union_type: struct_union_type_with_symbol ECPGfree_struct_member(struct_member_list[struct_level]); struct_member_list[struct_level] = NULL; struct_level--; - @$ = cat_str(4, @1, mm_strdup("{"), @4, mm_strdup("}")); + @$ = cat_str(4, @1, "{", @4, "}"); } ; s_struct_union_symbol: SQL_STRUCT symbol { - $$.su = mm_strdup("struct"); + $$.su = "struct"; $$.symbol = @2; - ECPGstruct_sizeof = cat_str(3, mm_strdup("sizeof("), cat2_str(mm_strdup($$.su), mm_strdup($$.symbol)), mm_strdup(")")); + ECPGstruct_sizeof = mm_strdup(cat_str(3, "sizeof(", + cat2_str($$.su, $$.symbol), + ")")); } | UNION symbol { - $$.su = mm_strdup("union"); + $$.su = "union"; $$.symbol = @2; } ; @@ -1004,11 +1012,11 @@ s_struct_union: SQL_STRUCT { ECPGstruct_sizeof = mm_strdup(""); /* This must not be NULL to * distinguish from simple types. */ - @$ = mm_strdup("struct"); + @$ = "struct"; } | UNION { - @$ = mm_strdup("union"); + @$ = "union"; } ; @@ -1047,23 +1055,27 @@ variable_list: variable | variable_list ',' variable { if (actual_type[struct_level].type_enum == ECPGt_varchar || actual_type[struct_level].type_enum == ECPGt_bytea) - @$ = cat_str(4, @1, mm_strdup(";"), mm_strdup(actual_type[struct_level].type_storage), @3); + @$ = cat_str(4, @1, ";", actual_type[struct_level].type_storage, @3); else - @$ = cat_str(3, @1, mm_strdup(","), @3); + @$ = cat_str(3, @1, ",", @3); } ; variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initializer { struct ECPGtype *type; - char *dimension = $3.index1; /* dimension of array */ - char *length = $3.index2; /* length of string */ + const char *dimension = $3.index1; /* dimension of array */ + const char *length = $3.index2; /* length of string */ char *dim_str; - char *vcn; + char vcn[32]; int *varlen_type_counter; char *struct_name; - adjust_array(actual_type[struct_level].type_enum, &dimension, &length, actual_type[struct_level].type_dimension, actual_type[struct_level].type_index, strlen(@1), false); + adjust_array(actual_type[struct_level].type_enum, + &dimension, &length, + actual_type[struct_level].type_dimension, + actual_type[struct_level].type_index, + strlen(@1), false); switch (actual_type[struct_level].type_enum) { case ECPGt_struct: @@ -1073,7 +1085,7 @@ variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initialize else type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_str, actual_type[struct_level].type_sizeof), dimension); - @$ = cat_str(5, @1, mm_strdup(@2), $3.str, @4, @5); + @$ = cat_str(5, @1, @2, $3.str, @4, @5); break; case ECPGt_varchar: @@ -1094,9 +1106,9 @@ variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initialize type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, *varlen_type_counter), dimension); if (strcmp(dimension, "0") == 0 || abs(atoi(dimension)) == 1) - dim_str = mm_strdup(""); + dim_str = ""; else - dim_str = cat_str(3, mm_strdup("["), mm_strdup(dimension), mm_strdup("]")); + dim_str = cat_str(3, "[", dimension, "]"); /* * cannot check for atoi <= 0 because a defined constant will @@ -1109,12 +1121,11 @@ variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initialize * make sure varchar struct name is unique by adding a unique * counter to its definition */ - vcn = (char *) mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); - sprintf(vcn, "%d", *varlen_type_counter); + snprintf(vcn, sizeof(vcn), "%d", *varlen_type_counter); if (strcmp(dimension, "0") == 0) - @$ = cat_str(7, make2_str(mm_strdup(struct_name), vcn), mm_strdup(" { int len; char arr["), mm_strdup(length), mm_strdup("]; } *"), mm_strdup(@2), @4, @5); + @$ = cat_str(7, make2_str(struct_name, vcn), " { int len; char arr[", length, "]; } *", @2, @4, @5); else - @$ = cat_str(8, make2_str(mm_strdup(struct_name), vcn), mm_strdup(" { int len; char arr["), mm_strdup(length), mm_strdup("]; } "), mm_strdup(@2), dim_str, @4, @5); + @$ = cat_str(8, make2_str(struct_name, vcn), " { int len; char arr[", length, "]; } ", @2, dim_str, @4, @5); (*varlen_type_counter)++; break; @@ -1132,25 +1143,26 @@ variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initialize * if we have an initializer but no string size set, * let's use the initializer's length */ - free(length); - length = mm_alloc(i + sizeof("sizeof()")); - sprintf(length, "sizeof(%s)", @5 + 2); + char *buf = loc_alloc(32); + + snprintf(buf, 32, "sizeof(%s)", @5 + 2); + length = buf; } type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0); } else type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0), dimension); - @$ = cat_str(5, @1, mm_strdup(@2), $3.str, @4, @5); + @$ = cat_str(5, @1, @2, $3.str, @4, @5); break; default: if (atoi(dimension) < 0) - type = ECPGmake_simple_type(actual_type[struct_level].type_enum, mm_strdup("1"), 0); + type = ECPGmake_simple_type(actual_type[struct_level].type_enum, "1", 0); else - type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, mm_strdup("1"), 0), dimension); + type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, "1", 0), dimension); - @$ = cat_str(5, @1, mm_strdup(@2), $3.str, @4, @5); + @$ = cat_str(5, @1, @2, $3.str, @4, @5); break; } @@ -1172,7 +1184,7 @@ opt_pointer: /* EMPTY */ | '*' | '*' '*' { - @$ = mm_strdup("**"); + @$ = "**"; } ; @@ -1182,7 +1194,7 @@ opt_pointer: /* EMPTY */ ECPGDeclare: DECLARE STATEMENT ecpg_ident { /* this is only supported for compatibility */ - @$ = cat_str(3, mm_strdup("/* declare statement"), @3, mm_strdup("*/")); + @$ = cat_str(3, "/* declare statement", @3, "*/"); } ; /* @@ -1197,25 +1209,25 @@ ECPGDisconnect: SQL_DISCONNECT dis_name dis_name: connection_object | CURRENT_P { - @$ = mm_strdup("\"CURRENT\""); + @$ = "\"CURRENT\""; } | ALL { - @$ = mm_strdup("\"ALL\""); + @$ = "\"ALL\""; } | /* EMPTY */ { - @$ = mm_strdup("\"CURRENT\""); + @$ = "\"CURRENT\""; } ; connection_object: name { - @$ = make3_str(mm_strdup("\""), @1, mm_strdup("\"")); + @$ = make3_str("\"", @1, "\""); } | DEFAULT { - @$ = mm_strdup("\"DEFAULT\""); + @$ = "\"DEFAULT\""; } | char_variable ; @@ -1223,7 +1235,7 @@ connection_object: name execstring: char_variable | CSTRING { - @$ = make3_str(mm_strdup("\""), @1, mm_strdup("\"")); + @$ = make3_str("\"", @1, "\""); } ; @@ -1237,7 +1249,7 @@ ECPGFree: SQL_FREE cursor_name } | SQL_FREE ALL { - @$ = mm_strdup("all"); + @$ = "all"; } ; @@ -1258,7 +1270,7 @@ opt_ecpg_using: /* EMPTY */ ecpg_using: USING using_list { - @$ = EMPTY; + @$ = ""; } | using_descriptor ; @@ -1266,31 +1278,31 @@ ecpg_using: USING using_list using_descriptor: USING SQL_P SQL_DESCRIPTOR quoted_ident_stringvar { add_variable_to_head(&argsinsert, descriptor_variable(@4, 0), &no_indicator); - @$ = EMPTY; + @$ = ""; } | USING SQL_DESCRIPTOR name { add_variable_to_head(&argsinsert, sqlda_variable(@3), &no_indicator); - @$ = EMPTY; + @$ = ""; } ; into_descriptor: INTO SQL_P SQL_DESCRIPTOR quoted_ident_stringvar { add_variable_to_head(&argsresult, descriptor_variable(@4, 1), &no_indicator); - @$ = EMPTY; + @$ = ""; } | INTO SQL_DESCRIPTOR name { add_variable_to_head(&argsresult, sqlda_variable(@3), &no_indicator); - @$ = EMPTY; + @$ = ""; } ; into_sqlda: INTO name { add_variable_to_head(&argsresult, sqlda_variable(@2), &no_indicator); - @$ = EMPTY; + @$ = ""; } ; @@ -1299,18 +1311,18 @@ using_list: UsingValue | UsingValue ',' using_list UsingValue: UsingConst { - char *length = mm_alloc(32); + char length[32]; - sprintf(length, "%zu", strlen(@1)); + snprintf(length, sizeof(length), "%zu", strlen(@1)); add_variable_to_head(&argsinsert, new_variable(@1, ECPGmake_simple_type(ECPGt_const, length, 0), 0), &no_indicator); } | civar { - @$ = EMPTY; + @$ = ""; } | civarind { - @$ = EMPTY; + @$ = ""; } ; @@ -1430,9 +1442,9 @@ ECPGSetDescHeaderItem: desc_header_item '=' IntConstVar IntConstVar: Iconst { - char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); + char length[32]; - sprintf(length, "%zu", strlen(@1)); + snprintf(length, sizeof(length), "%zu", strlen(@1)); new_variable(@1, ECPGmake_simple_type(ECPGt_const, length, 0), 0); } | cvariable @@ -1484,37 +1496,39 @@ ECPGSetDescItem: descriptor_item '=' AllConstVar AllConstVar: ecpg_fconst { - char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); + char length[32]; - sprintf(length, "%zu", strlen(@1)); + snprintf(length, sizeof(length), "%zu", strlen(@1)); new_variable(@1, ECPGmake_simple_type(ECPGt_const, length, 0), 0); } | IntConstVar | '-' ecpg_fconst { - char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); - char *var = cat2_str(mm_strdup("-"), @2); + char length[32]; + char *var = cat2_str("-", @2); - sprintf(length, "%zu", strlen(var)); + snprintf(length, sizeof(length), "%zu", strlen(var)); new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0); @$ = var; } | '-' Iconst { - char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); - char *var = cat2_str(mm_strdup("-"), @2); + char length[32]; + char *var = cat2_str("-", @2); - sprintf(length, "%zu", strlen(var)); + snprintf(length, sizeof(length), "%zu", strlen(var)); new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0); @$ = var; } | ecpg_sconst { - char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); - char *var = @1 + 1; + char length[32]; + char *var; + /* Strip single quotes from ecpg_sconst */ + var = loc_strdup(@1 + 1); var[strlen(var) - 1] = '\0'; - sprintf(length, "%zu", strlen(var)); + snprintf(length, sizeof(length), "%zu", strlen(var)); new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0); @$ = var; } @@ -1587,9 +1601,9 @@ ECPGTypedef: TYPE_P add_typedef(@3, $6.index1, $6.index2, $5.type_enum, $5.type_dimension, $5.type_index, initializer, *@7 ? 1 : 0); if (auto_create_c == false) - @$ = cat_str(7, mm_strdup("/* exec sql type"), mm_strdup(@3), mm_strdup("is"), mm_strdup($5.type_str), mm_strdup($6.str), @7, mm_strdup("*/")); + @$ = cat_str(7, "/* exec sql type", @3, "is", $5.type_str, $6.str, @7, "*/"); else - @$ = cat_str(6, mm_strdup("typedef "), mm_strdup($5.type_str), *@7 ? mm_strdup("*") : mm_strdup(""), mm_strdup(@3), mm_strdup($6.str), mm_strdup(";")); + @$ = cat_str(6, "typedef ", $5.type_str, *@7 ? "*" : "", @3, $6.str, ";"); } ; @@ -1609,8 +1623,8 @@ ECPGVar: SQL_VAR ColLabel IS var_type opt_array_bounds opt_reference { struct variable *p = find_variable(@3); - char *dimension = $6.index1; - char *length = $6.index2; + const char *dimension = $6.index1; + const char *length = $6.index2; struct ECPGtype *type; if (($5.type_enum == ECPGt_struct || @@ -1619,7 +1633,8 @@ ECPGVar: SQL_VAR mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in EXEC SQL VAR command"); else { - adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *@7 ? 1 : 0, false); + adjust_array($5.type_enum, &dimension, &length, + $5.type_dimension, $5.type_index, *@7 ? 1 : 0, false); switch ($5.type_enum) { @@ -1653,9 +1668,9 @@ ECPGVar: SQL_VAR mmerror(PARSE_ERROR, ET_ERROR, "multidimensional arrays for simple data types are not supported"); if (atoi(dimension) < 0) - type = ECPGmake_simple_type($5.type_enum, mm_strdup("1"), 0); + type = ECPGmake_simple_type($5.type_enum, "1", 0); else - type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, mm_strdup("1"), 0), dimension); + type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, "1", 0), dimension); break; } @@ -1663,7 +1678,7 @@ ECPGVar: SQL_VAR p->type = type; } - @$ = cat_str(7, mm_strdup("/* exec sql var"), mm_strdup(@3), mm_strdup("is"), mm_strdup($5.type_str), mm_strdup($6.str), @7, mm_strdup("*/")); + @$ = cat_str(7, "/* exec sql var", @3, "is", $5.type_str, $6.str, @7, "*/"); } ; @@ -1673,83 +1688,83 @@ ECPGVar: SQL_VAR */ ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action { - when_error.code = $3.code; - when_error.command = $3.command; - @$ = cat_str(3, mm_strdup("/* exec sql whenever sqlerror "), $3.str, mm_strdup("; */")); + when_error.code = $3.code; + when_error.command = $3.command ? mm_strdup($3.command) : NULL; + @$ = cat_str(3, "/* exec sql whenever sqlerror ", $3.str, "; */"); } | SQL_WHENEVER NOT SQL_FOUND action { - when_nf.code = $4.code; - when_nf.command = $4.command; - @$ = cat_str(3, mm_strdup("/* exec sql whenever not found "), $4.str, mm_strdup("; */")); + when_nf.code = $4.code; + when_nf.command = $4.command ? mm_strdup($4.command) : NULL; + @$ = cat_str(3, "/* exec sql whenever not found ", $4.str, "; */"); } | SQL_WHENEVER SQL_SQLWARNING action { - when_warn.code = $3.code; - when_warn.command = $3.command; - @$ = cat_str(3, mm_strdup("/* exec sql whenever sql_warning "), $3.str, mm_strdup("; */")); + when_warn.code = $3.code; + when_warn.command = $3.command ? mm_strdup($3.command) : NULL; + @$ = cat_str(3, "/* exec sql whenever sql_warning ", $3.str, "; */"); } ; action: CONTINUE_P { - $$.code = W_NOTHING; - $$.command = NULL; - $$.str = mm_strdup("continue"); + $$.code = W_NOTHING; + $$.command = NULL; + $$.str = "continue"; } | SQL_SQLPRINT { - $$.code = W_SQLPRINT; - $$.command = NULL; - $$.str = mm_strdup("sqlprint"); + $$.code = W_SQLPRINT; + $$.command = NULL; + $$.str = "sqlprint"; } | SQL_STOP { - $$.code = W_STOP; - $$.command = NULL; - $$.str = mm_strdup("stop"); + $$.code = W_STOP; + $$.command = NULL; + $$.str = "stop"; } | SQL_GOTO name { - $$.code = W_GOTO; - $$.command = mm_strdup(@2); - $$.str = cat2_str(mm_strdup("goto "), @2); + $$.code = W_GOTO; + $$.command = loc_strdup(@2); + $$.str = cat2_str("goto ", @2); } | SQL_GO TO name { - $$.code = W_GOTO; - $$.command = mm_strdup(@3); - $$.str = cat2_str(mm_strdup("goto "), @3); + $$.code = W_GOTO; + $$.command = loc_strdup(@3); + $$.str = cat2_str("goto ", @3); } | DO name '(' c_args ')' { - $$.code = W_DO; - $$.command = cat_str(4, @2, mm_strdup("("), @4, mm_strdup(")")); - $$.str = cat2_str(mm_strdup("do"), mm_strdup($$.command)); + $$.code = W_DO; + $$.command = cat_str(4, @2, "(", @4, ")"); + $$.str = cat2_str("do", $$.command); } | DO SQL_BREAK { - $$.code = W_BREAK; - $$.command = NULL; - $$.str = mm_strdup("break"); + $$.code = W_BREAK; + $$.command = NULL; + $$.str = "break"; } | DO CONTINUE_P { - $$.code = W_CONTINUE; - $$.command = NULL; - $$.str = mm_strdup("continue"); + $$.code = W_CONTINUE; + $$.command = NULL; + $$.str = "continue"; } | CALL name '(' c_args ')' { - $$.code = W_DO; - $$.command = cat_str(4, @2, mm_strdup("("), @4, mm_strdup(")")); - $$.str = cat2_str(mm_strdup("call"), mm_strdup($$.command)); + $$.code = W_DO; + $$.command = cat_str(4, @2, "(", @4, ")"); + $$.str = cat2_str("call", $$.command); } | CALL name { - $$.code = W_DO; - $$.command = cat2_str(@2, mm_strdup("()")); - $$.str = cat2_str(mm_strdup("call"), mm_strdup($$.command)); + $$.code = W_DO; + $$.command = cat2_str(@2, "()"); + $$.str = cat2_str("call", $$.command); } ; @@ -1913,7 +1928,7 @@ ecpgstart: SQL_START { reset_variables(); pacounter = 1; - @$ = EMPTY; + @$ = ""; } ; @@ -1982,7 +1997,7 @@ cvariable: CVARIABLE * As long as multidimensional arrays are not implemented we have to * check for those here */ - char *ptr = @1; + const char *ptr = @1; int brace_open = 0, brace = false; @@ -2013,18 +2028,12 @@ cvariable: CVARIABLE ; ecpg_param: PARAM - { - @$ = make_name(); - } ; ecpg_bconst: BCONST ; ecpg_fconst: FCONST - { - @$ = make_name(); - } ; ecpg_sconst: SCONST @@ -2036,17 +2045,17 @@ ecpg_xconst: XCONST ecpg_ident: IDENT | CSTRING { - @$ = make3_str(mm_strdup("\""), @1, mm_strdup("\"")); + @$ = make3_str("\"", @1, "\""); } ; quoted_ident_stringvar: name { - @$ = make3_str(mm_strdup("\""), @1, mm_strdup("\"")); + @$ = make3_str("\"", @1, "\""); } | char_variable { - @$ = make3_str(mm_strdup("("), @1, mm_strdup(")")); + @$ = make3_str("(", @1, ")"); } ; @@ -2057,7 +2066,7 @@ quoted_ident_stringvar: name c_stuff_item: c_anything | '(' ')' { - @$ = mm_strdup("()"); + @$ = "()"; } | '(' c_stuff ')' ; @@ -2094,7 +2103,7 @@ c_anything: ecpg_ident | '-' | '/' | '%' - | NULL_P { @$ = mm_strdup("NULL"); } + | NULL_P { @$ = "NULL"; } | S_ADD | S_AND | S_ANYTHING @@ -2155,11 +2164,11 @@ DeallocateStmt: DEALLOCATE prepared_name } | DEALLOCATE ALL { - @$ = mm_strdup("all"); + @$ = "all"; } | DEALLOCATE PREPARE ALL { - @$ = mm_strdup("all"); + @$ = "all"; } ; @@ -2177,7 +2186,7 @@ Iresult: Iconst if (pg_strcasecmp(@1, "sizeof") != 0) mmerror(PARSE_ERROR, ET_ERROR, "operator not allowed in variable definition"); else - @$ = cat_str(4, @1, mm_strdup("("), $3.type_str, mm_strdup(")")); + @$ = cat_str(4, @1, "(", $3.type_str, ")"); } ; @@ -2190,7 +2199,7 @@ execute_rest: /* EMPTY */ ecpg_into: INTO into_list { /* always suppress this from the constructed string */ - @$ = EMPTY; + @$ = ""; } | into_descriptor ; diff --git a/src/interfaces/ecpg/preproc/output.c b/src/interfaces/ecpg/preproc/output.c index 8d2b6e7cb81..a18904f88bd 100644 --- a/src/interfaces/ecpg/preproc/output.c +++ b/src/interfaces/ecpg/preproc/output.c @@ -12,7 +12,6 @@ output_line_number(void) char *line = hashline_number(); fprintf(base_yyout, "%s", line); - free(line); } void @@ -100,7 +99,7 @@ hashline_number(void) ) { /* "* 2" here is for escaping '\' and '"' below */ - char *line = mm_alloc(strlen("\n#line %d \"%s\"\n") + sizeof(int) * CHAR_BIT * 10 / 3 + strlen(input_filename) * 2); + char *line = loc_alloc(strlen("\n#line %d \"%s\"\n") + sizeof(int) * CHAR_BIT * 10 / 3 + strlen(input_filename) * 2); char *src, *dest; @@ -119,7 +118,7 @@ hashline_number(void) return line; } - return EMPTY; + return ""; } static char *ecpg_statement_type_name[] = { diff --git a/src/interfaces/ecpg/preproc/parser.c b/src/interfaces/ecpg/preproc/parser.c index ca0dead26d0..373c93fc04a 100644 --- a/src/interfaces/ecpg/preproc/parser.c +++ b/src/interfaces/ecpg/preproc/parser.c @@ -204,7 +204,7 @@ filtered_base_yylex(void) /* Combine 3 tokens into 1 */ base_yylval.str = psprintf("%s UESCAPE %s", base_yylval.str, escstr); - base_yylloc = mm_strdup(base_yylval.str); + base_yylloc = loc_strdup(base_yylval.str); /* Clear have_lookahead, thereby consuming all three tokens */ have_lookahead = false; @@ -254,11 +254,11 @@ base_yylex_location(void) case UIDENT: case IP: /* Duplicate the value */ - base_yylloc = mm_strdup(base_yylval.str); + base_yylloc = loc_strdup(base_yylval.str); break; default: /* Else just use the input, i.e., yytext */ - base_yylloc = mm_strdup(base_yytext); + base_yylloc = loc_strdup(base_yytext); /* Apply an ASCII-only downcasing */ for (unsigned char *ptr = (unsigned char *) base_yylloc; *ptr; ptr++) { diff --git a/src/interfaces/ecpg/preproc/preproc_extern.h b/src/interfaces/ecpg/preproc/preproc_extern.h index 29329ccd891..a60b0381fbb 100644 --- a/src/interfaces/ecpg/preproc/preproc_extern.h +++ b/src/interfaces/ecpg/preproc/preproc_extern.h @@ -13,12 +13,11 @@ /* defines */ #define STRUCT_DEPTH 128 -#define EMPTY mm_strdup("") /* * "Location tracking" support --- see ecpg.header for more comments. */ -typedef char *YYLTYPE; +typedef const char *YYLTYPE; #define YYLTYPE_IS_DECLARED 1 @@ -82,22 +81,25 @@ extern int base_yylex(void); extern void base_yyerror(const char *error); extern void *mm_alloc(size_t size); extern char *mm_strdup(const char *string); -extern char *cat2_str(char *str1, char *str2); +extern void *loc_alloc(size_t size); +extern char *loc_strdup(const char *string); +extern void reclaim_local_storage(void); +extern char *cat2_str(const char *str1, const char *str2); extern char *cat_str(int count,...); -extern char *make2_str(char *str1, char *str2); -extern char *make3_str(char *str1, char *str2, char *str3); +extern char *make2_str(const char *str1, const char *str2); +extern char *make3_str(const char *str1, const char *str2, const char *str3); extern void mmerror(int error_code, enum errortype type, const char *error,...) pg_attribute_printf(3, 4); extern void mmfatal(int error_code, const char *error,...) pg_attribute_printf(2, 3) pg_attribute_noreturn(); -extern void output_get_descr_header(char *desc_name); -extern void output_get_descr(char *desc_name, char *index); -extern void output_set_descr_header(char *desc_name); -extern void output_set_descr(char *desc_name, char *index); -extern void push_assignment(char *var, enum ECPGdtype value); -extern struct variable *find_variable(char *name); +extern void output_get_descr_header(const char *desc_name); +extern void output_get_descr(const char *desc_name, const char *index); +extern void output_set_descr_header(const char *desc_name); +extern void output_set_descr(const char *desc_name, const char *index); +extern void push_assignment(const char *var, enum ECPGdtype value); +extern struct variable *find_variable(const char *name); extern void whenever_action(int mode); -extern void add_descriptor(char *name, char *connection); -extern void drop_descriptor(char *name, char *connection); -extern struct descriptor *lookup_descriptor(char *name, char *connection); +extern void add_descriptor(const char *name, const char *connection); +extern void drop_descriptor(const char *name, const char *connection); +extern struct descriptor *lookup_descriptor(const char *name, const char *connection); extern struct variable *descriptor_variable(const char *name, int input); extern struct variable *sqlda_variable(const char *name); extern void add_variable_to_head(struct arguments **list, @@ -109,9 +111,9 @@ extern void add_variable_to_tail(struct arguments **list, extern void remove_variable_from_list(struct arguments **list, struct variable *var); extern void dump_variables(struct arguments *list, int mode); extern struct typedefs *get_typedef(const char *name, bool noerror); -extern void adjust_array(enum ECPGttype type_enum, char **dimension, - char **length, char *type_dimension, - char *type_index, int pointer_len, +extern void adjust_array(enum ECPGttype type_enum, const char **dimension, + const char **length, const char *type_dimension, + const char *type_index, int pointer_len, bool type_definition); extern void reset_variables(void); extern void check_indicator(struct ECPGtype *var); diff --git a/src/interfaces/ecpg/preproc/type.c b/src/interfaces/ecpg/preproc/type.c index 5610a8dc76b..7f52521dbf1 100644 --- a/src/interfaces/ecpg/preproc/type.c +++ b/src/interfaces/ecpg/preproc/type.c @@ -69,13 +69,13 @@ ECPGmake_struct_member(const char *name, struct ECPGtype *type, struct ECPGstruc } struct ECPGtype * -ECPGmake_simple_type(enum ECPGttype type, char *size, int counter) +ECPGmake_simple_type(enum ECPGttype type, const char *size, int counter) { struct ECPGtype *ne = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype)); ne->type = type; ne->type_name = NULL; - ne->size = size; + ne->size = mm_strdup(size); ne->u.element = NULL; ne->struct_sizeof = NULL; ne->counter = counter; /* only needed for varchar and bytea */ @@ -84,7 +84,7 @@ ECPGmake_simple_type(enum ECPGttype type, char *size, int counter) } struct ECPGtype * -ECPGmake_array_type(struct ECPGtype *type, char *size) +ECPGmake_array_type(struct ECPGtype *type, const char *size) { struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_array, size, 0); @@ -96,7 +96,7 @@ ECPGmake_array_type(struct ECPGtype *type, char *size) struct ECPGtype * ECPGmake_struct_type(struct ECPGstruct_member *rm, enum ECPGttype type, char *type_name, char *struct_sizeof) { - struct ECPGtype *ne = ECPGmake_simple_type(type, mm_strdup("1"), 0); + struct ECPGtype *ne = ECPGmake_simple_type(type, "1", 0); ne->type_name = mm_strdup(type_name); ne->u.members = ECPGstruct_member_dup(rm); diff --git a/src/interfaces/ecpg/preproc/type.h b/src/interfaces/ecpg/preproc/type.h index ce2124361fd..90126551d19 100644 --- a/src/interfaces/ecpg/preproc/type.h +++ b/src/interfaces/ecpg/preproc/type.h @@ -35,8 +35,8 @@ struct ECPGtype /* Everything is malloced. */ void ECPGmake_struct_member(const char *name, struct ECPGtype *type, struct ECPGstruct_member **start); -struct ECPGtype *ECPGmake_simple_type(enum ECPGttype type, char *size, int counter); -struct ECPGtype *ECPGmake_array_type(struct ECPGtype *type, char *size); +struct ECPGtype *ECPGmake_simple_type(enum ECPGttype type, const char *size, int counter); +struct ECPGtype *ECPGmake_array_type(struct ECPGtype *type, const char *size); struct ECPGtype *ECPGmake_struct_type(struct ECPGstruct_member *rm, enum ECPGttype type, char *type_name, char *struct_sizeof); @@ -93,28 +93,28 @@ struct when struct index { - char *index1; - char *index2; - char *str; + const char *index1; + const char *index2; + const char *str; }; struct su_symbol { - char *su; - char *symbol; + const char *su; + const char *symbol; }; struct prep { - char *name; - char *stmt; - char *type; + const char *name; + const char *stmt; + const char *type; }; struct exec { - char *name; - char *type; + const char *name; + const char *type; }; struct this_type @@ -221,14 +221,14 @@ enum errortype struct fetch_desc { - char *str; - char *name; + const char *str; + const char *name; }; struct describe { int input; - char *stmt_name; + const char *stmt_name; }; #endif /* _ECPG_PREPROC_TYPE_H */ diff --git a/src/interfaces/ecpg/preproc/util.c b/src/interfaces/ecpg/preproc/util.c index cb1eca7f3cb..f177df32488 100644 --- a/src/interfaces/ecpg/preproc/util.c +++ b/src/interfaces/ecpg/preproc/util.c @@ -104,33 +104,117 @@ mm_strdup(const char *string) return new; } + /* - * String concatenation + * "Local" memory management support + * + * These functions manage memory that is only needed for a short time + * (processing of one input statement) within the ecpg grammar. + * Data allocated with these is not meant to be freed separately; + * rather it's freed by calling reclaim_local_storage() at the end + * of each statement cycle. */ +typedef struct loc_chunk +{ + struct loc_chunk *next; /* list link */ + unsigned int chunk_used; /* index of first unused byte in data[] */ + unsigned int chunk_avail; /* # bytes still available in data[] */ + char data[FLEXIBLE_ARRAY_MEMBER]; /* actual storage */ +} loc_chunk; + +#define LOC_CHUNK_OVERHEAD MAXALIGN(offsetof(loc_chunk, data)) +#define LOC_CHUNK_MIN_SIZE 8192 + +/* Head of list of loc_chunks */ +static loc_chunk *loc_chunks = NULL; + /* - * Concatenate 2 strings, inserting a space between them unless either is empty + * Allocate local space of the requested size. * - * The input strings are freed. + * Exits on OOM. + */ +void * +loc_alloc(size_t size) +{ + void *result; + loc_chunk *cur_chunk = loc_chunks; + + /* Ensure all allocations are adequately aligned */ + size = MAXALIGN(size); + + /* Need a new chunk? */ + if (cur_chunk == NULL || size > cur_chunk->chunk_avail) + { + size_t chunk_size = Max(size, LOC_CHUNK_MIN_SIZE); + + cur_chunk = mm_alloc(chunk_size + LOC_CHUNK_OVERHEAD); + /* Depending on alignment rules, we could waste a bit here */ + cur_chunk->chunk_used = LOC_CHUNK_OVERHEAD - offsetof(loc_chunk, data); + cur_chunk->chunk_avail = chunk_size; + /* New chunk becomes the head of the list */ + cur_chunk->next = loc_chunks; + loc_chunks = cur_chunk; + } + + result = cur_chunk->data + cur_chunk->chunk_used; + cur_chunk->chunk_used += size; + cur_chunk->chunk_avail -= size; + return result; +} + +/* + * Copy given string into local storage + */ +char * +loc_strdup(const char *string) +{ + char *result = loc_alloc(strlen(string) + 1); + + strcpy(result, string); + return result; +} + +/* + * Reclaim local storage when appropriate + */ +void +reclaim_local_storage(void) +{ + loc_chunk *cur_chunk, + *next_chunk; + + for (cur_chunk = loc_chunks; cur_chunk; cur_chunk = next_chunk) + { + next_chunk = cur_chunk->next; + free(cur_chunk); + } + loc_chunks = NULL; +} + + +/* + * String concatenation support routines. These return "local" (transient) + * storage. + */ + +/* + * Concatenate 2 strings, inserting a space between them unless either is empty */ char * -cat2_str(char *str1, char *str2) +cat2_str(const char *str1, const char *str2) { - char *res_str = (char *) mm_alloc(strlen(str1) + strlen(str2) + 2); + char *res_str = (char *) loc_alloc(strlen(str1) + strlen(str2) + 2); strcpy(res_str, str1); if (strlen(str1) != 0 && strlen(str2) != 0) strcat(res_str, " "); strcat(res_str, str2); - free(str1); - free(str2); return res_str; } /* * Concatenate N strings, inserting spaces between them unless they are empty - * - * The input strings are freed. */ char * cat_str(int count,...) @@ -154,36 +238,27 @@ cat_str(int count,...) /* * Concatenate 2 strings, with no space between - * - * The input strings are freed. */ char * -make2_str(char *str1, char *str2) +make2_str(const char *str1, const char *str2) { - char *res_str = (char *) mm_alloc(strlen(str1) + strlen(str2) + 1); + char *res_str = (char *) loc_alloc(strlen(str1) + strlen(str2) + 1); strcpy(res_str, str1); strcat(res_str, str2); - free(str1); - free(str2); return res_str; } /* * Concatenate 3 strings, with no space between - * - * The input strings are freed. */ char * -make3_str(char *str1, char *str2, char *str3) +make3_str(const char *str1, const char *str2, const char *str3) { - char *res_str = (char *) mm_alloc(strlen(str1) + strlen(str2) + strlen(str3) + 1); + char *res_str = (char *) loc_alloc(strlen(str1) + strlen(str2) + strlen(str3) + 1); strcpy(res_str, str1); strcat(res_str, str2); strcat(res_str, str3); - free(str1); - free(str2); - free(str3); return res_str; } diff --git a/src/interfaces/ecpg/preproc/variable.c b/src/interfaces/ecpg/preproc/variable.c index b23ed5edf46..6b87d5ff3d9 100644 --- a/src/interfaces/ecpg/preproc/variable.c +++ b/src/interfaces/ecpg/preproc/variable.c @@ -22,7 +22,7 @@ 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) +find_struct_member(const char *name, char *str, struct ECPGstruct_member *members, int brace_level) { char *next = strpbrk(++str, ".-["), *end, @@ -123,7 +123,7 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member *members, int } static struct variable * -find_struct(char *name, char *next, char *end) +find_struct(const char *name, char *next, char *end) { struct variable *p; char c = *next; @@ -174,7 +174,7 @@ find_struct(char *name, char *next, char *end) } static struct variable * -find_simple(char *name) +find_simple(const char *name) { struct variable *p; @@ -190,7 +190,7 @@ find_simple(char *name) /* Note that this function will end the program in case of an unknown */ /* variable */ struct variable * -find_variable(char *name) +find_variable(const char *name) { char *next, *end; @@ -513,7 +513,10 @@ get_typedef(const char *name, bool noerror) } void -adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *type_dimension, char *type_index, int pointer_len, bool type_definition) +adjust_array(enum ECPGttype type_enum, + const char **dimension, const char **length, + const char *type_dimension, const char *type_index, + int pointer_len, bool type_definition) { if (atoi(type_index) >= 0) { @@ -556,7 +559,7 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty if (pointer_len) { *length = *dimension; - *dimension = mm_strdup("0"); + *dimension = "0"; } if (atoi(*length) >= 0) @@ -567,13 +570,13 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty case ECPGt_bytea: /* pointer has to get dimension 0 */ if (pointer_len) - *dimension = mm_strdup("0"); + *dimension = "0"; /* one index is the string length */ if (atoi(*length) < 0) { *length = *dimension; - *dimension = mm_strdup("-1"); + *dimension = "-1"; } break; @@ -583,13 +586,13 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty /* char ** */ if (pointer_len == 2) { - *length = *dimension = mm_strdup("0"); + *length = *dimension = "0"; break; } /* pointer has to get length 0 */ if (pointer_len == 1) - *length = mm_strdup("0"); + *length = "0"; /* one index is the string length */ if (atoi(*length) < 0) @@ -604,13 +607,13 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty * do not change this for typedefs since it will be * changed later on when the variable is defined */ - *length = mm_strdup("1"); + *length = "1"; else if (strcmp(*dimension, "0") == 0) - *length = mm_strdup("-1"); + *length = "-1"; else *length = *dimension; - *dimension = mm_strdup("-1"); + *dimension = "-1"; } break; default: @@ -618,7 +621,7 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty if (pointer_len) { *length = *dimension; - *dimension = mm_strdup("0"); + *dimension = "0"; } if (atoi(*length) >= 0) diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index a65e1c07c5d..57de1acff3a 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -3602,6 +3602,7 @@ libpq_source line_t lineno_t list_sort_comparator +loc_chunk local_relopt local_relopts local_source