mirror of
https://github.com/postgres/postgres.git
synced 2025-07-11 10:01:57 +03:00
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:
@ -18,13 +18,12 @@
|
|||||||
static struct assignment *assignments;
|
static struct assignment *assignments;
|
||||||
|
|
||||||
void
|
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));
|
struct assignment *new = (struct assignment *) mm_alloc(sizeof(struct assignment));
|
||||||
|
|
||||||
new->next = assignments;
|
new->next = assignments;
|
||||||
new->variable = mm_alloc(strlen(var) + 1);
|
new->variable = mm_strdup(var);
|
||||||
strcpy(new->variable, var);
|
|
||||||
new->value = value;
|
new->value = value;
|
||||||
assignments = new;
|
assignments = new;
|
||||||
}
|
}
|
||||||
@ -73,7 +72,7 @@ ECPGnumeric_lvalue(char *name)
|
|||||||
static struct descriptor *descriptors;
|
static struct descriptor *descriptors;
|
||||||
|
|
||||||
void
|
void
|
||||||
add_descriptor(char *name, char *connection)
|
add_descriptor(const char *name, const char *connection)
|
||||||
{
|
{
|
||||||
struct descriptor *new;
|
struct descriptor *new;
|
||||||
|
|
||||||
@ -83,20 +82,16 @@ add_descriptor(char *name, char *connection)
|
|||||||
new = (struct descriptor *) mm_alloc(sizeof(struct descriptor));
|
new = (struct descriptor *) mm_alloc(sizeof(struct descriptor));
|
||||||
|
|
||||||
new->next = descriptors;
|
new->next = descriptors;
|
||||||
new->name = mm_alloc(strlen(name) + 1);
|
new->name = mm_strdup(name);
|
||||||
strcpy(new->name, name);
|
|
||||||
if (connection)
|
if (connection)
|
||||||
{
|
new->connection = mm_strdup(connection);
|
||||||
new->connection = mm_alloc(strlen(connection) + 1);
|
|
||||||
strcpy(new->connection, connection);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
new->connection = connection;
|
new->connection = NULL;
|
||||||
descriptors = new;
|
descriptors = new;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
drop_descriptor(char *name, char *connection)
|
drop_descriptor(const char *name, const char *connection)
|
||||||
{
|
{
|
||||||
struct descriptor *i;
|
struct descriptor *i;
|
||||||
struct descriptor **lastptr = &descriptors;
|
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);
|
mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to the default connection does not exist", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct descriptor
|
struct descriptor *
|
||||||
*
|
lookup_descriptor(const char *name, const char *connection)
|
||||||
lookup_descriptor(char *name, char *connection)
|
|
||||||
{
|
{
|
||||||
struct descriptor *i;
|
struct descriptor *i;
|
||||||
|
|
||||||
@ -159,7 +153,7 @@ lookup_descriptor(char *name, char *connection)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
output_get_descr_header(char *desc_name)
|
output_get_descr_header(const char *desc_name)
|
||||||
{
|
{
|
||||||
struct assignment *results;
|
struct assignment *results;
|
||||||
|
|
||||||
@ -178,7 +172,7 @@ output_get_descr_header(char *desc_name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
output_get_descr(char *desc_name, char *index)
|
output_get_descr(const char *desc_name, const char *index)
|
||||||
{
|
{
|
||||||
struct assignment *results;
|
struct assignment *results;
|
||||||
|
|
||||||
@ -211,7 +205,7 @@ output_get_descr(char *desc_name, char *index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
output_set_descr_header(char *desc_name)
|
output_set_descr_header(const char *desc_name)
|
||||||
{
|
{
|
||||||
struct assignment *results;
|
struct assignment *results;
|
||||||
|
|
||||||
@ -272,7 +266,7 @@ descriptor_item_name(enum ECPGdtype itemcode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
output_set_descr(char *desc_name, char *index)
|
output_set_descr(const char *desc_name, const char *index)
|
||||||
{
|
{
|
||||||
struct assignment *results;
|
struct assignment *results;
|
||||||
|
|
||||||
|
@ -45,18 +45,16 @@ ECPG: stmtExecuteStmt block
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* case of ecpg_ident or CSTRING */
|
/* case of ecpg_ident or CSTRING */
|
||||||
char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
|
char length[32];
|
||||||
char *str = mm_strdup($1.name + 1);
|
char *str;
|
||||||
|
|
||||||
/*
|
/* Remove double quotes from name */
|
||||||
* It must be cut off double quotation because new_variable()
|
str = loc_strdup($1.name + 1);
|
||||||
* double-quotes.
|
|
||||||
*/
|
|
||||||
str[strlen(str) - 1] = '\0';
|
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);
|
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
|
ECPG: stmtPrepareStmt block
|
||||||
@ -66,7 +64,7 @@ ECPG: stmtPrepareStmt block
|
|||||||
output_prepare_statement($1.name, $1.stmt);
|
output_prepare_statement($1.name, $1.stmt);
|
||||||
else if (strlen($1.type) == 0)
|
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);
|
output_prepare_statement($1.name, stmt);
|
||||||
}
|
}
|
||||||
@ -77,18 +75,16 @@ ECPG: stmtPrepareStmt block
|
|||||||
add_variable_to_tail(&argsinsert, find_variable($1.name), &no_indicator);
|
add_variable_to_tail(&argsinsert, find_variable($1.name), &no_indicator);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
|
char length[32];
|
||||||
char *str = mm_strdup($1.name + 1);
|
char *str;
|
||||||
|
|
||||||
/*
|
/* Remove double quotes from name */
|
||||||
* It must be cut off double quotation because new_variable()
|
str = loc_strdup($1.name + 1);
|
||||||
* double-quotes.
|
|
||||||
*/
|
|
||||||
str[strlen(str) - 1] = '\0';
|
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);
|
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
|
ECPG: stmtTransactionStmt block
|
||||||
@ -142,8 +138,6 @@ ECPG: stmtViewStmt rule
|
|||||||
fputs("ECPGt_EORT);", base_yyout);
|
fputs("ECPGt_EORT);", base_yyout);
|
||||||
fprintf(base_yyout, "}");
|
fprintf(base_yyout, "}");
|
||||||
output_line_number();
|
output_line_number();
|
||||||
|
|
||||||
free($1.stmt_name);
|
|
||||||
}
|
}
|
||||||
| ECPGDisconnect
|
| ECPGDisconnect
|
||||||
{
|
{
|
||||||
@ -175,8 +169,6 @@ ECPG: stmtViewStmt rule
|
|||||||
{
|
{
|
||||||
lookup_descriptor($1.name, connection);
|
lookup_descriptor($1.name, connection);
|
||||||
output_get_descr($1.name, $1.str);
|
output_get_descr($1.name, $1.str);
|
||||||
free($1.name);
|
|
||||||
free($1.str);
|
|
||||||
}
|
}
|
||||||
| ECPGGetDescriptorHeader
|
| ECPGGetDescriptorHeader
|
||||||
{
|
{
|
||||||
@ -190,7 +182,7 @@ ECPG: stmtViewStmt rule
|
|||||||
if ((ptr = add_additional_variables(@1, true)) != NULL)
|
if ((ptr = add_additional_variables(@1, true)) != NULL)
|
||||||
{
|
{
|
||||||
connection = ptr->connection ? mm_strdup(ptr->connection) : 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;
|
ptr->opened = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -211,8 +203,6 @@ ECPG: stmtViewStmt rule
|
|||||||
{
|
{
|
||||||
lookup_descriptor($1.name, connection);
|
lookup_descriptor($1.name, connection);
|
||||||
output_set_descr($1.name, $1.str);
|
output_set_descr($1.name, $1.str);
|
||||||
free($1.name);
|
|
||||||
free($1.str);
|
|
||||||
}
|
}
|
||||||
| ECPGSetDescriptorHeader
|
| ECPGSetDescriptorHeader
|
||||||
{
|
{
|
||||||
@ -243,9 +233,9 @@ ECPG: stmtViewStmt rule
|
|||||||
}
|
}
|
||||||
ECPG: where_or_current_clauseWHERECURRENT_POFcursor_name block
|
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
|
ECPG: CopyStmtCOPYopt_binaryqualified_nameopt_column_listcopy_fromopt_programcopy_file_namecopy_delimiteropt_withcopy_optionswhere_clause addon
|
||||||
if (strcmp(@6, "from") == 0 &&
|
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");
|
mmerror(PARSE_ERROR, ET_WARNING, "COPY FROM STDIN is not implemented");
|
||||||
ECPG: var_valueNumericOnly addon
|
ECPG: var_valueNumericOnly addon
|
||||||
if (@1[0] == '$')
|
if (@1[0] == '$')
|
||||||
@$ = mm_strdup("$0");
|
@$ = "$0";
|
||||||
ECPG: fetch_argscursor_name addon
|
ECPG: fetch_argscursor_name addon
|
||||||
struct cursor *ptr = add_additional_variables(@1, false);
|
struct cursor *ptr = add_additional_variables(@1, false);
|
||||||
|
|
||||||
if (ptr->connection)
|
if (ptr->connection)
|
||||||
connection = mm_strdup(ptr->connection);
|
connection = mm_strdup(ptr->connection);
|
||||||
if (@1[0] == ':')
|
if (@1[0] == ':')
|
||||||
@$ = mm_strdup("$0");
|
@$ = "$0";
|
||||||
ECPG: fetch_argsfrom_incursor_name addon
|
ECPG: fetch_argsfrom_incursor_name addon
|
||||||
struct cursor *ptr = add_additional_variables(@2, false);
|
struct cursor *ptr = add_additional_variables(@2, false);
|
||||||
|
|
||||||
if (ptr->connection)
|
if (ptr->connection)
|
||||||
connection = mm_strdup(ptr->connection);
|
connection = mm_strdup(ptr->connection);
|
||||||
if (@2[0] == ':')
|
if (@2[0] == ':')
|
||||||
@$ = cat2_str(mm_strdup(@1), mm_strdup("$0"));
|
@$ = cat2_str(@1, "$0");
|
||||||
ECPG: fetch_argsNEXTopt_from_incursor_name addon
|
ECPG: fetch_argsNEXTopt_from_incursor_name addon
|
||||||
ECPG: fetch_argsPRIORopt_from_incursor_name addon
|
ECPG: fetch_argsPRIORopt_from_incursor_name addon
|
||||||
ECPG: fetch_argsFIRST_Popt_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)
|
if (ptr->connection)
|
||||||
connection = mm_strdup(ptr->connection);
|
connection = mm_strdup(ptr->connection);
|
||||||
if (@3[0] == ':')
|
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
|
ECPG: fetch_argsSignedIconstopt_from_incursor_name addon
|
||||||
struct cursor *ptr = add_additional_variables(@3, false);
|
struct cursor *ptr = add_additional_variables(@3, false);
|
||||||
bool replace = false;
|
bool replace = false;
|
||||||
@ -287,16 +277,16 @@ ECPG: fetch_argsSignedIconstopt_from_incursor_name addon
|
|||||||
connection = mm_strdup(ptr->connection);
|
connection = mm_strdup(ptr->connection);
|
||||||
if (@3[0] == ':')
|
if (@3[0] == ':')
|
||||||
{
|
{
|
||||||
@3 = mm_strdup("$0");
|
@3 = "$0";
|
||||||
replace = true;
|
replace = true;
|
||||||
}
|
}
|
||||||
if (@1[0] == '$')
|
if (@1[0] == '$')
|
||||||
{
|
{
|
||||||
@1 = mm_strdup("$0");
|
@1 = "$0";
|
||||||
replace = true;
|
replace = true;
|
||||||
}
|
}
|
||||||
if (replace)
|
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_argsFORWARDALLopt_from_incursor_name addon
|
||||||
ECPG: fetch_argsBACKWARDALLopt_from_incursor_name addon
|
ECPG: fetch_argsBACKWARDALLopt_from_incursor_name addon
|
||||||
struct cursor *ptr = add_additional_variables(@4, false);
|
struct cursor *ptr = add_additional_variables(@4, false);
|
||||||
@ -304,7 +294,7 @@ ECPG: fetch_argsBACKWARDALLopt_from_incursor_name addon
|
|||||||
if (ptr->connection)
|
if (ptr->connection)
|
||||||
connection = mm_strdup(ptr->connection);
|
connection = mm_strdup(ptr->connection);
|
||||||
if (@4[0] == ':')
|
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_argsABSOLUTE_PSignedIconstopt_from_incursor_name addon
|
||||||
ECPG: fetch_argsRELATIVE_PSignedIconstopt_from_incursor_name addon
|
ECPG: fetch_argsRELATIVE_PSignedIconstopt_from_incursor_name addon
|
||||||
ECPG: fetch_argsFORWARDSignedIconstopt_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);
|
connection = mm_strdup(ptr->connection);
|
||||||
if (@4[0] == ':')
|
if (@4[0] == ':')
|
||||||
{
|
{
|
||||||
@4 = mm_strdup("$0");
|
@4 = "$0";
|
||||||
replace = true;
|
replace = true;
|
||||||
}
|
}
|
||||||
if (@2[0] == '$')
|
if (@2[0] == '$')
|
||||||
{
|
{
|
||||||
@2 = mm_strdup("$0");
|
@2 = "$0";
|
||||||
replace = true;
|
replace = true;
|
||||||
}
|
}
|
||||||
if (replace)
|
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
|
ECPG: cursor_namename block
|
||||||
| char_civar
|
| char_civar
|
||||||
{
|
{
|
||||||
char *curname = mm_alloc(strlen(@1) + 2);
|
char *curname = loc_alloc(strlen(@1) + 2);
|
||||||
|
|
||||||
sprintf(curname, ":%s", @1);
|
sprintf(curname, ":%s", @1);
|
||||||
@$ = curname;
|
@$ = curname;
|
||||||
@ -367,7 +357,7 @@ ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectSt
|
|||||||
{
|
{
|
||||||
struct cursor *ptr,
|
struct cursor *ptr,
|
||||||
*this;
|
*this;
|
||||||
char *cursor_marker = @2[0] == ':' ? mm_strdup("$0") : mm_strdup(@2);
|
const char *cursor_marker = @2[0] == ':' ? "$0" : @2;
|
||||||
char *comment,
|
char *comment,
|
||||||
*c1,
|
*c1,
|
||||||
*c2;
|
*c2;
|
||||||
@ -394,7 +384,7 @@ ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectSt
|
|||||||
this->function = (current_function ? mm_strdup(current_function) : NULL);
|
this->function = (current_function ? mm_strdup(current_function) : NULL);
|
||||||
this->connection = connection ? mm_strdup(connection) : NULL;
|
this->connection = connection ? mm_strdup(connection) : NULL;
|
||||||
this->opened = false;
|
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 = argsinsert;
|
||||||
this->argsinsert_oos = NULL;
|
this->argsinsert_oos = NULL;
|
||||||
this->argsresult = argsresult;
|
this->argsresult = argsresult;
|
||||||
@ -402,20 +392,20 @@ ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectSt
|
|||||||
argsinsert = argsresult = NULL;
|
argsinsert = argsresult = NULL;
|
||||||
cur = this;
|
cur = this;
|
||||||
|
|
||||||
c1 = mm_strdup(this->command);
|
c1 = loc_strdup(this->command);
|
||||||
if ((c2 = strstr(c1, "*/")) != NULL)
|
while ((c2 = strstr(c1, "*/")) != NULL)
|
||||||
{
|
{
|
||||||
/* We put this text into a comment, so we better remove [*][/]. */
|
/* We put this text into a comment, so we better remove [*][/]. */
|
||||||
c2[0] = '.';
|
c2[0] = '.';
|
||||||
c2[1] = '.';
|
c2[1] = '.';
|
||||||
}
|
}
|
||||||
comment = cat_str(3, mm_strdup("/*"), c1, mm_strdup("*/"));
|
comment = cat_str(3, "/*", c1, "*/");
|
||||||
|
|
||||||
@$ = cat2_str(adjust_outofscope_cursor_vars(this), comment);
|
@$ = cat2_str(adjust_outofscope_cursor_vars(this), comment);
|
||||||
}
|
}
|
||||||
ECPG: ClosePortalStmtCLOSEcursor_name block
|
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;
|
struct cursor *ptr = NULL;
|
||||||
|
|
||||||
for (ptr = cur; ptr != NULL; ptr = ptr->next)
|
for (ptr = cur; ptr != NULL; ptr = ptr->next)
|
||||||
@ -427,23 +417,23 @@ ECPG: ClosePortalStmtCLOSEcursor_name block
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@$ = cat2_str(mm_strdup("close"), cursor_marker);
|
@$ = cat2_str("close", cursor_marker);
|
||||||
}
|
}
|
||||||
ECPG: opt_hold block
|
ECPG: opt_hold block
|
||||||
{
|
{
|
||||||
if (compat == ECPG_COMPAT_INFORMIX_SE && autocommit)
|
if (compat == ECPG_COMPAT_INFORMIX_SE && autocommit)
|
||||||
@$ = mm_strdup("with hold");
|
@$ = "with hold";
|
||||||
else
|
else
|
||||||
@$ = EMPTY;
|
@$ = "";
|
||||||
}
|
}
|
||||||
ECPG: into_clauseINTOOptTempTableName block
|
ECPG: into_clauseINTOOptTempTableName block
|
||||||
{
|
{
|
||||||
FoundInto = 1;
|
FoundInto = 1;
|
||||||
@$ = cat2_str(mm_strdup("into"), @2);
|
@$ = cat2_str("into", @2);
|
||||||
}
|
}
|
||||||
| ecpg_into
|
| ecpg_into
|
||||||
{
|
{
|
||||||
@$ = EMPTY;
|
@$ = "";
|
||||||
}
|
}
|
||||||
ECPG: TypenameSimpleTypenameopt_array_bounds block
|
ECPG: TypenameSimpleTypenameopt_array_bounds block
|
||||||
{
|
{
|
||||||
@ -451,37 +441,33 @@ ECPG: TypenameSimpleTypenameopt_array_bounds block
|
|||||||
}
|
}
|
||||||
ECPG: TypenameSETOFSimpleTypenameopt_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
|
ECPG: opt_array_boundsopt_array_bounds'['']' block
|
||||||
{
|
{
|
||||||
$$.index1 = $1.index1;
|
$$.index1 = $1.index1;
|
||||||
$$.index2 = $1.index2;
|
$$.index2 = $1.index2;
|
||||||
if (strcmp($$.index1, "-1") == 0)
|
if (strcmp($$.index1, "-1") == 0)
|
||||||
$$.index1 = mm_strdup("0");
|
$$.index1 = "0";
|
||||||
else if (strcmp($1.index2, "-1") == 0)
|
else if (strcmp($1.index2, "-1") == 0)
|
||||||
$$.index2 = mm_strdup("0");
|
$$.index2 = "0";
|
||||||
$$.str = cat_str(2, $1.str, mm_strdup("[]"));
|
$$.str = cat_str(2, $1.str, "[]");
|
||||||
}
|
}
|
||||||
| opt_array_bounds '[' Iresult ']'
|
| opt_array_bounds '[' Iresult ']'
|
||||||
{
|
{
|
||||||
$$.index1 = $1.index1;
|
$$.index1 = $1.index1;
|
||||||
$$.index2 = $1.index2;
|
$$.index2 = $1.index2;
|
||||||
if (strcmp($1.index1, "-1") == 0)
|
if (strcmp($1.index1, "-1") == 0)
|
||||||
$$.index1 = mm_strdup(@3);
|
$$.index1 = @3;
|
||||||
else if (strcmp($1.index2, "-1") == 0)
|
else if (strcmp($1.index2, "-1") == 0)
|
||||||
$$.index2 = mm_strdup(@3);
|
$$.index2 = @3;
|
||||||
$$.str = cat_str(4, $1.str, mm_strdup("["), @3, mm_strdup("]"));
|
$$.str = cat_str(4, $1.str, "[", @3, "]");
|
||||||
}
|
}
|
||||||
ECPG: opt_array_bounds block
|
ECPG: opt_array_bounds block
|
||||||
{
|
{
|
||||||
$$.index1 = mm_strdup("-1");
|
$$.index1 = "-1";
|
||||||
$$.index2 = mm_strdup("-1");
|
$$.index2 = "-1";
|
||||||
$$.str = EMPTY;
|
$$.str = "";
|
||||||
}
|
|
||||||
ECPG: IconstICONST block
|
|
||||||
{
|
|
||||||
@$ = make_name();
|
|
||||||
}
|
}
|
||||||
ECPG: AexprConstNULL_P rule
|
ECPG: AexprConstNULL_P rule
|
||||||
| civar
|
| civar
|
||||||
@ -494,83 +480,83 @@ ECPG: FetchStmtMOVEfetch_args rule
|
|||||||
| FETCH fetch_args ecpg_fetch_into
|
| FETCH fetch_args ecpg_fetch_into
|
||||||
| FETCH FORWARD cursor_name opt_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);
|
struct cursor *ptr = add_additional_variables(@3, false);
|
||||||
|
|
||||||
if (ptr->connection)
|
if (ptr->connection)
|
||||||
connection = mm_strdup(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
|
| 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);
|
struct cursor *ptr = add_additional_variables(@4, false);
|
||||||
|
|
||||||
if (ptr->connection)
|
if (ptr->connection)
|
||||||
connection = mm_strdup(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
|
| 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);
|
struct cursor *ptr = add_additional_variables(@3, false);
|
||||||
|
|
||||||
if (ptr->connection)
|
if (ptr->connection)
|
||||||
connection = mm_strdup(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
|
| 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);
|
struct cursor *ptr = add_additional_variables(@4, false);
|
||||||
|
|
||||||
if (ptr->connection)
|
if (ptr->connection)
|
||||||
connection = mm_strdup(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
|
| 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);
|
struct cursor *ptr = add_additional_variables(@3, false);
|
||||||
|
|
||||||
if (ptr->connection)
|
if (ptr->connection)
|
||||||
connection = mm_strdup(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
|
| 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);
|
struct cursor *ptr = add_additional_variables(@4, false);
|
||||||
|
|
||||||
if (ptr->connection)
|
if (ptr->connection)
|
||||||
connection = mm_strdup(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
|
| 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);
|
struct cursor *ptr = add_additional_variables(@3, false);
|
||||||
|
|
||||||
if (ptr->connection)
|
if (ptr->connection)
|
||||||
connection = mm_strdup(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
|
| 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);
|
struct cursor *ptr = add_additional_variables(@4, false);
|
||||||
|
|
||||||
if (ptr->connection)
|
if (ptr->connection)
|
||||||
connection = mm_strdup(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
|
ECPG: limit_clauseLIMITselect_limit_value','select_offset_value block
|
||||||
{
|
{
|
||||||
|
@ -39,8 +39,6 @@ char *input_filename = NULL;
|
|||||||
static int FoundInto = 0;
|
static int FoundInto = 0;
|
||||||
static int initializer = 0;
|
static int initializer = 0;
|
||||||
static int pacounter = 1;
|
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 struct this_type actual_type[STRUCT_DEPTH];
|
||||||
static char *actual_startline[STRUCT_DEPTH];
|
static char *actual_startline[STRUCT_DEPTH];
|
||||||
static int varchar_counter = 1;
|
static int varchar_counter = 1;
|
||||||
@ -95,7 +93,7 @@ yylloc_default(YYLTYPE *target, YYLTYPE *rhs, int N)
|
|||||||
needed++;
|
needed++;
|
||||||
needed += thislen;
|
needed += thislen;
|
||||||
}
|
}
|
||||||
result = (char *) mm_alloc(needed + 1);
|
result = (char *) loc_alloc(needed + 1);
|
||||||
ptr = result;
|
ptr = result;
|
||||||
for (int i = 1; i <= N; i++)
|
for (int i = 1; i <= N; i++)
|
||||||
{
|
{
|
||||||
@ -115,22 +113,19 @@ yylloc_default(YYLTYPE *target, YYLTYPE *rhs, int N)
|
|||||||
*target = rhs[1];
|
*target = rhs[1];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
*target = EMPTY;
|
{
|
||||||
|
/* No need to allocate any space */
|
||||||
|
*target = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* and the rest */
|
/* and the rest */
|
||||||
static char *
|
static char *
|
||||||
make_name(void)
|
create_questionmarks(const char *name, bool array)
|
||||||
{
|
|
||||||
return mm_strdup(base_yytext);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
create_questionmarks(char *name, bool array)
|
|
||||||
{
|
{
|
||||||
struct variable *p = find_variable(name);
|
struct variable *p = find_variable(name);
|
||||||
int count;
|
int count;
|
||||||
char *result = EMPTY;
|
char *result = "";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In case we have a struct, we have to print as many "?" as there are
|
* 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--)
|
for (; count > 0; count--)
|
||||||
{
|
{
|
||||||
sprintf(pacounter_buffer, "$%d", pacounter++);
|
char buf[32];
|
||||||
result = cat_str(3, result, mm_strdup(pacounter_buffer), mm_strdup(" , "));
|
|
||||||
|
snprintf(buf, sizeof(buf), "$%d", pacounter++);
|
||||||
|
result = cat_str(3, result, buf, " , ");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* removed the trailing " ," */
|
/* remove the trailing " ," */
|
||||||
|
|
||||||
result[strlen(result) - 3] = '\0';
|
result[strlen(result) - 3] = '\0';
|
||||||
return result;
|
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
|
* pointer instead of the variable. Do it only for local variables, not
|
||||||
* for globals.
|
* for globals.
|
||||||
*/
|
*/
|
||||||
|
char *result = "";
|
||||||
char *result = EMPTY;
|
|
||||||
int insert;
|
int insert;
|
||||||
|
|
||||||
for (insert = 1; insert >= 0; 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>)" */
|
/* change variable name to "ECPGget_var(<counter>)" */
|
||||||
original_var = ptr->variable->name;
|
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 */
|
/* Don't emit ECPGset_var() calls for global variables */
|
||||||
if (ptr->variable->brace_level == 0)
|
if (ptr->variable->brace_level == 0)
|
||||||
@ -227,12 +222,12 @@ adjust_outofscope_cursor_vars(struct cursor *cur)
|
|||||||
&& ptr->variable->type->type != ECPGt_bytea)
|
&& ptr->variable->type->type != ECPGt_bytea)
|
||||||
&& atoi(ptr->variable->type->size) > 1)
|
&& atoi(ptr->variable->type->size) > 1)
|
||||||
{
|
{
|
||||||
newvar = new_variable(cat_str(4, mm_strdup("("),
|
newvar = new_variable(cat_str(4, "(",
|
||||||
mm_strdup(ecpg_type_name(ptr->variable->type->u.element->type)),
|
ecpg_type_name(ptr->variable->type->u.element->type),
|
||||||
mm_strdup(" *)(ECPGget_var("),
|
" *)(ECPGget_var(",
|
||||||
mm_strdup(var_text)),
|
var_text),
|
||||||
ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type,
|
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->u.element->counter),
|
||||||
ptr->variable->type->size),
|
ptr->variable->type->size),
|
||||||
0);
|
0);
|
||||||
@ -244,10 +239,10 @@ adjust_outofscope_cursor_vars(struct cursor *cur)
|
|||||||
|| ptr->variable->type->type == ECPGt_bytea)
|
|| ptr->variable->type->type == ECPGt_bytea)
|
||||||
&& atoi(ptr->variable->type->size) > 1)
|
&& atoi(ptr->variable->type->size) > 1)
|
||||||
{
|
{
|
||||||
newvar = new_variable(cat_str(4, mm_strdup("("),
|
newvar = new_variable(cat_str(4, "(",
|
||||||
mm_strdup(ecpg_type_name(ptr->variable->type->type)),
|
ecpg_type_name(ptr->variable->type->type),
|
||||||
mm_strdup(" *)(ECPGget_var("),
|
" *)(ECPGget_var(",
|
||||||
mm_strdup(var_text)),
|
var_text),
|
||||||
ECPGmake_simple_type(ptr->variable->type->type,
|
ECPGmake_simple_type(ptr->variable->type->type,
|
||||||
ptr->variable->type->size,
|
ptr->variable->type->size,
|
||||||
ptr->variable->type->counter),
|
ptr->variable->type->counter),
|
||||||
@ -259,11 +254,11 @@ adjust_outofscope_cursor_vars(struct cursor *cur)
|
|||||||
else if (ptr->variable->type->type == ECPGt_struct
|
else if (ptr->variable->type->type == ECPGt_struct
|
||||||
|| ptr->variable->type->type == ECPGt_union)
|
|| ptr->variable->type->type == ECPGt_union)
|
||||||
{
|
{
|
||||||
newvar = new_variable(cat_str(5, mm_strdup("(*("),
|
newvar = new_variable(cat_str(5, "(*(",
|
||||||
mm_strdup(ptr->variable->type->type_name),
|
ptr->variable->type->type_name,
|
||||||
mm_strdup(" *)(ECPGget_var("),
|
" *)(ECPGget_var(",
|
||||||
mm_strdup(var_text),
|
var_text,
|
||||||
mm_strdup(")")),
|
")"),
|
||||||
ECPGmake_struct_type(ptr->variable->type->u.members,
|
ECPGmake_struct_type(ptr->variable->type->u.members,
|
||||||
ptr->variable->type->type,
|
ptr->variable->type->type,
|
||||||
ptr->variable->type->type_name,
|
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
|
if (ptr->variable->type->u.element->type == ECPGt_struct
|
||||||
|| ptr->variable->type->u.element->type == ECPGt_union)
|
|| ptr->variable->type->u.element->type == ECPGt_union)
|
||||||
{
|
{
|
||||||
newvar = new_variable(cat_str(5, mm_strdup("(*("),
|
newvar = new_variable(cat_str(5, "(*(",
|
||||||
mm_strdup(ptr->variable->type->u.element->type_name),
|
ptr->variable->type->u.element->type_name,
|
||||||
mm_strdup(" *)(ECPGget_var("),
|
" *)(ECPGget_var(",
|
||||||
mm_strdup(var_text),
|
var_text,
|
||||||
mm_strdup(")")),
|
")"),
|
||||||
ECPGmake_struct_type(ptr->variable->type->u.element->u.members,
|
ECPGmake_struct_type(ptr->variable->type->u.element->u.members,
|
||||||
ptr->variable->type->u.element->type,
|
ptr->variable->type->u.element->type,
|
||||||
ptr->variable->type->u.element->type_name,
|
ptr->variable->type->u.element->type_name,
|
||||||
@ -289,10 +284,10 @@ adjust_outofscope_cursor_vars(struct cursor *cur)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
newvar = new_variable(cat_str(4, mm_strdup("("),
|
newvar = new_variable(cat_str(4, "(",
|
||||||
mm_strdup(ecpg_type_name(ptr->variable->type->u.element->type)),
|
ecpg_type_name(ptr->variable->type->u.element->type),
|
||||||
mm_strdup(" *)(ECPGget_var("),
|
" *)(ECPGget_var(",
|
||||||
mm_strdup(var_text)),
|
var_text),
|
||||||
ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type,
|
ECPGmake_array_type(ECPGmake_simple_type(ptr->variable->type->u.element->type,
|
||||||
ptr->variable->type->u.element->size,
|
ptr->variable->type->u.element->size,
|
||||||
ptr->variable->type->u.element->counter),
|
ptr->variable->type->u.element->counter),
|
||||||
@ -303,10 +298,10 @@ adjust_outofscope_cursor_vars(struct cursor *cur)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
newvar = new_variable(cat_str(4, mm_strdup("*("),
|
newvar = new_variable(cat_str(4, "*(",
|
||||||
mm_strdup(ecpg_type_name(ptr->variable->type->type)),
|
ecpg_type_name(ptr->variable->type->type),
|
||||||
mm_strdup(" *)(ECPGget_var("),
|
" *)(ECPGget_var(",
|
||||||
mm_strdup(var_text)),
|
var_text),
|
||||||
ECPGmake_simple_type(ptr->variable->type->type,
|
ECPGmake_simple_type(ptr->variable->type->type,
|
||||||
ptr->variable->type->size,
|
ptr->variable->type->size,
|
||||||
ptr->variable->type->counter),
|
ptr->variable->type->counter),
|
||||||
@ -320,10 +315,11 @@ adjust_outofscope_cursor_vars(struct cursor *cur)
|
|||||||
*/
|
*/
|
||||||
if (!skip_set_var)
|
if (!skip_set_var)
|
||||||
{
|
{
|
||||||
sprintf(var_text, "%d, %s", ecpg_internal_var++, var_ptr ? "&(" : "(");
|
snprintf(var_text, sizeof(var_text), "%d, %s",
|
||||||
result = cat_str(5, result, mm_strdup("ECPGset_var("),
|
ecpg_internal_var++, var_ptr ? "&(" : "(");
|
||||||
mm_strdup(var_text), mm_strdup(original_var),
|
result = cat_str(5, result, "ECPGset_var(",
|
||||||
mm_strdup("), __LINE__);\n"));
|
var_text, original_var,
|
||||||
|
"), __LINE__);\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -338,17 +334,17 @@ adjust_outofscope_cursor_vars(struct cursor *cur)
|
|||||||
{
|
{
|
||||||
/* change variable name to "ECPGget_var(<counter>)" */
|
/* change variable name to "ECPGget_var(<counter>)" */
|
||||||
original_var = ptr->indicator->name;
|
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;
|
var_ptr = false;
|
||||||
|
|
||||||
if (ptr->indicator->type->type == ECPGt_struct
|
if (ptr->indicator->type->type == ECPGt_struct
|
||||||
|| ptr->indicator->type->type == ECPGt_union)
|
|| ptr->indicator->type->type == ECPGt_union)
|
||||||
{
|
{
|
||||||
newind = new_variable(cat_str(5, mm_strdup("(*("),
|
newind = new_variable(cat_str(5, "(*(",
|
||||||
mm_strdup(ptr->indicator->type->type_name),
|
ptr->indicator->type->type_name,
|
||||||
mm_strdup(" *)(ECPGget_var("),
|
" *)(ECPGget_var(",
|
||||||
mm_strdup(var_text),
|
var_text,
|
||||||
mm_strdup(")")),
|
")"),
|
||||||
ECPGmake_struct_type(ptr->indicator->type->u.members,
|
ECPGmake_struct_type(ptr->indicator->type->u.members,
|
||||||
ptr->indicator->type->type,
|
ptr->indicator->type->type,
|
||||||
ptr->indicator->type->type_name,
|
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
|
if (ptr->indicator->type->u.element->type == ECPGt_struct
|
||||||
|| ptr->indicator->type->u.element->type == ECPGt_union)
|
|| ptr->indicator->type->u.element->type == ECPGt_union)
|
||||||
{
|
{
|
||||||
newind = new_variable(cat_str(5, mm_strdup("(*("),
|
newind = new_variable(cat_str(5, "(*(",
|
||||||
mm_strdup(ptr->indicator->type->u.element->type_name),
|
ptr->indicator->type->u.element->type_name,
|
||||||
mm_strdup(" *)(ECPGget_var("),
|
" *)(ECPGget_var(",
|
||||||
mm_strdup(var_text),
|
var_text,
|
||||||
mm_strdup(")")),
|
")"),
|
||||||
ECPGmake_struct_type(ptr->indicator->type->u.element->u.members,
|
ECPGmake_struct_type(ptr->indicator->type->u.element->u.members,
|
||||||
ptr->indicator->type->u.element->type,
|
ptr->indicator->type->u.element->type,
|
||||||
ptr->indicator->type->u.element->type_name,
|
ptr->indicator->type->u.element->type_name,
|
||||||
@ -374,9 +370,10 @@ adjust_outofscope_cursor_vars(struct cursor *cur)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
newind = new_variable(cat_str(4, mm_strdup("("),
|
newind = new_variable(cat_str(4, "(",
|
||||||
mm_strdup(ecpg_type_name(ptr->indicator->type->u.element->type)),
|
ecpg_type_name(ptr->indicator->type->u.element->type),
|
||||||
mm_strdup(" *)(ECPGget_var("), mm_strdup(var_text)),
|
" *)(ECPGget_var(",
|
||||||
|
var_text),
|
||||||
ECPGmake_array_type(ECPGmake_simple_type(ptr->indicator->type->u.element->type,
|
ECPGmake_array_type(ECPGmake_simple_type(ptr->indicator->type->u.element->type,
|
||||||
ptr->indicator->type->u.element->size,
|
ptr->indicator->type->u.element->size,
|
||||||
ptr->indicator->type->u.element->counter),
|
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)
|
else if (atoi(ptr->indicator->type->size) > 1)
|
||||||
{
|
{
|
||||||
newind = new_variable(cat_str(4, mm_strdup("("),
|
newind = new_variable(cat_str(4, "(",
|
||||||
mm_strdup(ecpg_type_name(ptr->indicator->type->type)),
|
ecpg_type_name(ptr->indicator->type->type),
|
||||||
mm_strdup(" *)(ECPGget_var("),
|
" *)(ECPGget_var(",
|
||||||
mm_strdup(var_text)),
|
var_text),
|
||||||
ECPGmake_simple_type(ptr->indicator->type->type,
|
ECPGmake_simple_type(ptr->indicator->type->type,
|
||||||
ptr->indicator->type->size,
|
ptr->indicator->type->size,
|
||||||
ptr->variable->type->counter),
|
ptr->variable->type->counter),
|
||||||
@ -398,10 +395,10 @@ adjust_outofscope_cursor_vars(struct cursor *cur)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
newind = new_variable(cat_str(4, mm_strdup("*("),
|
newind = new_variable(cat_str(4, "*(",
|
||||||
mm_strdup(ecpg_type_name(ptr->indicator->type->type)),
|
ecpg_type_name(ptr->indicator->type->type),
|
||||||
mm_strdup(" *)(ECPGget_var("),
|
" *)(ECPGget_var(",
|
||||||
mm_strdup(var_text)),
|
var_text),
|
||||||
ECPGmake_simple_type(ptr->indicator->type->type,
|
ECPGmake_simple_type(ptr->indicator->type->type,
|
||||||
ptr->indicator->type->size,
|
ptr->indicator->type->size,
|
||||||
ptr->variable->type->counter),
|
ptr->variable->type->counter),
|
||||||
@ -413,10 +410,11 @@ adjust_outofscope_cursor_vars(struct cursor *cur)
|
|||||||
* create call to "ECPGset_var(<counter>, <pointer>. <line
|
* create call to "ECPGset_var(<counter>, <pointer>. <line
|
||||||
* number>)"
|
* number>)"
|
||||||
*/
|
*/
|
||||||
sprintf(var_text, "%d, %s", ecpg_internal_var++, var_ptr ? "&(" : "(");
|
snprintf(var_text, sizeof(var_text), "%d, %s",
|
||||||
result = cat_str(5, result, mm_strdup("ECPGset_var("),
|
ecpg_internal_var++, var_ptr ? "&(" : "(");
|
||||||
mm_strdup(var_text), mm_strdup(original_var),
|
result = cat_str(5, result, "ECPGset_var(",
|
||||||
mm_strdup("), __LINE__);\n"));
|
var_text, original_var,
|
||||||
|
"), __LINE__);\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
add_variable_to_tail(&newlist, newvar, newind);
|
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))
|
(cur->function != NULL && strcmp(cur->function, current_function) == 0))
|
||||||
|
|
||||||
static struct cursor *
|
static struct cursor *
|
||||||
add_additional_variables(char *name, bool insert)
|
add_additional_variables(const char *name, bool insert)
|
||||||
{
|
{
|
||||||
struct cursor *ptr;
|
struct cursor *ptr;
|
||||||
struct arguments *p;
|
struct arguments *p;
|
||||||
@ -475,8 +473,10 @@ add_additional_variables(char *name, bool insert)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_typedef(char *name, char *dimension, char *length, enum ECPGttype type_enum,
|
add_typedef(const char *name, const char *dimension, const char *length,
|
||||||
char *type_dimension, char *type_index, int initializer, int array)
|
enum ECPGttype type_enum,
|
||||||
|
const char *type_dimension, const char *type_index,
|
||||||
|
int initializer, int array)
|
||||||
{
|
{
|
||||||
/* add entry to list */
|
/* add entry to list */
|
||||||
struct typedefs *ptr,
|
struct typedefs *ptr,
|
||||||
@ -496,19 +496,20 @@ add_typedef(char *name, char *dimension, char *length, enum ECPGttype type_enum,
|
|||||||
/* re-definition is a bug */
|
/* re-definition is a bug */
|
||||||
mmerror(PARSE_ERROR, ET_ERROR, "type \"%s\" is already defined", name);
|
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));
|
this = (struct typedefs *) mm_alloc(sizeof(struct typedefs));
|
||||||
|
|
||||||
/* initial definition */
|
/* initial definition */
|
||||||
this->next = types;
|
this->next = types;
|
||||||
this->name = name;
|
this->name = mm_strdup(name);
|
||||||
this->brace_level = braces_open;
|
this->brace_level = braces_open;
|
||||||
this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
|
this->type = (struct this_type *) mm_alloc(sizeof(struct this_type));
|
||||||
this->type->type_enum = type_enum;
|
this->type->type_enum = type_enum;
|
||||||
this->type->type_str = mm_strdup(name);
|
this->type->type_str = mm_strdup(name);
|
||||||
this->type->type_dimension = dimension; /* dimension of array */
|
this->type->type_dimension = mm_strdup(dimension); /* dimension of array */
|
||||||
this->type->type_index = length; /* length of string */
|
this->type->type_index = mm_strdup(length); /* length of string */
|
||||||
this->type->type_sizeof = ECPGstruct_sizeof;
|
this->type->type_sizeof = ECPGstruct_sizeof;
|
||||||
this->struct_member_list = (type_enum == ECPGt_struct || type_enum == ECPGt_union) ?
|
this->struct_member_list = (type_enum == ECPGt_struct || type_enum == ECPGt_union) ?
|
||||||
ECPGstruct_member_dup(struct_member_list[struct_level]) : NULL;
|
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();
|
char *line = hashline_number();
|
||||||
|
|
||||||
fprintf(base_yyout, "%s", line);
|
fprintf(base_yyout, "%s", line);
|
||||||
free(line);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -100,7 +99,7 @@ hashline_number(void)
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
/* "* 2" here is for escaping '\' and '"' below */
|
/* "* 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,
|
char *src,
|
||||||
*dest;
|
*dest;
|
||||||
|
|
||||||
@ -119,7 +118,7 @@ hashline_number(void)
|
|||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
return EMPTY;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *ecpg_statement_type_name[] = {
|
static char *ecpg_statement_type_name[] = {
|
||||||
|
@ -204,7 +204,7 @@ filtered_base_yylex(void)
|
|||||||
|
|
||||||
/* Combine 3 tokens into 1 */
|
/* Combine 3 tokens into 1 */
|
||||||
base_yylval.str = psprintf("%s UESCAPE %s", base_yylval.str, escstr);
|
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 */
|
/* Clear have_lookahead, thereby consuming all three tokens */
|
||||||
have_lookahead = false;
|
have_lookahead = false;
|
||||||
@ -254,11 +254,11 @@ base_yylex_location(void)
|
|||||||
case UIDENT:
|
case UIDENT:
|
||||||
case IP:
|
case IP:
|
||||||
/* Duplicate the <str> value */
|
/* Duplicate the <str> value */
|
||||||
base_yylloc = mm_strdup(base_yylval.str);
|
base_yylloc = loc_strdup(base_yylval.str);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Else just use the input, i.e., yytext */
|
/* 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 */
|
/* Apply an ASCII-only downcasing */
|
||||||
for (unsigned char *ptr = (unsigned char *) base_yylloc; *ptr; ptr++)
|
for (unsigned char *ptr = (unsigned char *) base_yylloc; *ptr; ptr++)
|
||||||
{
|
{
|
||||||
|
@ -13,12 +13,11 @@
|
|||||||
/* defines */
|
/* defines */
|
||||||
|
|
||||||
#define STRUCT_DEPTH 128
|
#define STRUCT_DEPTH 128
|
||||||
#define EMPTY mm_strdup("")
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "Location tracking" support --- see ecpg.header for more comments.
|
* "Location tracking" support --- see ecpg.header for more comments.
|
||||||
*/
|
*/
|
||||||
typedef char *YYLTYPE;
|
typedef const char *YYLTYPE;
|
||||||
|
|
||||||
#define YYLTYPE_IS_DECLARED 1
|
#define YYLTYPE_IS_DECLARED 1
|
||||||
|
|
||||||
@ -82,22 +81,25 @@ extern int base_yylex(void);
|
|||||||
extern void base_yyerror(const char *error);
|
extern void base_yyerror(const char *error);
|
||||||
extern void *mm_alloc(size_t size);
|
extern void *mm_alloc(size_t size);
|
||||||
extern char *mm_strdup(const char *string);
|
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 *cat_str(int count,...);
|
||||||
extern char *make2_str(char *str1, char *str2);
|
extern char *make2_str(const char *str1, const char *str2);
|
||||||
extern char *make3_str(char *str1, char *str2, char *str3);
|
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 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 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_header(const char *desc_name);
|
||||||
extern void output_get_descr(char *desc_name, char *index);
|
extern void output_get_descr(const char *desc_name, const char *index);
|
||||||
extern void output_set_descr_header(char *desc_name);
|
extern void output_set_descr_header(const char *desc_name);
|
||||||
extern void output_set_descr(char *desc_name, char *index);
|
extern void output_set_descr(const char *desc_name, const char *index);
|
||||||
extern void push_assignment(char *var, enum ECPGdtype value);
|
extern void push_assignment(const char *var, enum ECPGdtype value);
|
||||||
extern struct variable *find_variable(char *name);
|
extern struct variable *find_variable(const char *name);
|
||||||
extern void whenever_action(int mode);
|
extern void whenever_action(int mode);
|
||||||
extern void add_descriptor(char *name, char *connection);
|
extern void add_descriptor(const char *name, const char *connection);
|
||||||
extern void drop_descriptor(char *name, char *connection);
|
extern void drop_descriptor(const char *name, const char *connection);
|
||||||
extern struct descriptor *lookup_descriptor(char *name, 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 *descriptor_variable(const char *name, int input);
|
||||||
extern struct variable *sqlda_variable(const char *name);
|
extern struct variable *sqlda_variable(const char *name);
|
||||||
extern void add_variable_to_head(struct arguments **list,
|
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 remove_variable_from_list(struct arguments **list, struct variable *var);
|
||||||
extern void dump_variables(struct arguments *list, int mode);
|
extern void dump_variables(struct arguments *list, int mode);
|
||||||
extern struct typedefs *get_typedef(const char *name, bool noerror);
|
extern struct typedefs *get_typedef(const char *name, bool noerror);
|
||||||
extern void adjust_array(enum ECPGttype type_enum, char **dimension,
|
extern void adjust_array(enum ECPGttype type_enum, const char **dimension,
|
||||||
char **length, char *type_dimension,
|
const char **length, const char *type_dimension,
|
||||||
char *type_index, int pointer_len,
|
const char *type_index, int pointer_len,
|
||||||
bool type_definition);
|
bool type_definition);
|
||||||
extern void reset_variables(void);
|
extern void reset_variables(void);
|
||||||
extern void check_indicator(struct ECPGtype *var);
|
extern void check_indicator(struct ECPGtype *var);
|
||||||
|
@ -69,13 +69,13 @@ ECPGmake_struct_member(const char *name, struct ECPGtype *type, struct ECPGstruc
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct ECPGtype *
|
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));
|
struct ECPGtype *ne = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype));
|
||||||
|
|
||||||
ne->type = type;
|
ne->type = type;
|
||||||
ne->type_name = NULL;
|
ne->type_name = NULL;
|
||||||
ne->size = size;
|
ne->size = mm_strdup(size);
|
||||||
ne->u.element = NULL;
|
ne->u.element = NULL;
|
||||||
ne->struct_sizeof = NULL;
|
ne->struct_sizeof = NULL;
|
||||||
ne->counter = counter; /* only needed for varchar and bytea */
|
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 *
|
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);
|
struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_array, size, 0);
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ ECPGmake_array_type(struct ECPGtype *type, char *size)
|
|||||||
struct ECPGtype *
|
struct ECPGtype *
|
||||||
ECPGmake_struct_type(struct ECPGstruct_member *rm, enum ECPGttype type, char *type_name, char *struct_sizeof)
|
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->type_name = mm_strdup(type_name);
|
||||||
ne->u.members = ECPGstruct_member_dup(rm);
|
ne->u.members = ECPGstruct_member_dup(rm);
|
||||||
|
@ -35,8 +35,8 @@ struct ECPGtype
|
|||||||
/* Everything is malloced. */
|
/* Everything is malloced. */
|
||||||
void ECPGmake_struct_member(const char *name, struct ECPGtype *type,
|
void ECPGmake_struct_member(const char *name, struct ECPGtype *type,
|
||||||
struct ECPGstruct_member **start);
|
struct ECPGstruct_member **start);
|
||||||
struct ECPGtype *ECPGmake_simple_type(enum ECPGttype type, char *size, int counter);
|
struct ECPGtype *ECPGmake_simple_type(enum ECPGttype type, const char *size, int counter);
|
||||||
struct ECPGtype *ECPGmake_array_type(struct ECPGtype *type, char *size);
|
struct ECPGtype *ECPGmake_array_type(struct ECPGtype *type, const char *size);
|
||||||
struct ECPGtype *ECPGmake_struct_type(struct ECPGstruct_member *rm,
|
struct ECPGtype *ECPGmake_struct_type(struct ECPGstruct_member *rm,
|
||||||
enum ECPGttype type, char *type_name,
|
enum ECPGttype type, char *type_name,
|
||||||
char *struct_sizeof);
|
char *struct_sizeof);
|
||||||
@ -93,28 +93,28 @@ struct when
|
|||||||
|
|
||||||
struct index
|
struct index
|
||||||
{
|
{
|
||||||
char *index1;
|
const char *index1;
|
||||||
char *index2;
|
const char *index2;
|
||||||
char *str;
|
const char *str;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct su_symbol
|
struct su_symbol
|
||||||
{
|
{
|
||||||
char *su;
|
const char *su;
|
||||||
char *symbol;
|
const char *symbol;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct prep
|
struct prep
|
||||||
{
|
{
|
||||||
char *name;
|
const char *name;
|
||||||
char *stmt;
|
const char *stmt;
|
||||||
char *type;
|
const char *type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct exec
|
struct exec
|
||||||
{
|
{
|
||||||
char *name;
|
const char *name;
|
||||||
char *type;
|
const char *type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct this_type
|
struct this_type
|
||||||
@ -221,14 +221,14 @@ enum errortype
|
|||||||
|
|
||||||
struct fetch_desc
|
struct fetch_desc
|
||||||
{
|
{
|
||||||
char *str;
|
const char *str;
|
||||||
char *name;
|
const char *name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct describe
|
struct describe
|
||||||
{
|
{
|
||||||
int input;
|
int input;
|
||||||
char *stmt_name;
|
const char *stmt_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _ECPG_PREPROC_TYPE_H */
|
#endif /* _ECPG_PREPROC_TYPE_H */
|
||||||
|
@ -104,33 +104,117 @@ mm_strdup(const char *string)
|
|||||||
return new;
|
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
|
* Concatenate 2 strings, inserting a space between them unless either is empty
|
||||||
*
|
|
||||||
* The input strings are freed.
|
|
||||||
*/
|
*/
|
||||||
char *
|
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);
|
strcpy(res_str, str1);
|
||||||
if (strlen(str1) != 0 && strlen(str2) != 0)
|
if (strlen(str1) != 0 && strlen(str2) != 0)
|
||||||
strcat(res_str, " ");
|
strcat(res_str, " ");
|
||||||
strcat(res_str, str2);
|
strcat(res_str, str2);
|
||||||
free(str1);
|
|
||||||
free(str2);
|
|
||||||
return res_str;
|
return res_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Concatenate N strings, inserting spaces between them unless they are empty
|
* Concatenate N strings, inserting spaces between them unless they are empty
|
||||||
*
|
|
||||||
* The input strings are freed.
|
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
cat_str(int count,...)
|
cat_str(int count,...)
|
||||||
@ -154,36 +238,27 @@ cat_str(int count,...)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Concatenate 2 strings, with no space between
|
* Concatenate 2 strings, with no space between
|
||||||
*
|
|
||||||
* The input strings are freed.
|
|
||||||
*/
|
*/
|
||||||
char *
|
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);
|
strcpy(res_str, str1);
|
||||||
strcat(res_str, str2);
|
strcat(res_str, str2);
|
||||||
free(str1);
|
|
||||||
free(str2);
|
|
||||||
return res_str;
|
return res_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Concatenate 3 strings, with no space between
|
* Concatenate 3 strings, with no space between
|
||||||
*
|
|
||||||
* The input strings are freed.
|
|
||||||
*/
|
*/
|
||||||
char *
|
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);
|
strcpy(res_str, str1);
|
||||||
strcat(res_str, str2);
|
strcat(res_str, str2);
|
||||||
strcat(res_str, str3);
|
strcat(res_str, str3);
|
||||||
free(str1);
|
|
||||||
free(str2);
|
|
||||||
free(str3);
|
|
||||||
return res_str;
|
return res_str;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ new_variable(const char *name, struct ECPGtype *type, int brace_level)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct variable *
|
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, ".-["),
|
char *next = strpbrk(++str, ".-["),
|
||||||
*end,
|
*end,
|
||||||
@ -123,7 +123,7 @@ find_struct_member(char *name, char *str, struct ECPGstruct_member *members, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct variable *
|
static struct variable *
|
||||||
find_struct(char *name, char *next, char *end)
|
find_struct(const char *name, char *next, char *end)
|
||||||
{
|
{
|
||||||
struct variable *p;
|
struct variable *p;
|
||||||
char c = *next;
|
char c = *next;
|
||||||
@ -174,7 +174,7 @@ find_struct(char *name, char *next, char *end)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct variable *
|
static struct variable *
|
||||||
find_simple(char *name)
|
find_simple(const char *name)
|
||||||
{
|
{
|
||||||
struct variable *p;
|
struct variable *p;
|
||||||
|
|
||||||
@ -190,7 +190,7 @@ find_simple(char *name)
|
|||||||
/* Note that this function will end the program in case of an unknown */
|
/* Note that this function will end the program in case of an unknown */
|
||||||
/* variable */
|
/* variable */
|
||||||
struct variable *
|
struct variable *
|
||||||
find_variable(char *name)
|
find_variable(const char *name)
|
||||||
{
|
{
|
||||||
char *next,
|
char *next,
|
||||||
*end;
|
*end;
|
||||||
@ -513,7 +513,10 @@ get_typedef(const char *name, bool noerror)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
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)
|
if (atoi(type_index) >= 0)
|
||||||
{
|
{
|
||||||
@ -556,7 +559,7 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty
|
|||||||
if (pointer_len)
|
if (pointer_len)
|
||||||
{
|
{
|
||||||
*length = *dimension;
|
*length = *dimension;
|
||||||
*dimension = mm_strdup("0");
|
*dimension = "0";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atoi(*length) >= 0)
|
if (atoi(*length) >= 0)
|
||||||
@ -567,13 +570,13 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty
|
|||||||
case ECPGt_bytea:
|
case ECPGt_bytea:
|
||||||
/* pointer has to get dimension 0 */
|
/* pointer has to get dimension 0 */
|
||||||
if (pointer_len)
|
if (pointer_len)
|
||||||
*dimension = mm_strdup("0");
|
*dimension = "0";
|
||||||
|
|
||||||
/* one index is the string length */
|
/* one index is the string length */
|
||||||
if (atoi(*length) < 0)
|
if (atoi(*length) < 0)
|
||||||
{
|
{
|
||||||
*length = *dimension;
|
*length = *dimension;
|
||||||
*dimension = mm_strdup("-1");
|
*dimension = "-1";
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -583,13 +586,13 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty
|
|||||||
/* char ** */
|
/* char ** */
|
||||||
if (pointer_len == 2)
|
if (pointer_len == 2)
|
||||||
{
|
{
|
||||||
*length = *dimension = mm_strdup("0");
|
*length = *dimension = "0";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pointer has to get length 0 */
|
/* pointer has to get length 0 */
|
||||||
if (pointer_len == 1)
|
if (pointer_len == 1)
|
||||||
*length = mm_strdup("0");
|
*length = "0";
|
||||||
|
|
||||||
/* one index is the string length */
|
/* one index is the string length */
|
||||||
if (atoi(*length) < 0)
|
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
|
* do not change this for typedefs since it will be
|
||||||
* changed later on when the variable is defined
|
* changed later on when the variable is defined
|
||||||
*/
|
*/
|
||||||
*length = mm_strdup("1");
|
*length = "1";
|
||||||
else if (strcmp(*dimension, "0") == 0)
|
else if (strcmp(*dimension, "0") == 0)
|
||||||
*length = mm_strdup("-1");
|
*length = "-1";
|
||||||
else
|
else
|
||||||
*length = *dimension;
|
*length = *dimension;
|
||||||
|
|
||||||
*dimension = mm_strdup("-1");
|
*dimension = "-1";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -618,7 +621,7 @@ adjust_array(enum ECPGttype type_enum, char **dimension, char **length, char *ty
|
|||||||
if (pointer_len)
|
if (pointer_len)
|
||||||
{
|
{
|
||||||
*length = *dimension;
|
*length = *dimension;
|
||||||
*dimension = mm_strdup("0");
|
*dimension = "0";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atoi(*length) >= 0)
|
if (atoi(*length) >= 0)
|
||||||
|
@ -3602,6 +3602,7 @@ libpq_source
|
|||||||
line_t
|
line_t
|
||||||
lineno_t
|
lineno_t
|
||||||
list_sort_comparator
|
list_sort_comparator
|
||||||
|
loc_chunk
|
||||||
local_relopt
|
local_relopt
|
||||||
local_relopts
|
local_relopts
|
||||||
local_source
|
local_source
|
||||||
|
Reference in New Issue
Block a user