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
This commit is contained in:
parent
f18231e817
commit
1acd0f5527
@ -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;
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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];
|
||||
|
||||
snprintf(buf, sizeof(buf), "$%d", pacounter++);
|
||||
result = cat_str(3, result, buf, " , ");
|
||||
}
|
||||
|
||||
/* removed the trailing " ," */
|
||||
|
||||
/* 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(<counter>)" */
|
||||
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(<counter>)" */
|
||||
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(<counter>, <pointer>. <line
|
||||
* number>)"
|
||||
*/
|
||||
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;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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[] = {
|
||||
|
@ -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 <str> 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++)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
/*
|
||||
* Allocate local space of the requested size.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* The input strings are freed.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -3602,6 +3602,7 @@ libpq_source
|
||||
line_t
|
||||
lineno_t
|
||||
list_sort_comparator
|
||||
loc_chunk
|
||||
local_relopt
|
||||
local_relopts
|
||||
local_source
|
||||
|
Loading…
x
Reference in New Issue
Block a user