summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2024-10-14 17:44:42 +0000
committerTom Lane2024-10-14 17:44:42 +0000
commita542d5614bdb6430094556162b9ca2f01d35f9dc (patch)
treea3171cd3c51af3c76b49c23876636dc601197bb0
parent6b005499447512abfa1e4add87dcf3e2859c4f9e (diff)
ecpg: re-implement preprocessor's string management.
Most productions in the preprocessor grammar construct strings representing SQL or C statements or fragments thereof. Instead of returning these as <str> results of the productions, return them as "location" values, taking advantage of Bison's flexibility about what a location is. We aren't really giving up anything thereby, since ecpg's error reports have always just given line numbers, and that's tracked separately. The advantage of this is that a single instance of the YYLLOC_DEFAULT macro can perform all the work needed by the vast majority of productions, including all the ones made automatically by parse.pl. This avoids having large numbers of effectively-identical productions, which tickles an optimization inefficiency in recent versions of clang. (This patch reduces the compilation time for preproc.o by more than 100-fold with clang 16, and is visibly helpful with gcc too.) The compiled parser is noticeably smaller as well. A disadvantage of this approach is that YYLLOC_DEFAULT is applied before running the production's semantic action (if any). This means it cannot use the method favored by cat_str() of free'ing all the input strings; if the action needs to look at the input strings, it'd be looking at dangling storage. As this stands, therefore, it leaks memory like a sieve. This is already a big patch though, and fixing the memory management seems like a separable problem, so let's leave that for the next step. (This does remove some free() calls that I'd have had to touch anyway, in the expectation that the next step will manage memory reclamation quite differently.) Most of the changes here are mindless substitution of "@N" for "$N" in grammar rules; see the changes to README.parser for an explanation. Discussion: https://postgr.es/m/[email protected]
-rw-r--r--src/interfaces/ecpg/preproc/README.parser32
-rw-r--r--src/interfaces/ecpg/preproc/ecpg.addons294
-rw-r--r--src/interfaces/ecpg/preproc/ecpg.header63
-rw-r--r--src/interfaces/ecpg/preproc/ecpg.trailer1148
-rw-r--r--src/interfaces/ecpg/preproc/ecpg.type127
-rw-r--r--src/interfaces/ecpg/preproc/output.c16
-rw-r--r--src/interfaces/ecpg/preproc/parse.pl215
-rw-r--r--src/interfaces/ecpg/preproc/parser.c58
-rw-r--r--src/interfaces/ecpg/preproc/preproc_extern.h15
9 files changed, 752 insertions, 1216 deletions
diff --git a/src/interfaces/ecpg/preproc/README.parser b/src/interfaces/ecpg/preproc/README.parser
index 5698f5ab328..378cb9344c4 100644
--- a/src/interfaces/ecpg/preproc/README.parser
+++ b/src/interfaces/ecpg/preproc/README.parser
@@ -4,8 +4,8 @@ Some notes:
1) Most input matching core grammar productions is simply converted
to strings and concatenated together to form the SQL string
- passed to the server. parse.pl can automatically build the
- grammar actions needed to do this.
+ passed to the server. This is handled mostly automatically,
+ as described below.
2) Some grammar rules need special actions that are added to or
completely override the default token-concatenation behavior.
This is controlled by ecpg.addons as explained below.
@@ -14,11 +14,31 @@ Some notes:
4) ecpg.header contains the "prologue" part of preproc.y, including
support functions, Bison options, etc.
5) Additional terminals added by ECPG must be defined in ecpg.tokens.
- Additional nonterminals added by ECPG must be defined in ecpg.type.
+ Additional nonterminals added by ECPG must be defined in ecpg.type,
+ but only if they have non-void result type, which most don't.
ecpg.header, ecpg.tokens, ecpg.type, and ecpg.trailer are just
copied verbatim into preproc.y at appropriate points.
+
+In the pre-v18 implementation of ecpg, the strings constructed
+by grammar rules were returned as the Bison result of each rule.
+This led to a large number of effectively-identical rule actions,
+which caused compilation-time problems with some versions of clang.
+Now, rules that need to return a string are declared as having
+void type (which in Bison means leaving out any %type declaration
+for them). Instead, we abuse Bison's "location tracking" mechanism
+to carry the string results, which allows a single YYLLOC_DEFAULT
+call to handle the standard token-concatenation behavior for the
+vast majority of the rules. Rules that don't need to do anything
+else can omit a semantic action altogether. Rules that need to
+construct an output string specially can do so, but they should
+assign it to "@$" rather than the usual "$$"; also, to reference
+the string value of the N'th input token, write "@N" not "$N".
+(But rules that return something other than a simple string
+continue to use the normal Bison notations.)
+
+
ecpg.addons contains entries that begin with a line like
ECPG: concattokens ruletype
and typically have one or more following lines that are the code
@@ -69,9 +89,9 @@ parse.pl contains some tables that list backend grammar
productions to be ignored or modified.
Nonterminals that construct strings (as described above) should be
-given <str> type, which is parse.pl's default assumption for
-nonterminals found in gram.y. That can be overridden at need by
-making an entry in parse.pl's %replace_types table. %replace_types
+given void type, which is parse.pl's default assumption for
+nonterminals found in gram.y. If the result should be of some other
+type, make an entry in parse.pl's %replace_types table. %replace_types
can also be used to suppress output of a nonterminal's rules
altogether (in which case ecpg.trailer had better provide replacement
rules, since the nonterminal will still be referred to elsewhere).
diff --git a/src/interfaces/ecpg/preproc/ecpg.addons b/src/interfaces/ecpg/preproc/ecpg.addons
index 6a1893553b4..24ee54554e3 100644
--- a/src/interfaces/ecpg/preproc/ecpg.addons
+++ b/src/interfaces/ecpg/preproc/ecpg.addons
@@ -3,36 +3,35 @@ ECPG: stmtClosePortalStmt block
{
if (INFORMIX_MODE)
{
- if (pg_strcasecmp($1 + strlen("close "), "database") == 0)
+ if (pg_strcasecmp(@1 + strlen("close "), "database") == 0)
{
if (connection)
mmerror(PARSE_ERROR, ET_ERROR, "AT option not allowed in CLOSE DATABASE statement");
fprintf(base_yyout, "{ ECPGdisconnect(__LINE__, \"CURRENT\");");
whenever_action(2);
- free($1);
break;
}
}
- output_statement($1, 0, ECPGst_normal);
+ output_statement(@1, 0, ECPGst_normal);
}
ECPG: stmtDeallocateStmt block
{
- output_deallocate_prepare_statement($1);
+ output_deallocate_prepare_statement(@1);
}
ECPG: stmtDeclareCursorStmt block
{
- output_simple_statement($1, (strncmp($1, "ECPGset_var", strlen("ECPGset_var")) == 0) ? 4 : 0);
+ output_simple_statement(@1, (strncmp(@1, "ECPGset_var", strlen("ECPGset_var")) == 0) ? 4 : 0);
}
ECPG: stmtDiscardStmt block
ECPG: stmtFetchStmt block
- { output_statement($1, 1, ECPGst_normal); }
+ { output_statement(@1, 1, ECPGst_normal); }
ECPG: stmtDeleteStmt block
ECPG: stmtInsertStmt block
ECPG: stmtSelectStmt block
ECPG: stmtUpdateStmt block
- { output_statement($1, 1, ECPGst_prepnormal); }
+ { output_statement(@1, 1, ECPGst_prepnormal); }
ECPG: stmtExecuteStmt block
{
check_declared_list($1.name);
@@ -94,50 +93,45 @@ ECPG: stmtPrepareStmt block
}
ECPG: stmtTransactionStmt block
{
- fprintf(base_yyout, "{ ECPGtrans(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1);
+ fprintf(base_yyout, "{ ECPGtrans(__LINE__, %s, \"%s\");", connection ? connection : "NULL", @1);
whenever_action(2);
- free($1);
}
ECPG: toplevel_stmtTransactionStmtLegacy block
{
- fprintf(base_yyout, "{ ECPGtrans(__LINE__, %s, \"%s\");", connection ? connection : "NULL", $1);
+ fprintf(base_yyout, "{ ECPGtrans(__LINE__, %s, \"%s\");", connection ? connection : "NULL", @1);
whenever_action(2);
- free($1);
}
ECPG: stmtViewStmt rule
| ECPGAllocateDescr
{
- fprintf(base_yyout, "ECPGallocate_desc(__LINE__, %s);", $1);
+ fprintf(base_yyout, "ECPGallocate_desc(__LINE__, %s);", @1);
whenever_action(0);
- free($1);
}
| ECPGConnect
{
if (connection)
mmerror(PARSE_ERROR, ET_ERROR, "AT option not allowed in CONNECT statement");
- fprintf(base_yyout, "{ ECPGconnect(__LINE__, %d, %s, %d); ", compat, $1, autocommit);
+ fprintf(base_yyout, "{ ECPGconnect(__LINE__, %d, %s, %d); ", compat, @1, autocommit);
reset_variables();
whenever_action(2);
- free($1);
}
| ECPGDeclareStmt
{
- output_simple_statement($1, 0);
+ output_simple_statement(@1, 0);
}
| ECPGCursorStmt
{
- output_simple_statement($1, (strncmp($1, "ECPGset_var", strlen("ECPGset_var")) == 0) ? 4 : 0);
+ output_simple_statement(@1, (strncmp(@1, "ECPGset_var", strlen("ECPGset_var")) == 0) ? 4 : 0);
}
| ECPGDeallocateDescr
{
- fprintf(base_yyout, "ECPGdeallocate_desc(__LINE__, %s);", $1);
+ fprintf(base_yyout, "ECPGdeallocate_desc(__LINE__, %s);", @1);
whenever_action(0);
- free($1);
}
| ECPGDeclare
{
- output_simple_statement($1, 0);
+ output_simple_statement(@1, 0);
}
| ECPGDescribe
{
@@ -157,27 +151,25 @@ ECPG: stmtViewStmt rule
mmerror(PARSE_ERROR, ET_ERROR, "AT option not allowed in DISCONNECT statement");
fprintf(base_yyout, "{ ECPGdisconnect(__LINE__, %s);",
- $1 ? $1 : "\"CURRENT\"");
+ @1 ? @1 : "\"CURRENT\"");
whenever_action(2);
- free($1);
}
| ECPGExecuteImmediateStmt
{
- output_statement($1, 0, ECPGst_exec_immediate);
+ output_statement(@1, 0, ECPGst_exec_immediate);
}
| ECPGFree
{
const char *con = connection ? connection : "NULL";
- if (strcmp($1, "all") == 0)
+ if (strcmp(@1, "all") == 0)
fprintf(base_yyout, "{ ECPGdeallocate_all(__LINE__, %d, %s);", compat, con);
- else if ($1[0] == ':')
- fprintf(base_yyout, "{ ECPGdeallocate(__LINE__, %d, %s, %s);", compat, con, $1 + 1);
+ else if (@1[0] == ':')
+ fprintf(base_yyout, "{ ECPGdeallocate(__LINE__, %d, %s, %s);", compat, con, @1 + 1);
else
- fprintf(base_yyout, "{ ECPGdeallocate(__LINE__, %d, %s, \"%s\");", compat, con, $1);
+ fprintf(base_yyout, "{ ECPGdeallocate(__LINE__, %d, %s, \"%s\");", compat, con, @1);
whenever_action(2);
- free($1);
}
| ECPGGetDescriptor
{
@@ -188,15 +180,14 @@ ECPG: stmtViewStmt rule
}
| ECPGGetDescriptorHeader
{
- lookup_descriptor($1, connection);
- output_get_descr_header($1);
- free($1);
+ lookup_descriptor(@1, connection);
+ output_get_descr_header(@1);
}
| ECPGOpen
{
struct cursor *ptr;
- if ((ptr = add_additional_variables($1, true)) != NULL)
+ 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);
@@ -205,18 +196,16 @@ ECPG: stmtViewStmt rule
}
| ECPGSetAutocommit
{
- fprintf(base_yyout, "{ ECPGsetcommit(__LINE__, \"%s\", %s);", $1, connection ? connection : "NULL");
+ fprintf(base_yyout, "{ ECPGsetcommit(__LINE__, \"%s\", %s);", @1, connection ? connection : "NULL");
whenever_action(2);
- free($1);
}
| ECPGSetConnection
{
if (connection)
mmerror(PARSE_ERROR, ET_ERROR, "AT option not allowed in SET CONNECTION statement");
- fprintf(base_yyout, "{ ECPGsetconn(__LINE__, %s);", $1);
+ fprintf(base_yyout, "{ ECPGsetconn(__LINE__, %s);", @1);
whenever_action(2);
- free($1);
}
| ECPGSetDescriptor
{
@@ -227,17 +216,15 @@ ECPG: stmtViewStmt rule
}
| ECPGSetDescriptorHeader
{
- lookup_descriptor($1, connection);
- output_set_descr_header($1);
- free($1);
+ lookup_descriptor(@1, connection);
+ output_set_descr_header(@1);
}
| ECPGTypedef
{
if (connection)
mmerror(PARSE_ERROR, ET_ERROR, "AT option not allowed in TYPE statement");
- fprintf(base_yyout, "%s", $1);
- free($1);
+ fprintf(base_yyout, "%s", @1);
output_line_number();
}
| ECPGVar
@@ -245,180 +232,169 @@ ECPG: stmtViewStmt rule
if (connection)
mmerror(PARSE_ERROR, ET_ERROR, "AT option not allowed in VAR statement");
- output_simple_statement($1, 0);
+ output_simple_statement(@1, 0);
}
| ECPGWhenever
{
if (connection)
mmerror(PARSE_ERROR, ET_ERROR, "AT option not allowed in WHENEVER statement");
- output_simple_statement($1, 0);
+ output_simple_statement(@1, 0);
}
ECPG: where_or_current_clauseWHERECURRENT_POFcursor_name block
{
- char *cursor_marker = $4[0] == ':' ? mm_strdup("$0") : $4;
+ char *cursor_marker = @4[0] == ':' ? mm_strdup("$0") : @4;
- $$ = cat_str(2, mm_strdup("where current of"), cursor_marker);
+ @$ = cat_str(2, mm_strdup("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 &&
- (strcmp($7, "stdin") == 0 || strcmp($7, "stdout") == 0))
+ if (strcmp(@6, "from") == 0 &&
+ (strcmp(@7, "stdin") == 0 || strcmp(@7, "stdout") == 0))
mmerror(PARSE_ERROR, ET_WARNING, "COPY FROM STDIN is not implemented");
ECPG: var_valueNumericOnly addon
- if ($1[0] == '$')
- {
- free($1);
- $1 = mm_strdup("$0");
- }
+ if (@1[0] == '$')
+ @$ = mm_strdup("$0");
ECPG: fetch_argscursor_name addon
- struct cursor *ptr = add_additional_variables($1, false);
+ struct cursor *ptr = add_additional_variables(@1, false);
if (ptr->connection)
connection = mm_strdup(ptr->connection);
- if ($1[0] == ':')
- {
- free($1);
- $1 = mm_strdup("$0");
- }
+ if (@1[0] == ':')
+ @$ = mm_strdup("$0");
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)
connection = mm_strdup(ptr->connection);
- if ($2[0] == ':')
- {
- free($2);
- $2 = mm_strdup("$0");
- }
+ if (@2[0] == ':')
+ @$ = cat2_str(mm_strdup(@1), mm_strdup("$0"));
ECPG: fetch_argsNEXTopt_from_incursor_name addon
ECPG: fetch_argsPRIORopt_from_incursor_name addon
ECPG: fetch_argsFIRST_Popt_from_incursor_name addon
ECPG: fetch_argsLAST_Popt_from_incursor_name addon
ECPG: fetch_argsALLopt_from_incursor_name addon
- struct cursor *ptr = add_additional_variables($3, false);
+ struct cursor *ptr = add_additional_variables(@3, false);
if (ptr->connection)
connection = mm_strdup(ptr->connection);
- if ($3[0] == ':')
- {
- free($3);
- $3 = mm_strdup("$0");
- }
+ if (@3[0] == ':')
+ @$ = cat_str(3, mm_strdup(@1), mm_strdup(@2), mm_strdup("$0"));
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;
if (ptr->connection)
connection = mm_strdup(ptr->connection);
- if ($3[0] == ':')
+ if (@3[0] == ':')
{
- free($3);
- $3 = mm_strdup("$0");
+ @3 = mm_strdup("$0");
+ replace = true;
}
- if ($1[0] == '$')
+ if (@1[0] == '$')
{
- free($1);
- $1 = mm_strdup("$0");
+ @1 = mm_strdup("$0");
+ replace = true;
}
+ if (replace)
+ @$ = cat_str(3, mm_strdup(@1), mm_strdup(@2), mm_strdup(@3));
ECPG: fetch_argsFORWARDALLopt_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);
if (ptr->connection)
connection = mm_strdup(ptr->connection);
- if ($4[0] == ':')
- {
- free($4);
- $4 = mm_strdup("$0");
- }
+ if (@4[0] == ':')
+ @$ = cat_str(4, mm_strdup(@1), mm_strdup(@2), mm_strdup(@3), mm_strdup("$0"));
ECPG: fetch_argsABSOLUTE_PSignedIconstopt_from_incursor_name addon
ECPG: fetch_argsRELATIVE_PSignedIconstopt_from_incursor_name addon
ECPG: fetch_argsFORWARDSignedIconstopt_from_incursor_name addon
ECPG: fetch_argsBACKWARDSignedIconstopt_from_incursor_name addon
- struct cursor *ptr = add_additional_variables($4, false);
+ struct cursor *ptr = add_additional_variables(@4, false);
+ bool replace = false;
if (ptr->connection)
connection = mm_strdup(ptr->connection);
- if ($4[0] == ':')
+ if (@4[0] == ':')
{
- free($4);
- $4 = mm_strdup("$0");
+ @4 = mm_strdup("$0");
+ replace = true;
}
- if ($2[0] == '$')
+ if (@2[0] == '$')
{
- free($2);
- $2 = mm_strdup("$0");
+ @2 = mm_strdup("$0");
+ replace = true;
}
-ECPG: cursor_namename rule
+ if (replace)
+ @$ = cat_str(4, mm_strdup(@1), mm_strdup(@2), mm_strdup(@3), mm_strdup(@4));
+ECPG: cursor_namename block
| char_civar
{
- char *curname = mm_alloc(strlen($1) + 2);
+ char *curname = mm_alloc(strlen(@1) + 2);
- sprintf(curname, ":%s", $1);
- free($1);
- $1 = curname;
- $$ = $1;
+ sprintf(curname, ":%s", @1);
+ @$ = curname;
}
ECPG: ExplainableStmtExecuteStmt block
{
- $$ = $1.name;
+ @$ = $1.name;
}
ECPG: PrepareStmtPREPAREprepared_nameprep_type_clauseASPreparableStmt block
{
- $$.name = $2;
- $$.type = $3;
- $$.stmt = $5;
+ $$.name = @2;
+ $$.type = @3;
+ $$.stmt = @5;
}
| PREPARE prepared_name FROM execstring
{
- $$.name = $2;
+ $$.name = @2;
$$.type = NULL;
- $$.stmt = $4;
+ $$.stmt = @4;
}
ECPG: ExecuteStmtEXECUTEprepared_nameexecute_param_clauseexecute_rest block
{
- $$.name = $2;
- $$.type = $3;
+ $$.name = @2;
+ $$.type = @3;
}
ECPG: ExecuteStmtCREATEOptTempTABLEcreate_as_targetASEXECUTEprepared_nameexecute_param_clauseopt_with_dataexecute_rest block
{
- $$.name = cat_str(8, mm_strdup("create"), $2, mm_strdup("table"), $4, mm_strdup("as execute"), $7, $8, $9);
+ $$.name = @$;
}
ECPG: ExecuteStmtCREATEOptTempTABLEIF_PNOTEXISTScreate_as_targetASEXECUTEprepared_nameexecute_param_clauseopt_with_dataexecute_rest block
{
- $$.name = cat_str(8, mm_strdup("create"), $2, mm_strdup("table if not exists"), $7, mm_strdup("as execute"), $10, $11, $12);
+ $$.name = @$;
}
ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectStmt block
{
struct cursor *ptr,
*this;
- char *cursor_marker = $2[0] == ':' ? mm_strdup("$0") : mm_strdup($2);
+ char *cursor_marker = @2[0] == ':' ? mm_strdup("$0") : mm_strdup(@2);
char *comment,
*c1,
*c2;
- int (*strcmp_fn) (const char *, const char *) = (($2[0] == ':' || $2[0] == '"') ? strcmp : pg_strcasecmp);
+ int (*strcmp_fn) (const char *, const char *) = ((@2[0] == ':' || @2[0] == '"') ? strcmp : pg_strcasecmp);
- if (INFORMIX_MODE && pg_strcasecmp($2, "database") == 0)
+ if (INFORMIX_MODE && pg_strcasecmp(@2, "database") == 0)
mmfatal(PARSE_ERROR, "\"database\" cannot be used as cursor name in INFORMIX mode");
for (ptr = cur; ptr != NULL; ptr = ptr->next)
{
- if (strcmp_fn($2, ptr->name) == 0)
+ if (strcmp_fn(@2, ptr->name) == 0)
{
- if ($2[0] == ':')
- mmerror(PARSE_ERROR, ET_ERROR, "using variable \"%s\" in different declare statements is not supported", $2 + 1);
+ if (@2[0] == ':')
+ mmerror(PARSE_ERROR, ET_ERROR, "using variable \"%s\" in different declare statements is not supported", @2 + 1);
else
- mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" is already defined", $2);
+ mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" is already defined", @2);
}
}
this = (struct cursor *) mm_alloc(sizeof(struct cursor));
this->next = cur;
- this->name = $2;
+ this->name = mm_strdup(@2);
this->function = (current_function ? mm_strdup(current_function) : NULL);
this->connection = connection ? mm_strdup(connection) : NULL;
this->opened = false;
- this->command = cat_str(7, mm_strdup("declare"), cursor_marker, $3, mm_strdup("cursor"), $5, mm_strdup("for"), $7);
+ this->command = cat_str(7, mm_strdup("declare"), cursor_marker, @3, mm_strdup("cursor"), @5, mm_strdup("for"), @7);
this->argsinsert = argsinsert;
this->argsinsert_oos = NULL;
this->argsresult = argsresult;
@@ -435,47 +411,47 @@ ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectSt
}
comment = cat_str(3, mm_strdup("/*"), c1, mm_strdup("*/"));
- $$ = cat2_str(adjust_outofscope_cursor_vars(this), comment);
+ @$ = cat2_str(adjust_outofscope_cursor_vars(this), comment);
}
ECPG: ClosePortalStmtCLOSEcursor_name block
{
- char *cursor_marker = $2[0] == ':' ? mm_strdup("$0") : $2;
+ char *cursor_marker = @2[0] == ':' ? mm_strdup("$0") : @2;
struct cursor *ptr = NULL;
for (ptr = cur; ptr != NULL; ptr = ptr->next)
{
- if (strcmp($2, ptr->name) == 0)
+ if (strcmp(@2, ptr->name) == 0)
{
if (ptr->connection)
connection = mm_strdup(ptr->connection);
break;
}
}
- $$ = cat2_str(mm_strdup("close"), cursor_marker);
+ @$ = cat2_str(mm_strdup("close"), cursor_marker);
}
ECPG: opt_hold block
{
if (compat == ECPG_COMPAT_INFORMIX_SE && autocommit)
- $$ = mm_strdup("with hold");
+ @$ = mm_strdup("with hold");
else
- $$ = EMPTY;
+ @$ = EMPTY;
}
ECPG: into_clauseINTOOptTempTableName block
{
FoundInto = 1;
- $$ = cat2_str(mm_strdup("into"), $2);
+ @$ = cat2_str(mm_strdup("into"), @2);
}
| ecpg_into
{
- $$ = EMPTY;
+ @$ = EMPTY;
}
ECPG: TypenameSimpleTypenameopt_array_bounds block
{
- $$ = cat2_str($1, $2.str);
+ @$ = cat2_str(@1, $2.str);
}
ECPG: TypenameSETOFSimpleTypenameopt_array_bounds block
{
- $$ = cat_str(3, mm_strdup("setof"), $2, $3.str);
+ @$ = cat_str(3, mm_strdup("setof"), @2, $3.str);
}
ECPG: opt_array_boundsopt_array_bounds'['']' block
{
@@ -492,10 +468,10 @@ ECPG: opt_array_boundsopt_array_bounds'['']' block
$$.index1 = $1.index1;
$$.index2 = $1.index2;
if (strcmp($1.index1, "-1") == 0)
- $$.index1 = mm_strdup($3);
+ $$.index1 = mm_strdup(@3);
else if (strcmp($1.index2, "-1") == 0)
- $$.index2 = mm_strdup($3);
- $$.str = cat_str(4, $1.str, mm_strdup("["), $3, mm_strdup("]"));
+ $$.index2 = mm_strdup(@3);
+ $$.str = cat_str(4, $1.str, mm_strdup("["), @3, mm_strdup("]"));
}
ECPG: opt_array_bounds block
{
@@ -505,108 +481,100 @@ ECPG: opt_array_bounds block
}
ECPG: IconstICONST block
{
- $$ = make_name();
+ @$ = make_name();
}
ECPG: AexprConstNULL_P rule
- | civar { $$ = $1; }
- | civarind { $$ = $1; }
+ | civar
+ | civarind
ECPG: VariableShowStmtSHOWALL block
{
mmerror(PARSE_ERROR, ET_ERROR, "SHOW ALL is not implemented");
- $$ = EMPTY;
}
ECPG: FetchStmtMOVEfetch_args rule
| FETCH fetch_args ecpg_fetch_into
- {
- $$ = cat2_str(mm_strdup("fetch"), $2);
- }
| FETCH FORWARD cursor_name opt_ecpg_fetch_into
{
- char *cursor_marker = $3[0] == ':' ? mm_strdup("$0") : $3;
- struct cursor *ptr = add_additional_variables($3, false);
+ char *cursor_marker = @3[0] == ':' ? mm_strdup("$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, mm_strdup("fetch forward"), cursor_marker);
}
| FETCH FORWARD from_in cursor_name opt_ecpg_fetch_into
{
- char *cursor_marker = $4[0] == ':' ? mm_strdup("$0") : $4;
- struct cursor *ptr = add_additional_variables($4, false);
+ char *cursor_marker = @4[0] == ':' ? mm_strdup("$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, mm_strdup("fetch forward from"), cursor_marker);
}
| FETCH BACKWARD cursor_name opt_ecpg_fetch_into
{
- char *cursor_marker = $3[0] == ':' ? mm_strdup("$0") : $3;
- struct cursor *ptr = add_additional_variables($3, false);
+ char *cursor_marker = @3[0] == ':' ? mm_strdup("$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, mm_strdup("fetch backward"), cursor_marker);
}
| FETCH BACKWARD from_in cursor_name opt_ecpg_fetch_into
{
- char *cursor_marker = $4[0] == ':' ? mm_strdup("$0") : $4;
- struct cursor *ptr = add_additional_variables($4, false);
+ char *cursor_marker = @4[0] == ':' ? mm_strdup("$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, mm_strdup("fetch backward from"), cursor_marker);
}
| MOVE FORWARD cursor_name
{
- char *cursor_marker = $3[0] == ':' ? mm_strdup("$0") : $3;
- struct cursor *ptr = add_additional_variables($3, false);
+ char *cursor_marker = @3[0] == ':' ? mm_strdup("$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, mm_strdup("move forward"), cursor_marker);
}
| MOVE FORWARD from_in cursor_name
{
- char *cursor_marker = $4[0] == ':' ? mm_strdup("$0") : $4;
- struct cursor *ptr = add_additional_variables($4, false);
+ char *cursor_marker = @4[0] == ':' ? mm_strdup("$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, mm_strdup("move forward from"), cursor_marker);
}
| MOVE BACKWARD cursor_name
{
- char *cursor_marker = $3[0] == ':' ? mm_strdup("$0") : $3;
- struct cursor *ptr = add_additional_variables($3, false);
+ char *cursor_marker = @3[0] == ':' ? mm_strdup("$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, mm_strdup("move backward"), cursor_marker);
}
| MOVE BACKWARD from_in cursor_name
{
- char *cursor_marker = $4[0] == ':' ? mm_strdup("$0") : $4;
- struct cursor *ptr = add_additional_variables($4, false);
+ char *cursor_marker = @4[0] == ':' ? mm_strdup("$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, mm_strdup("move backward from"), cursor_marker);
}
ECPG: limit_clauseLIMITselect_limit_value','select_offset_value block
{
mmerror(PARSE_ERROR, ET_WARNING, "no longer supported LIMIT #,# syntax passed to server");
- $$ = cat_str(4, mm_strdup("limit"), $2, mm_strdup(","), $4);
}
ECPG: SignedIconstIconst rule
| civar
- {
- $$ = $1;
- }
diff --git a/src/interfaces/ecpg/preproc/ecpg.header b/src/interfaces/ecpg/preproc/ecpg.header
index 28e1b2aac40..8df6248c976 100644
--- a/src/interfaces/ecpg/preproc/ecpg.header
+++ b/src/interfaces/ecpg/preproc/ecpg.header
@@ -13,14 +13,6 @@
extern int base_yychar;
extern int base_yynerrs;
-/* Location tracking support --- simpler than bison's default */
-#define YYLLOC_DEFAULT(Current, Rhs, N) \
- do { \
- if (N) \
- (Current) = (Rhs)[1]; \
- else \
- (Current) = (Rhs)[0]; \
- } while (0)
/*
* The %name-prefix option below will make bison call base_yylex, but we
@@ -200,6 +192,61 @@ make3_str(char *str1, char *str2, char *str3)
return res_str;
}
+/*
+ * "Location tracking" support. We commandeer Bison's location tracking
+ * mechanism to manage the output string for productions that ordinarily would
+ * return a <str> result. This allows the majority of those productions to
+ * have default semantic actions, reducing the size of the parser, and also
+ * greatly reducing its compilation time on some versions of clang.
+ *
+ * To do this, we make YYLTYPE be a pointer to a malloc'd string, and then
+ * merge the location strings of the input tokens in the default YYLLOC
+ * computation. Productions that are okay with the standard merge need not
+ * do anything more; otherwise, they can override it by assigning to @$.
+ */
+#define YYLLOC_DEFAULT(Current, Rhs, N) yylloc_default(&(Current), Rhs, N)
+
+static void
+yylloc_default(YYLTYPE *target, YYLTYPE *rhs, int N)
+{
+ if (N > 1)
+ {
+ /* Concatenate non-empty inputs with one space between them */
+ char *result,
+ *ptr;
+ size_t needed = 0;
+
+ for (int i = 1; i <= N; i++)
+ {
+ size_t thislen = strlen(rhs[i]);
+
+ if (needed > 0 && thislen > 0)
+ needed++;
+ needed += thislen;
+ }
+ result = (char *) mm_alloc(needed + 1);
+ ptr = result;
+ for (int i = 1; i <= N; i++)
+ {
+ size_t thislen = strlen(rhs[i]);
+
+ if (ptr > result && thislen > 0)
+ *ptr++ = ' ';
+ memcpy(ptr, rhs[i], thislen);
+ ptr += thislen;
+ }
+ *ptr = '\0';
+ *target = result;
+ }
+ else if (N == 1)
+ {
+ /* Just re-use the single input */
+ *target = rhs[1];
+ }
+ else
+ *target = EMPTY;
+}
+
/* and the rest */
static char *
make_name(void)
diff --git a/src/interfaces/ecpg/preproc/ecpg.trailer b/src/interfaces/ecpg/preproc/ecpg.trailer
index f3ab73bed61..2a3949ca035 100644
--- a/src/interfaces/ecpg/preproc/ecpg.trailer
+++ b/src/interfaces/ecpg/preproc/ecpg.trailer
@@ -18,20 +18,17 @@ statement: ecpgstart at toplevel_stmt ';'
}
| ecpgstart ECPGVarDeclaration
{
- fprintf(base_yyout, "%s", $2);
- free($2);
+ fprintf(base_yyout, "%s", @$);
output_line_number();
}
| ECPGDeclaration
| c_thing
{
- fprintf(base_yyout, "%s", $1);
- free($1);
+ fprintf(base_yyout, "%s", @$);
}
| CPP_LINE
{
- fprintf(base_yyout, "%s", $1);
- free($1);
+ fprintf(base_yyout, "%s", @$);
}
| '{'
{
@@ -58,8 +55,6 @@ CreateAsStmt: CREATE OptTemp TABLE create_as_target AS
{
if (FoundInto == 1)
mmerror(PARSE_ERROR, ET_ERROR, "CREATE TABLE AS cannot specify INTO");
-
- $$ = cat_str(7, mm_strdup("create"), $2, mm_strdup("table"), $4, mm_strdup("as"), $7, $8);
}
| CREATE OptTemp TABLE IF_P NOT EXISTS create_as_target AS
{
@@ -68,14 +63,12 @@ CreateAsStmt: CREATE OptTemp TABLE create_as_target AS
{
if (FoundInto == 1)
mmerror(PARSE_ERROR, ET_ERROR, "CREATE TABLE AS cannot specify INTO");
-
- $$ = cat_str(7, mm_strdup("create"), $2, mm_strdup("table if not exists"), $7, mm_strdup("as"), $10, $11);
}
;
at: AT connection_object
{
- connection = $2;
+ connection = @2;
/*
* Do we have a variable as connection target? Remove the variable
@@ -91,55 +84,52 @@ at: AT connection_object
*/
ECPGConnect: SQL_CONNECT TO connection_target opt_connection_name opt_user
{
- $$ = cat_str(5, $3, mm_strdup(","), $5, mm_strdup(","), $4);
+ @$ = cat_str(5, @3, mm_strdup(","), @5, mm_strdup(","), @4);
}
| SQL_CONNECT TO DEFAULT
{
- $$ = mm_strdup("NULL, NULL, NULL, \"DEFAULT\"");
+ @$ = mm_strdup("NULL, NULL, NULL, \"DEFAULT\"");
}
/* also allow ORACLE syntax */
| SQL_CONNECT ora_user
{
- $$ = cat_str(3, mm_strdup("NULL,"), $2, mm_strdup(", NULL"));
+ @$ = cat_str(3, mm_strdup("NULL,"), @2, mm_strdup(", NULL"));
}
| DATABASE connection_target
{
- $$ = cat2_str($2, mm_strdup(", NULL, NULL, NULL"));
+ @$ = cat2_str(@2, mm_strdup(", NULL, NULL, NULL"));
}
;
connection_target: opt_database_name opt_server opt_port
{
/* old style: dbname[@server][:port] */
- if (strlen($2) > 0 && *($2) != '@')
- mmerror(PARSE_ERROR, ET_ERROR, "expected \"@\", found \"%s\"", $2);
+ if (strlen(@2) > 0 && *(@2) != '@')
+ mmerror(PARSE_ERROR, ET_ERROR, "expected \"@\", found \"%s\"", @2);
/* C strings need to be handled differently */
- if ($1[0] == '\"')
- $$ = $1;
+ if (@1[0] == '\"')
+ @$ = @1;
else
- $$ = make3_str(mm_strdup("\""), make3_str($1, $2, $3), mm_strdup("\""));
+ @$ = make3_str(mm_strdup("\""), make3_str(@1, @2, @3), mm_strdup("\""));
}
| db_prefix ':' server opt_port '/' opt_database_name opt_options
{
/* new style: <tcp|unix>:postgresql://server[:port][/dbname] */
- if (strncmp($1, "unix:postgresql", strlen("unix:postgresql")) != 0 && strncmp($1, "tcp:postgresql", strlen("tcp:postgresql")) != 0)
+ if (strncmp(@1, "unix:postgresql", strlen("unix:postgresql")) != 0 && strncmp(@1, "tcp:postgresql", strlen("tcp:postgresql")) != 0)
mmerror(PARSE_ERROR, ET_ERROR, "only protocols \"tcp\" and \"unix\" and database type \"postgresql\" are supported");
- if (strncmp($3, "//", strlen("//")) != 0)
- mmerror(PARSE_ERROR, ET_ERROR, "expected \"://\", found \"%s\"", $3);
+ if (strncmp(@3, "//", strlen("//")) != 0)
+ mmerror(PARSE_ERROR, ET_ERROR, "expected \"://\", found \"%s\"", @3);
- if (strncmp($1, "unix", strlen("unix")) == 0 &&
- strncmp($3 + strlen("//"), "localhost", strlen("localhost")) != 0 &&
- strncmp($3 + strlen("//"), "127.0.0.1", strlen("127.0.0.1")) != 0)
- mmerror(PARSE_ERROR, ET_ERROR, "Unix-domain sockets only work on \"localhost\" but not on \"%s\"", $3 + strlen("//"));
+ if (strncmp(@1, "unix", strlen("unix")) == 0 &&
+ strncmp(@3 + strlen("//"), "localhost", strlen("localhost")) != 0 &&
+ strncmp(@3 + strlen("//"), "127.0.0.1", strlen("127.0.0.1")) != 0)
+ mmerror(PARSE_ERROR, ET_ERROR, "Unix-domain sockets only work on \"localhost\" but not on \"%s\"", @3 + strlen("//"));
- $$ = make3_str(make3_str(mm_strdup("\""), $1, mm_strdup(":")), $3, make3_str(make3_str($4, mm_strdup("/"), $6), $7, mm_strdup("\"")));
+ @$ = make3_str(make3_str(mm_strdup("\""), @1, mm_strdup(":")), @3, make3_str(make3_str(@4, mm_strdup("/"), @6), @7, mm_strdup("\"")));
}
| char_variable
- {
- $$ = $1;
- }
| ecpg_sconst
{
/*
@@ -147,128 +137,107 @@ connection_target: opt_database_name opt_server opt_port
* so we change the quotes. Note, that the rule for ecpg_sconst adds
* these single quotes.
*/
- $1[0] = '\"';
- $1[strlen($1) - 1] = '\"';
- $$ = $1;
+ @1[0] = '\"';
+ @1[strlen(@1) - 1] = '\"';
+ @$ = @1;
}
;
opt_database_name: name
- {
- $$ = $1;
- }
| /* EMPTY */
- {
- $$ = EMPTY;
- }
;
db_prefix: ecpg_ident cvariable
{
- if (strcmp($2, "postgresql") != 0 && strcmp($2, "postgres") != 0)
- mmerror(PARSE_ERROR, ET_ERROR, "expected \"postgresql\", found \"%s\"", $2);
+ if (strcmp(@2, "postgresql") != 0 && strcmp(@2, "postgres") != 0)
+ mmerror(PARSE_ERROR, ET_ERROR, "expected \"postgresql\", found \"%s\"", @2);
- if (strcmp($1, "tcp") != 0 && strcmp($1, "unix") != 0)
- mmerror(PARSE_ERROR, ET_ERROR, "invalid connection type: %s", $1);
+ if (strcmp(@1, "tcp") != 0 && strcmp(@1, "unix") != 0)
+ mmerror(PARSE_ERROR, ET_ERROR, "invalid connection type: %s", @1);
- $$ = make3_str($1, mm_strdup(":"), $2);
+ @$ = make3_str(@1, mm_strdup(":"), @2);
}
;
server: Op server_name
{
- if (strcmp($1, "@") != 0 && strcmp($1, "//") != 0)
- mmerror(PARSE_ERROR, ET_ERROR, "expected \"@\" or \"://\", found \"%s\"", $1);
+ if (strcmp(@1, "@") != 0 && strcmp(@1, "//") != 0)
+ mmerror(PARSE_ERROR, ET_ERROR, "expected \"@\" or \"://\", found \"%s\"", @1);
- $$ = make2_str($1, $2);
+ @$ = make2_str(@1, @2);
}
;
opt_server: server
- {
- $$ = $1;
- }
| /* EMPTY */
- {
- $$ = EMPTY;
- }
;
server_name: ColId
- {
- $$ = $1;
- }
| ColId '.' server_name
- {
- $$ = make3_str($1, mm_strdup("."), $3);
- }
| IP
{
- $$ = make_name();
+ @$ = make_name();
}
;
opt_port: ':' Iconst
{
- $$ = make2_str(mm_strdup(":"), $2);
+ @$ = make2_str(mm_strdup(":"), @2);
}
| /* EMPTY */
- {
- $$ = EMPTY;
- }
;
opt_connection_name: AS connection_object
{
- $$ = $2;
+ @$ = @2;
}
| /* EMPTY */
{
- $$ = mm_strdup("NULL");
+ @$ = mm_strdup("NULL");
}
;
opt_user: USER ora_user
{
- $$ = $2;
+ @$ = @2;
}
| /* EMPTY */
{
- $$ = mm_strdup("NULL, NULL");
+ @$ = mm_strdup("NULL, NULL");
}
;
ora_user: user_name
{
- $$ = cat2_str($1, mm_strdup(", NULL"));
+ @$ = cat2_str(@1, mm_strdup(", NULL"));
}
| user_name '/' user_name
{
- $$ = cat_str(3, $1, mm_strdup(","), $3);
+ @$ = cat_str(3, @1, mm_strdup(","), @3);
}
| user_name SQL_IDENTIFIED BY user_name
{
- $$ = cat_str(3, $1, mm_strdup(","), $4);
+ @$ = cat_str(3, @1, mm_strdup(","), @4);
}
| user_name USING user_name
{
- $$ = cat_str(3, $1, mm_strdup(","), $3);
+ @$ = cat_str(3, @1, mm_strdup(","), @3);
}
;
user_name: RoleId
{
- if ($1[0] == '\"')
- $$ = $1;
+ if (@1[0] == '\"')
+ @$ = @1;
else
- $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\""));
+ @$ = make3_str(mm_strdup("\""), @1, mm_strdup("\""));
}
| ecpg_sconst
{
- if ($1[0] == '\"')
- $$ = $1;
+ if (@1[0] == '\"')
+ @$ = @1;
else
- $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\""));
+ @$ = make3_str(mm_strdup("\""), @1, mm_strdup("\""));
}
| civar
{
@@ -280,16 +249,16 @@ user_name: RoleId
/* handle varchars */
if (type == ECPGt_varchar)
- $$ = make2_str(mm_strdup(argsinsert->variable->name), mm_strdup(".arr"));
+ @$ = make2_str(mm_strdup(argsinsert->variable->name), mm_strdup(".arr"));
else
- $$ = mm_strdup(argsinsert->variable->name);
+ @$ = mm_strdup(argsinsert->variable->name);
}
;
char_variable: cvariable
{
/* check if we have a string variable */
- struct variable *p = find_variable($1);
+ struct variable *p = find_variable(@1);
enum ECPGttype type = p->type->type;
/* If we have just one character this is not a string */
@@ -306,14 +275,14 @@ char_variable: cvariable
case ECPGt_char:
case ECPGt_unsigned_char:
case ECPGt_string:
- $$ = $1;
+ @$ = @1;
break;
case ECPGt_varchar:
- $$ = make2_str($1, mm_strdup(".arr"));
+ @$ = make2_str(@1, mm_strdup(".arr"));
break;
default:
mmerror(PARSE_ERROR, ET_ERROR, "invalid data type");
- $$ = $1;
+ @$ = @1;
break;
}
}
@@ -322,72 +291,63 @@ char_variable: cvariable
opt_options: Op connect_options
{
- if (strlen($1) == 0)
+ if (strlen(@1) == 0)
mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement");
- if (strcmp($1, "?") != 0)
- mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", $1);
+ if (strcmp(@1, "?") != 0)
+ mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", @1);
- $$ = make2_str(mm_strdup("?"), $2);
+ @$ = make2_str(mm_strdup("?"), @2);
}
| /* EMPTY */
- {
- $$ = EMPTY;
- }
;
connect_options: ColId opt_opt_value
{
- $$ = make2_str($1, $2);
+ @$ = make2_str(@1, @2);
}
| ColId opt_opt_value Op connect_options
{
- if (strlen($3) == 0)
+ if (strlen(@3) == 0)
mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement");
- if (strcmp($3, "&") != 0)
- mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", $3);
+ if (strcmp(@3, "&") != 0)
+ mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", @3);
- $$ = make3_str(make2_str($1, $2), $3, $4);
+ @$ = make3_str(make2_str(@1, @2), @3, @4);
}
;
opt_opt_value: /* EMPTY */
- {
- $$ = EMPTY;
- }
| '=' Iconst
{
- $$ = make2_str(mm_strdup("="), $2);
+ @$ = make2_str(mm_strdup("="), @2);
}
| '=' ecpg_ident
{
- $$ = make2_str(mm_strdup("="), $2);
+ @$ = make2_str(mm_strdup("="), @2);
}
| '=' civar
{
- $$ = make2_str(mm_strdup("="), $2);
+ @$ = make2_str(mm_strdup("="), @2);
}
;
prepared_name: name
{
- if ($1[0] == '\"' && $1[strlen($1) - 1] == '\"') /* already quoted? */
- $$ = $1;
+ if (@1[0] == '\"' && @1[strlen(@1) - 1] == '\"') /* already quoted? */
+ @$ = @1;
else /* not quoted => convert to lowercase */
{
size_t i;
- for (i = 0; i < strlen($1); i++)
- $1[i] = tolower((unsigned char) $1[i]);
+ for (i = 0; i < strlen(@1); i++)
+ @1[i] = tolower((unsigned char) @1[i]);
- $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\""));
+ @$ = make3_str(mm_strdup("\""), @1, mm_strdup("\""));
}
}
| char_variable
- {
- $$ = $1;
- }
;
/*
@@ -400,7 +360,7 @@ ECPGDeclareStmt: DECLARE prepared_name STATEMENT
/* Check whether the declared name has been defined or not */
for (ptr = g_declared_list; ptr != NULL; ptr = ptr->next)
{
- if (strcmp($2, ptr->name) == 0)
+ if (strcmp(@2, ptr->name) == 0)
{
/* re-definition is not allowed */
mmerror(PARSE_ERROR, ET_ERROR, "name \"%s\" is already declared", ptr->name);
@@ -413,7 +373,7 @@ ECPGDeclareStmt: DECLARE prepared_name STATEMENT
if (ptr)
{
/* initial definition */
- ptr->name = $2;
+ ptr->name = @2;
if (connection)
ptr->connection = mm_strdup(connection);
else
@@ -423,7 +383,7 @@ ECPGDeclareStmt: DECLARE prepared_name STATEMENT
g_declared_list = ptr;
}
- $$ = cat_str(3, mm_strdup("/* declare "), mm_strdup($2), mm_strdup(" as an SQL identifier */"));
+ @$ = cat_str(3, mm_strdup("/* declare "), mm_strdup(@2), mm_strdup(" as an SQL identifier */"));
}
;
@@ -435,26 +395,26 @@ ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared_
{
struct cursor *ptr,
*this;
- char *cursor_marker = $2[0] == ':' ? mm_strdup("$0") : mm_strdup($2);
- int (*strcmp_fn) (const char *, const char *) = (($2[0] == ':' || $2[0] == '"') ? strcmp : pg_strcasecmp);
+ char *cursor_marker = @2[0] == ':' ? mm_strdup("$0") : mm_strdup(@2);
+ int (*strcmp_fn) (const char *, const char *) = ((@2[0] == ':' || @2[0] == '"') ? strcmp : pg_strcasecmp);
struct variable *thisquery = (struct variable *) mm_alloc(sizeof(struct variable));
char *comment;
char *con;
- if (INFORMIX_MODE && pg_strcasecmp($2, "database") == 0)
+ if (INFORMIX_MODE && pg_strcasecmp(@2, "database") == 0)
mmfatal(PARSE_ERROR, "\"database\" cannot be used as cursor name in INFORMIX mode");
- check_declared_list($7);
+ check_declared_list(@7);
con = connection ? connection : "NULL";
for (ptr = cur; ptr != NULL; ptr = ptr->next)
{
- if (strcmp_fn($2, ptr->name) == 0)
+ if (strcmp_fn(@2, ptr->name) == 0)
{
/* re-definition is a bug */
- if ($2[0] == ':')
- mmerror(PARSE_ERROR, ET_ERROR, "using variable \"%s\" in different declare statements is not supported", $2 + 1);
+ if (@2[0] == ':')
+ mmerror(PARSE_ERROR, ET_ERROR, "using variable \"%s\" in different declare statements is not supported", @2 + 1);
else
- mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" is already defined", $2);
+ mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" is already defined", @2);
}
}
@@ -462,24 +422,24 @@ ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared_
/* initial definition */
this->next = cur;
- this->name = $2;
+ this->name = @2;
this->function = (current_function ? mm_strdup(current_function) : NULL);
this->connection = connection ? mm_strdup(connection) : NULL;
- this->command = cat_str(6, mm_strdup("declare"), cursor_marker, $3, mm_strdup("cursor"), $5, mm_strdup("for $1"));
+ this->command = cat_str(6, mm_strdup("declare"), cursor_marker, @3, mm_strdup("cursor"), @5, mm_strdup("for $1"));
this->argsresult = NULL;
this->argsresult_oos = NULL;
thisquery->type = &ecpg_query;
thisquery->brace_level = 0;
thisquery->next = NULL;
- thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement(, , __LINE__)") + strlen(con) + strlen($7));
- sprintf(thisquery->name, "ECPGprepared_statement(%s, %s, __LINE__)", con, $7);
+ thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement(, , __LINE__)") + strlen(con) + strlen(@7));
+ sprintf(thisquery->name, "ECPGprepared_statement(%s, %s, __LINE__)", con, @7);
this->argsinsert = NULL;
this->argsinsert_oos = NULL;
- if ($2[0] == ':')
+ if (@2[0] == ':')
{
- struct variable *var = find_variable($2 + 1);
+ struct variable *var = find_variable(@2 + 1);
remove_variable_from_list(&argsinsert, var);
add_variable_to_head(&(this->argsinsert), var, &no_indicator);
@@ -490,7 +450,7 @@ ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared_
comment = cat_str(3, mm_strdup("/*"), mm_strdup(this->command), mm_strdup("*/"));
- $$ = cat_str(2, adjust_outofscope_cursor_vars(this),
+ @$ = cat_str(2, adjust_outofscope_cursor_vars(this),
comment);
}
;
@@ -501,7 +461,7 @@ ECPGExecuteImmediateStmt: EXECUTE IMMEDIATE execstring
* execute immediate means prepare the statement and immediately
* execute it
*/
- $$ = $3;
+ @$ = @3;
}
;
@@ -511,36 +471,24 @@ ECPGExecuteImmediateStmt: EXECUTE IMMEDIATE execstring
ECPGVarDeclaration: single_vt_declaration;
single_vt_declaration: type_declaration
- {
- $$ = $1;
- }
| var_declaration
- {
- $$ = $1;
- }
;
precision: NumericOnly
- {
- $$ = $1;
- }
;
opt_scale: ',' NumericOnly
{
- $$ = $2;
+ @$ = @2;
}
| /* EMPTY */
- {
- $$ = EMPTY;
- }
;
-ecpg_interval: opt_interval { $$ = $1; }
- | YEAR_P TO MINUTE_P { $$ = mm_strdup("year to minute"); }
- | YEAR_P TO SECOND_P { $$ = mm_strdup("year to second"); }
- | DAY_P TO DAY_P { $$ = mm_strdup("day to day"); }
- | MONTH_P TO MONTH_P { $$ = mm_strdup("month to month"); }
+ecpg_interval: opt_interval
+ | YEAR_P TO MINUTE_P
+ | YEAR_P TO SECOND_P
+ | DAY_P TO DAY_P
+ | MONTH_P TO MONTH_P
;
/*
@@ -552,8 +500,7 @@ ECPGDeclaration: sql_startdeclare
}
var_type_declarations sql_enddeclare
{
- fprintf(base_yyout, "%s/* exec sql end declare section */", $3);
- free($3);
+ fprintf(base_yyout, "%s/* exec sql end declare section */", @3);
output_line_number();
}
;
@@ -569,41 +516,17 @@ sql_enddeclare: ecpgstart END_P DECLARE SQL_SECTION ';'
;
var_type_declarations: /* EMPTY */
- {
- $$ = EMPTY;
- }
| vt_declarations
- {
- $$ = $1;
- }
;
vt_declarations: single_vt_declaration
- {
- $$ = $1;
- }
| CPP_LINE
- {
- $$ = $1;
- }
| vt_declarations single_vt_declaration
- {
- $$ = cat2_str($1, $2);
- }
| vt_declarations CPP_LINE
- {
- $$ = cat2_str($1, $2);
- }
;
variable_declarations: var_declaration
- {
- $$ = $1;
- }
| variable_declarations var_declaration
- {
- $$ = cat2_str($1, $2);
- }
;
type_declaration: S_TYPEDEF
@@ -614,18 +537,18 @@ type_declaration: S_TYPEDEF
}
var_type opt_pointer ECPGColLabel opt_array_bounds ';'
{
- add_typedef($5, $6.index1, $6.index2, $3.type_enum, $3.type_dimension, $3.type_index, initializer, *$4 ? 1 : 0);
+ add_typedef(@5, $6.index1, $6.index2, $3.type_enum, $3.type_dimension, $3.type_index, initializer, *@4 ? 1 : 0);
- fprintf(base_yyout, "typedef %s %s %s %s;\n", $3.type_str, *$4 ? "*" : "", $5, $6.str);
+ fprintf(base_yyout, "typedef %s %s %s %s;\n", $3.type_str, *@4 ? "*" : "", @5, $6.str);
output_line_number();
- $$ = mm_strdup("");
+ @$ = EMPTY;
}
;
var_declaration:
storage_declaration var_type
{
- actual_type[struct_level].type_storage = $1;
+ actual_type[struct_level].type_storage = @1;
actual_type[struct_level].type_enum = $2.type_enum;
actual_type[struct_level].type_str = $2.type_str;
actual_type[struct_level].type_dimension = $2.type_dimension;
@@ -636,7 +559,7 @@ var_declaration:
}
variable_list ';'
{
- $$ = cat_str(5, actual_startline[struct_level], $1, $2.type_str, $4, mm_strdup(";\n"));
+ @$ = cat_str(5, actual_startline[struct_level], @1, $2.type_str, @4, mm_strdup(";\n"));
}
| var_type
{
@@ -651,46 +574,31 @@ var_declaration:
}
variable_list ';'
{
- $$ = cat_str(4, actual_startline[struct_level], $1.type_str, $3, mm_strdup(";\n"));
+ @$ = cat_str(4, actual_startline[struct_level], $1.type_str, @3, mm_strdup(";\n"));
}
| struct_union_type_with_symbol ';'
{
- $$ = cat2_str($1, mm_strdup(";"));
+ @$ = cat2_str(@1, mm_strdup(";"));
}
;
opt_bit_field: ':' Iconst
- {
- $$ = cat2_str(mm_strdup(":"), $2);
- }
| /* EMPTY */
- {
- $$ = EMPTY;
- }
;
storage_declaration: storage_clause storage_modifier
- {
- $$ = cat2_str($1, $2);
- }
| storage_clause
- {
- $$ = $1;
- }
| storage_modifier
- {
- $$ = $1;
- }
;
-storage_clause: S_EXTERN { $$ = mm_strdup("extern"); }
- | S_STATIC { $$ = mm_strdup("static"); }
- | S_REGISTER { $$ = mm_strdup("register"); }
- | S_AUTO { $$ = mm_strdup("auto"); }
+storage_clause: S_EXTERN
+ | S_STATIC
+ | S_REGISTER
+ | S_AUTO
;
-storage_modifier: S_CONST { $$ = mm_strdup("const"); }
- | S_VOLATILE { $$ = mm_strdup("volatile"); }
+storage_modifier: S_CONST
+ | S_VOLATILE
;
var_type: simple_type
@@ -703,11 +611,11 @@ var_type: simple_type
}
| struct_union_type
{
- $$.type_str = $1;
+ $$.type_str = @1;
$$.type_dimension = mm_strdup("-1");
$$.type_index = mm_strdup("-1");
- if (strncmp($1, "struct", sizeof("struct") - 1) == 0)
+ if (strncmp(@1, "struct", sizeof("struct") - 1) == 0)
{
$$.type_enum = ECPGt_struct;
$$.type_sizeof = ECPGstruct_sizeof;
@@ -720,7 +628,7 @@ var_type: simple_type
}
| enum_type
{
- $$.type_str = $1;
+ $$.type_str = @1;
$$.type_enum = ECPGt_int;
$$.type_dimension = mm_strdup("-1");
$$.type_index = mm_strdup("-1");
@@ -749,12 +657,12 @@ var_type: simple_type
* will show up here as a plain identifier, and we need this duplicate
* code to recognize them.
*/
- if (strcmp($1, "numeric") == 0)
+ if (strcmp(@1, "numeric") == 0)
{
$$.type_enum = ECPGt_numeric;
$$.type_str = mm_strdup("numeric");
}
- else if (strcmp($1, "decimal") == 0)
+ else if (strcmp(@1, "decimal") == 0)
{
$$.type_enum = ECPGt_decimal;
$$.type_str = mm_strdup("decimal");
@@ -858,10 +766,10 @@ var_type: simple_type
* here, but not above because those are not currently SQL keywords.
* If they ever become so, they must gain duplicate productions above.
*/
- if (strlen($2) != 0 && strcmp($1, "datetime") != 0 && strcmp($1, "interval") != 0)
+ if (strlen(@2) != 0 && strcmp(@1, "datetime") != 0 && strcmp(@1, "interval") != 0)
mmerror(PARSE_ERROR, ET_ERROR, "interval specification not allowed here");
- if (strcmp($1, "varchar") == 0)
+ if (strcmp(@1, "varchar") == 0)
{
$$.type_enum = ECPGt_varchar;
$$.type_str = EMPTY; /* mm_strdup("varchar"); */
@@ -869,7 +777,7 @@ var_type: simple_type
$$.type_index = mm_strdup("-1");
$$.type_sizeof = NULL;
}
- else if (strcmp($1, "bytea") == 0)
+ else if (strcmp(@1, "bytea") == 0)
{
$$.type_enum = ECPGt_bytea;
$$.type_str = EMPTY;
@@ -877,7 +785,7 @@ var_type: simple_type
$$.type_index = mm_strdup("-1");
$$.type_sizeof = NULL;
}
- else if (strcmp($1, "float") == 0)
+ else if (strcmp(@1, "float") == 0)
{
$$.type_enum = ECPGt_float;
$$.type_str = mm_strdup("float");
@@ -885,7 +793,7 @@ var_type: simple_type
$$.type_index = mm_strdup("-1");
$$.type_sizeof = NULL;
}
- else if (strcmp($1, "double") == 0)
+ else if (strcmp(@1, "double") == 0)
{
$$.type_enum = ECPGt_double;
$$.type_str = mm_strdup("double");
@@ -893,7 +801,7 @@ var_type: simple_type
$$.type_index = mm_strdup("-1");
$$.type_sizeof = NULL;
}
- else if (strcmp($1, "numeric") == 0)
+ else if (strcmp(@1, "numeric") == 0)
{
$$.type_enum = ECPGt_numeric;
$$.type_str = mm_strdup("numeric");
@@ -901,7 +809,7 @@ var_type: simple_type
$$.type_index = mm_strdup("-1");
$$.type_sizeof = NULL;
}
- else if (strcmp($1, "decimal") == 0)
+ else if (strcmp(@1, "decimal") == 0)
{
$$.type_enum = ECPGt_decimal;
$$.type_str = mm_strdup("decimal");
@@ -909,7 +817,7 @@ var_type: simple_type
$$.type_index = mm_strdup("-1");
$$.type_sizeof = NULL;
}
- else if (strcmp($1, "date") == 0)
+ else if (strcmp(@1, "date") == 0)
{
$$.type_enum = ECPGt_date;
$$.type_str = mm_strdup("date");
@@ -917,7 +825,7 @@ var_type: simple_type
$$.type_index = mm_strdup("-1");
$$.type_sizeof = NULL;
}
- else if (strcmp($1, "timestamp") == 0)
+ else if (strcmp(@1, "timestamp") == 0)
{
$$.type_enum = ECPGt_timestamp;
$$.type_str = mm_strdup("timestamp");
@@ -925,7 +833,7 @@ var_type: simple_type
$$.type_index = mm_strdup("-1");
$$.type_sizeof = NULL;
}
- else if (strcmp($1, "interval") == 0)
+ else if (strcmp(@1, "interval") == 0)
{
$$.type_enum = ECPGt_interval;
$$.type_str = mm_strdup("interval");
@@ -933,7 +841,7 @@ var_type: simple_type
$$.type_index = mm_strdup("-1");
$$.type_sizeof = NULL;
}
- else if (strcmp($1, "datetime") == 0)
+ else if (strcmp(@1, "datetime") == 0)
{
$$.type_enum = ECPGt_timestamp;
$$.type_str = mm_strdup("timestamp");
@@ -941,7 +849,7 @@ var_type: simple_type
$$.type_index = mm_strdup("-1");
$$.type_sizeof = NULL;
}
- else if ((strcmp($1, "string") == 0) && INFORMIX_MODE)
+ else if ((strcmp(@1, "string") == 0) && INFORMIX_MODE)
{
$$.type_enum = ECPGt_string;
$$.type_str = mm_strdup("char");
@@ -952,7 +860,7 @@ var_type: simple_type
else
{
/* Otherwise, it must be a user-defined typedef name */
- struct typedefs *this = get_typedef($1, false);
+ struct typedefs *this = get_typedef(@1, false);
$$.type_str = (this->type->type_enum == ECPGt_varchar || this->type->type_enum == ECPGt_bytea) ? EMPTY : mm_strdup(this->name);
$$.type_enum = this->type->type_enum;
@@ -1001,23 +909,11 @@ var_type: simple_type
;
enum_type: ENUM_P symbol enum_definition
- {
- $$ = cat_str(3, mm_strdup("enum"), $2, $3);
- }
| ENUM_P enum_definition
- {
- $$ = cat2_str(mm_strdup("enum"), $2);
- }
| ENUM_P symbol
- {
- $$ = cat2_str(mm_strdup("enum"), $2);
- }
;
enum_definition: '{' c_list '}'
- {
- $$ = cat_str(3, mm_strdup("{"), $2, mm_strdup("}"));
- }
;
struct_union_type_with_symbol: s_struct_union_symbol
@@ -1071,14 +967,11 @@ struct_union_type_with_symbol: s_struct_union_symbol
this->struct_member_list = struct_member_list[struct_level];
types = this;
- $$ = cat_str(4, su_type.type_str, mm_strdup("{"), $4, mm_strdup("}"));
+ @$ = cat_str(4, su_type.type_str, mm_strdup("{"), @4, mm_strdup("}"));
}
;
struct_union_type: struct_union_type_with_symbol
- {
- $$ = $1;
- }
| s_struct_union
{
struct_member_list[struct_level++] = NULL;
@@ -1090,20 +983,20 @@ struct_union_type: struct_union_type_with_symbol
ECPGfree_struct_member(struct_member_list[struct_level]);
struct_member_list[struct_level] = NULL;
struct_level--;
- $$ = cat_str(4, $1, mm_strdup("{"), $4, mm_strdup("}"));
+ @$ = cat_str(4, @1, mm_strdup("{"), @4, mm_strdup("}"));
}
;
s_struct_union_symbol: SQL_STRUCT symbol
{
$$.su = mm_strdup("struct");
- $$.symbol = $2;
+ $$.symbol = @2;
ECPGstruct_sizeof = cat_str(3, mm_strdup("sizeof("), cat2_str(mm_strdup($$.su), mm_strdup($$.symbol)), mm_strdup(")"));
}
| UNION symbol
{
$$.su = mm_strdup("union");
- $$.symbol = $2;
+ $$.symbol = @2;
}
;
@@ -1111,15 +1004,15 @@ s_struct_union: SQL_STRUCT
{
ECPGstruct_sizeof = mm_strdup(""); /* This must not be NULL to
* distinguish from simple types. */
- $$ = mm_strdup("struct");
+ @$ = mm_strdup("struct");
}
| UNION
{
- $$ = mm_strdup("union");
+ @$ = mm_strdup("union");
}
;
-simple_type: unsigned_type { $$ = $1; }
+simple_type: unsigned_type
| opt_signed signed_type { $$ = $2; }
;
@@ -1151,15 +1044,12 @@ opt_signed: SQL_SIGNED
;
variable_list: variable
- {
- $$ = $1;
- }
| variable_list ',' variable
{
if (actual_type[struct_level].type_enum == ECPGt_varchar || actual_type[struct_level].type_enum == ECPGt_bytea)
- $$ = cat_str(4, $1, mm_strdup(";"), mm_strdup(actual_type[struct_level].type_storage), $3);
+ @$ = cat_str(4, @1, mm_strdup(";"), mm_strdup(actual_type[struct_level].type_storage), @3);
else
- $$ = cat_str(3, $1, mm_strdup(","), $3);
+ @$ = cat_str(3, @1, mm_strdup(","), @3);
}
;
@@ -1173,7 +1063,7 @@ variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initialize
int *varlen_type_counter;
char *struct_name;
- adjust_array(actual_type[struct_level].type_enum, &dimension, &length, actual_type[struct_level].type_dimension, actual_type[struct_level].type_index, strlen($1), false);
+ adjust_array(actual_type[struct_level].type_enum, &dimension, &length, actual_type[struct_level].type_dimension, actual_type[struct_level].type_index, strlen(@1), false);
switch (actual_type[struct_level].type_enum)
{
case ECPGt_struct:
@@ -1183,7 +1073,7 @@ variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initialize
else
type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_str, actual_type[struct_level].type_sizeof), dimension);
- $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5);
+ @$ = cat_str(5, @1, mm_strdup(@2), $3.str, @4, @5);
break;
case ECPGt_varchar:
@@ -1222,9 +1112,9 @@ variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initialize
vcn = (char *) mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
sprintf(vcn, "%d", *varlen_type_counter);
if (strcmp(dimension, "0") == 0)
- $$ = cat_str(7, make2_str(mm_strdup(struct_name), vcn), mm_strdup(" { int len; char arr["), mm_strdup(length), mm_strdup("]; } *"), mm_strdup($2), $4, $5);
+ @$ = cat_str(7, make2_str(mm_strdup(struct_name), vcn), mm_strdup(" { int len; char arr["), mm_strdup(length), mm_strdup("]; } *"), mm_strdup(@2), @4, @5);
else
- $$ = cat_str(8, make2_str(mm_strdup(struct_name), vcn), mm_strdup(" { int len; char arr["), mm_strdup(length), mm_strdup("]; } "), mm_strdup($2), dim_str, $4, $5);
+ @$ = cat_str(8, make2_str(mm_strdup(struct_name), vcn), mm_strdup(" { int len; char arr["), mm_strdup(length), mm_strdup("]; } "), mm_strdup(@2), dim_str, @4, @5);
(*varlen_type_counter)++;
break;
@@ -1233,7 +1123,7 @@ variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initialize
case ECPGt_string:
if (atoi(dimension) == -1)
{
- int i = strlen($5);
+ int i = strlen(@5);
if (atoi(length) == -1 && i > 0) /* char <var>[] =
* "string" */
@@ -1244,14 +1134,14 @@ variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initialize
*/
free(length);
length = mm_alloc(i + sizeof("sizeof()"));
- sprintf(length, "sizeof(%s)", $5 + 2);
+ sprintf(length, "sizeof(%s)", @5 + 2);
}
type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0);
}
else
type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0), dimension);
- $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5);
+ @$ = cat_str(5, @1, mm_strdup(@2), $3.str, @4, @5);
break;
default:
@@ -1260,41 +1150,29 @@ variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initialize
else
type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, mm_strdup("1"), 0), dimension);
- $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5);
+ @$ = cat_str(5, @1, mm_strdup(@2), $3.str, @4, @5);
break;
}
if (struct_level == 0)
- new_variable($2, type, braces_open);
+ new_variable(@2, type, braces_open);
else
- ECPGmake_struct_member($2, type, &(struct_member_list[struct_level - 1]));
-
- free($2);
+ ECPGmake_struct_member(@2, type, &(struct_member_list[struct_level - 1]));
}
;
opt_initializer: /* EMPTY */
- {
- $$ = EMPTY;
- }
| '=' c_term
{
initializer = 1;
- $$ = cat2_str(mm_strdup("="), $2);
}
;
opt_pointer: /* EMPTY */
- {
- $$ = EMPTY;
- }
| '*'
- {
- $$ = mm_strdup("*");
- }
| '*' '*'
{
- $$ = mm_strdup("**");
+ @$ = mm_strdup("**");
}
;
@@ -1304,7 +1182,7 @@ opt_pointer: /* EMPTY */
ECPGDeclare: DECLARE STATEMENT ecpg_ident
{
/* this is only supported for compatibility */
- $$ = cat_str(3, mm_strdup("/* declare statement"), $3, mm_strdup("*/"));
+ @$ = cat_str(3, mm_strdup("/* declare statement"), @3, mm_strdup("*/"));
}
;
/*
@@ -1312,49 +1190,40 @@ ECPGDeclare: DECLARE STATEMENT ecpg_ident
*/
ECPGDisconnect: SQL_DISCONNECT dis_name
{
- $$ = $2;
+ @$ = @2;
}
;
dis_name: connection_object
- {
- $$ = $1;
- }
| CURRENT_P
{
- $$ = mm_strdup("\"CURRENT\"");
+ @$ = mm_strdup("\"CURRENT\"");
}
| ALL
{
- $$ = mm_strdup("\"ALL\"");
+ @$ = mm_strdup("\"ALL\"");
}
| /* EMPTY */
{
- $$ = mm_strdup("\"CURRENT\"");
+ @$ = mm_strdup("\"CURRENT\"");
}
;
connection_object: name
{
- $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\""));
+ @$ = make3_str(mm_strdup("\""), @1, mm_strdup("\""));
}
| DEFAULT
{
- $$ = mm_strdup("\"DEFAULT\"");
+ @$ = mm_strdup("\"DEFAULT\"");
}
| char_variable
- {
- $$ = $1;
- }
;
execstring: char_variable
- {
- $$ = $1;
- }
| CSTRING
{
- $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\""));
+ @$ = make3_str(mm_strdup("\""), @1, mm_strdup("\""));
}
;
@@ -1364,11 +1233,11 @@ execstring: char_variable
*/
ECPGFree: SQL_FREE cursor_name
{
- $$ = $2;
+ @$ = @2;
}
| SQL_FREE ALL
{
- $$ = mm_strdup("all");
+ @$ = mm_strdup("all");
}
;
@@ -1377,60 +1246,51 @@ ECPGFree: SQL_FREE cursor_name
*/
ECPGOpen: SQL_OPEN cursor_name opt_ecpg_using
{
- if ($2[0] == ':')
- remove_variable_from_list(&argsinsert, find_variable($2 + 1));
- $$ = $2;
+ if (@2[0] == ':')
+ remove_variable_from_list(&argsinsert, find_variable(@2 + 1));
+ @$ = @2;
}
;
opt_ecpg_using: /* EMPTY */
- {
- $$ = EMPTY;
- }
| ecpg_using
- {
- $$ = $1;
- }
;
ecpg_using: USING using_list
{
- $$ = EMPTY;
+ @$ = EMPTY;
}
| using_descriptor
- {
- $$ = $1;
- }
;
using_descriptor: USING SQL_P SQL_DESCRIPTOR quoted_ident_stringvar
{
- add_variable_to_head(&argsinsert, descriptor_variable($4, 0), &no_indicator);
- $$ = EMPTY;
+ add_variable_to_head(&argsinsert, descriptor_variable(@4, 0), &no_indicator);
+ @$ = EMPTY;
}
| USING SQL_DESCRIPTOR name
{
- add_variable_to_head(&argsinsert, sqlda_variable($3), &no_indicator);
- $$ = EMPTY;
+ add_variable_to_head(&argsinsert, sqlda_variable(@3), &no_indicator);
+ @$ = EMPTY;
}
;
into_descriptor: INTO SQL_P SQL_DESCRIPTOR quoted_ident_stringvar
{
- add_variable_to_head(&argsresult, descriptor_variable($4, 1), &no_indicator);
- $$ = EMPTY;
+ add_variable_to_head(&argsresult, descriptor_variable(@4, 1), &no_indicator);
+ @$ = EMPTY;
}
| INTO SQL_DESCRIPTOR name
{
- add_variable_to_head(&argsresult, sqlda_variable($3), &no_indicator);
- $$ = EMPTY;
+ add_variable_to_head(&argsresult, sqlda_variable(@3), &no_indicator);
+ @$ = EMPTY;
}
;
into_sqlda: INTO name
{
- add_variable_to_head(&argsresult, sqlda_variable($2), &no_indicator);
- $$ = EMPTY;
+ add_variable_to_head(&argsresult, sqlda_variable(@2), &no_indicator);
+ @$ = EMPTY;
}
;
@@ -1441,55 +1301,28 @@ UsingValue: UsingConst
{
char *length = mm_alloc(32);
- sprintf(length, "%zu", strlen($1));
- add_variable_to_head(&argsinsert, new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0), &no_indicator);
+ sprintf(length, "%zu", strlen(@1));
+ add_variable_to_head(&argsinsert, new_variable(@1, ECPGmake_simple_type(ECPGt_const, length, 0), 0), &no_indicator);
}
| civar
{
- $$ = EMPTY;
+ @$ = EMPTY;
}
| civarind
{
- $$ = EMPTY;
+ @$ = EMPTY;
}
;
UsingConst: Iconst
- {
- $$ = $1;
- }
| '+' Iconst
- {
- $$ = cat_str(2, mm_strdup("+"), $2);
- }
| '-' Iconst
- {
- $$ = cat_str(2, mm_strdup("-"), $2);
- }
| ecpg_fconst
- {
- $$ = $1;
- }
| '+' ecpg_fconst
- {
- $$ = cat_str(2, mm_strdup("+"), $2);
- }
| '-' ecpg_fconst
- {
- $$ = cat_str(2, mm_strdup("-"), $2);
- }
| ecpg_sconst
- {
- $$ = $1;
- }
| ecpg_bconst
- {
- $$ = $1;
- }
| ecpg_xconst
- {
- $$ = $1;
- }
;
/*
@@ -1498,7 +1331,7 @@ UsingConst: Iconst
ECPGDescribe: SQL_DESCRIBE INPUT_P prepared_name using_descriptor
{
$$.input = 1;
- $$.stmt_name = $3;
+ $$.stmt_name = @3;
}
| SQL_DESCRIBE opt_output prepared_name using_descriptor
{
@@ -1509,33 +1342,27 @@ ECPGDescribe: SQL_DESCRIBE INPUT_P prepared_name using_descriptor
add_variable_to_head(&argsresult, var, &no_indicator);
$$.input = 0;
- $$.stmt_name = $3;
+ $$.stmt_name = @3;
}
| SQL_DESCRIBE opt_output prepared_name into_descriptor
{
$$.input = 0;
- $$.stmt_name = $3;
+ $$.stmt_name = @3;
}
| SQL_DESCRIBE INPUT_P prepared_name into_sqlda
{
$$.input = 1;
- $$.stmt_name = $3;
+ $$.stmt_name = @3;
}
| SQL_DESCRIBE opt_output prepared_name into_sqlda
{
$$.input = 0;
- $$.stmt_name = $3;
+ $$.stmt_name = @3;
}
;
opt_output: SQL_OUTPUT
- {
- $$ = mm_strdup("output");
- }
| /* EMPTY */
- {
- $$ = EMPTY;
- }
;
/*
@@ -1549,8 +1376,8 @@ opt_output: SQL_OUTPUT
*/
ECPGAllocateDescr: SQL_ALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
{
- add_descriptor($3, connection);
- $$ = $3;
+ add_descriptor(@3, connection);
+ @$ = @3;
}
;
@@ -1560,8 +1387,8 @@ ECPGAllocateDescr: SQL_ALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
*/
ECPGDeallocateDescr: DEALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
{
- drop_descriptor($3, connection);
- $$ = $3;
+ drop_descriptor(@3, connection);
+ @$ = @3;
}
;
@@ -1571,7 +1398,7 @@ ECPGDeallocateDescr: DEALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar
ECPGGetDescriptorHeader: SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar ECPGGetDescHeaderItems
{
- $$ = $3;
+ @$ = @3;
}
;
@@ -1581,13 +1408,13 @@ ECPGGetDescHeaderItems: ECPGGetDescHeaderItem
ECPGGetDescHeaderItem: cvariable '=' desc_header_item
{
- push_assignment($1, $3);
+ push_assignment(@1, $3);
}
;
ECPGSetDescriptorHeader: SET SQL_DESCRIPTOR quoted_ident_stringvar ECPGSetDescHeaderItems
{
- $$ = $3;
+ @$ = @3;
}
;
@@ -1597,7 +1424,7 @@ ECPGSetDescHeaderItems: ECPGSetDescHeaderItem
ECPGSetDescHeaderItem: desc_header_item '=' IntConstVar
{
- push_assignment($3, $1);
+ push_assignment(@3, $1);
}
;
@@ -1605,14 +1432,10 @@ IntConstVar: Iconst
{
char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
- sprintf(length, "%zu", strlen($1));
- new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
- $$ = $1;
+ sprintf(length, "%zu", strlen(@1));
+ new_variable(@1, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
}
| cvariable
- {
- $$ = $1;
- }
;
desc_header_item: SQL_COUNT
@@ -1627,8 +1450,8 @@ desc_header_item: SQL_COUNT
ECPGGetDescriptor: SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGGetDescItems
{
- $$.str = $5;
- $$.name = $3;
+ $$.str = @5;
+ $$.name = @3;
}
;
@@ -1638,14 +1461,14 @@ ECPGGetDescItems: ECPGGetDescItem
ECPGGetDescItem: cvariable '=' descriptor_item
{
- push_assignment($1, $3);
+ push_assignment(@1, $3);
}
;
ECPGSetDescriptor: SET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGSetDescItems
{
- $$.str = $5;
- $$.name = $3;
+ $$.str = @5;
+ $$.name = @3;
}
;
@@ -1655,7 +1478,7 @@ ECPGSetDescItems: ECPGSetDescItem
ECPGSetDescItem: descriptor_item '=' AllConstVar
{
- push_assignment($3, $1);
+ push_assignment(@3, $1);
}
;
@@ -1663,41 +1486,37 @@ AllConstVar: ecpg_fconst
{
char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
- sprintf(length, "%zu", strlen($1));
- new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
- $$ = $1;
+ sprintf(length, "%zu", strlen(@1));
+ new_variable(@1, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
}
| IntConstVar
- {
- $$ = $1;
- }
| '-' ecpg_fconst
{
char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
- char *var = cat2_str(mm_strdup("-"), $2);
+ char *var = cat2_str(mm_strdup("-"), @2);
sprintf(length, "%zu", strlen(var));
new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
- $$ = var;
+ @$ = var;
}
| '-' Iconst
{
char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
- char *var = cat2_str(mm_strdup("-"), $2);
+ char *var = cat2_str(mm_strdup("-"), @2);
sprintf(length, "%zu", strlen(var));
new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
- $$ = var;
+ @$ = var;
}
| ecpg_sconst
{
char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3);
- char *var = $1 + 1;
+ char *var = @1 + 1;
var[strlen(var) - 1] = '\0';
sprintf(length, "%zu", strlen(var));
new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0);
- $$ = var;
+ @$ = var;
}
;
@@ -1724,22 +1543,16 @@ descriptor_item: SQL_CARDINALITY { $$ = ECPGd_cardinality; }
*/
ECPGSetAutocommit: SET SQL_AUTOCOMMIT '=' on_off
{
- $$ = $4;
+ @$ = @4;
}
| SET SQL_AUTOCOMMIT TO on_off
{
- $$ = $4;
+ @$ = @4;
}
;
on_off: ON
- {
- $$ = mm_strdup("on");
- }
| OFF
- {
- $$ = mm_strdup("off");
- }
;
/*
@@ -1748,15 +1561,15 @@ on_off: ON
*/
ECPGSetConnection: SET CONNECTION TO connection_object
{
- $$ = $4;
+ @$ = @4;
}
| SET CONNECTION '=' connection_object
{
- $$ = $4;
+ @$ = @4;
}
| SET CONNECTION connection_object
{
- $$ = $3;
+ @$ = @3;
}
;
@@ -1771,23 +1584,17 @@ ECPGTypedef: TYPE_P
}
ECPGColLabel IS var_type opt_array_bounds opt_reference
{
- add_typedef($3, $6.index1, $6.index2, $5.type_enum, $5.type_dimension, $5.type_index, initializer, *$7 ? 1 : 0);
+ add_typedef(@3, $6.index1, $6.index2, $5.type_enum, $5.type_dimension, $5.type_index, initializer, *@7 ? 1 : 0);
if (auto_create_c == false)
- $$ = cat_str(7, mm_strdup("/* exec sql type"), mm_strdup($3), mm_strdup("is"), mm_strdup($5.type_str), mm_strdup($6.str), $7, mm_strdup("*/"));
+ @$ = cat_str(7, mm_strdup("/* exec sql type"), mm_strdup(@3), mm_strdup("is"), mm_strdup($5.type_str), mm_strdup($6.str), @7, mm_strdup("*/"));
else
- $$ = cat_str(6, mm_strdup("typedef "), mm_strdup($5.type_str), *$7 ? mm_strdup("*") : mm_strdup(""), mm_strdup($3), mm_strdup($6.str), mm_strdup(";"));
+ @$ = cat_str(6, mm_strdup("typedef "), mm_strdup($5.type_str), *@7 ? mm_strdup("*") : mm_strdup(""), mm_strdup(@3), mm_strdup($6.str), mm_strdup(";"));
}
;
opt_reference: SQL_REFERENCE
- {
- $$ = mm_strdup("reference");
- }
| /* EMPTY */
- {
- $$ = EMPTY;
- }
;
/*
@@ -1801,7 +1608,7 @@ ECPGVar: SQL_VAR
}
ColLabel IS var_type opt_array_bounds opt_reference
{
- struct variable *p = find_variable($3);
+ struct variable *p = find_variable(@3);
char *dimension = $6.index1;
char *length = $6.index2;
struct ECPGtype *type;
@@ -1812,7 +1619,7 @@ ECPGVar: SQL_VAR
mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in EXEC SQL VAR command");
else
{
- adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7 ? 1 : 0, false);
+ adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *@7 ? 1 : 0, false);
switch ($5.type_enum)
{
@@ -1856,7 +1663,7 @@ ECPGVar: SQL_VAR
p->type = type;
}
- $$ = cat_str(7, mm_strdup("/* exec sql var"), mm_strdup($3), mm_strdup("is"), mm_strdup($5.type_str), mm_strdup($6.str), $7, mm_strdup("*/"));
+ @$ = cat_str(7, mm_strdup("/* exec sql var"), mm_strdup(@3), mm_strdup("is"), mm_strdup($5.type_str), mm_strdup($6.str), @7, mm_strdup("*/"));
}
;
@@ -1868,19 +1675,19 @@ ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action
{
when_error.code = $<action>3.code;
when_error.command = $<action>3.command;
- $$ = cat_str(3, mm_strdup("/* exec sql whenever sqlerror "), $3.str, mm_strdup("; */"));
+ @$ = cat_str(3, mm_strdup("/* exec sql whenever sqlerror "), $3.str, mm_strdup("; */"));
}
| SQL_WHENEVER NOT SQL_FOUND action
{
when_nf.code = $<action>4.code;
when_nf.command = $<action>4.command;
- $$ = cat_str(3, mm_strdup("/* exec sql whenever not found "), $4.str, mm_strdup("; */"));
+ @$ = cat_str(3, mm_strdup("/* exec sql whenever not found "), $4.str, mm_strdup("; */"));
}
| SQL_WHENEVER SQL_SQLWARNING action
{
when_warn.code = $<action>3.code;
when_warn.command = $<action>3.command;
- $$ = cat_str(3, mm_strdup("/* exec sql whenever sql_warning "), $3.str, mm_strdup("; */"));
+ @$ = cat_str(3, mm_strdup("/* exec sql whenever sql_warning "), $3.str, mm_strdup("; */"));
}
;
@@ -1905,19 +1712,19 @@ action: CONTINUE_P
| SQL_GOTO name
{
$<action>$.code = W_GOTO;
- $<action>$.command = mm_strdup($2);
- $<action>$.str = cat2_str(mm_strdup("goto "), $2);
+ $<action>$.command = mm_strdup(@2);
+ $<action>$.str = cat2_str(mm_strdup("goto "), @2);
}
| SQL_GO TO name
{
$<action>$.code = W_GOTO;
- $<action>$.command = mm_strdup($3);
- $<action>$.str = cat2_str(mm_strdup("goto "), $3);
+ $<action>$.command = mm_strdup(@3);
+ $<action>$.str = cat2_str(mm_strdup("goto "), @3);
}
| DO name '(' c_args ')'
{
$<action>$.code = W_DO;
- $<action>$.command = cat_str(4, $2, mm_strdup("("), $4, mm_strdup(")"));
+ $<action>$.command = cat_str(4, @2, mm_strdup("("), @4, mm_strdup(")"));
$<action>$.str = cat2_str(mm_strdup("do"), mm_strdup($<action>$.command));
}
| DO SQL_BREAK
@@ -1935,13 +1742,13 @@ action: CONTINUE_P
| CALL name '(' c_args ')'
{
$<action>$.code = W_DO;
- $<action>$.command = cat_str(4, $2, mm_strdup("("), $4, mm_strdup(")"));
+ $<action>$.command = cat_str(4, @2, mm_strdup("("), @4, mm_strdup(")"));
$<action>$.str = cat2_str(mm_strdup("call"), mm_strdup($<action>$.command));
}
| CALL name
{
$<action>$.code = W_DO;
- $<action>$.command = cat2_str($2, mm_strdup("()"));
+ $<action>$.command = cat2_str(@2, mm_strdup("()"));
$<action>$.str = cat2_str(mm_strdup("call"), mm_strdup($<action>$.command));
}
;
@@ -1949,63 +1756,63 @@ action: CONTINUE_P
/* some other stuff for ecpg */
/* additional unreserved keywords */
-ECPGKeywords: ECPGKeywords_vanames { $$ = $1; }
- | ECPGKeywords_rest { $$ = $1; }
- ;
-
-ECPGKeywords_vanames: SQL_BREAK { $$ = mm_strdup("break"); }
- | SQL_CARDINALITY { $$ = mm_strdup("cardinality"); }
- | SQL_COUNT { $$ = mm_strdup("count"); }
- | SQL_DATETIME_INTERVAL_CODE { $$ = mm_strdup("datetime_interval_code"); }
- | SQL_DATETIME_INTERVAL_PRECISION { $$ = mm_strdup("datetime_interval_precision"); }
- | SQL_FOUND { $$ = mm_strdup("found"); }
- | SQL_GO { $$ = mm_strdup("go"); }
- | SQL_GOTO { $$ = mm_strdup("goto"); }
- | SQL_IDENTIFIED { $$ = mm_strdup("identified"); }
- | SQL_INDICATOR { $$ = mm_strdup("indicator"); }
- | SQL_KEY_MEMBER { $$ = mm_strdup("key_member"); }
- | SQL_LENGTH { $$ = mm_strdup("length"); }
- | SQL_NULLABLE { $$ = mm_strdup("nullable"); }
- | SQL_OCTET_LENGTH { $$ = mm_strdup("octet_length"); }
- | SQL_RETURNED_LENGTH { $$ = mm_strdup("returned_length"); }
- | SQL_RETURNED_OCTET_LENGTH { $$ = mm_strdup("returned_octet_length"); }
- | SQL_SCALE { $$ = mm_strdup("scale"); }
- | SQL_SECTION { $$ = mm_strdup("section"); }
- | SQL_SQLERROR { $$ = mm_strdup("sqlerror"); }
- | SQL_SQLPRINT { $$ = mm_strdup("sqlprint"); }
- | SQL_SQLWARNING { $$ = mm_strdup("sqlwarning"); }
- | SQL_STOP { $$ = mm_strdup("stop"); }
- ;
-
-ECPGKeywords_rest: SQL_CONNECT { $$ = mm_strdup("connect"); }
- | SQL_DESCRIBE { $$ = mm_strdup("describe"); }
- | SQL_DISCONNECT { $$ = mm_strdup("disconnect"); }
- | SQL_OPEN { $$ = mm_strdup("open"); }
- | SQL_VAR { $$ = mm_strdup("var"); }
- | SQL_WHENEVER { $$ = mm_strdup("whenever"); }
+ECPGKeywords: ECPGKeywords_vanames
+ | ECPGKeywords_rest
+ ;
+
+ECPGKeywords_vanames: SQL_BREAK
+ | SQL_CARDINALITY
+ | SQL_COUNT
+ | SQL_DATETIME_INTERVAL_CODE
+ | SQL_DATETIME_INTERVAL_PRECISION
+ | SQL_FOUND
+ | SQL_GO
+ | SQL_GOTO
+ | SQL_IDENTIFIED
+ | SQL_INDICATOR
+ | SQL_KEY_MEMBER
+ | SQL_LENGTH
+ | SQL_NULLABLE
+ | SQL_OCTET_LENGTH
+ | SQL_RETURNED_LENGTH
+ | SQL_RETURNED_OCTET_LENGTH
+ | SQL_SCALE
+ | SQL_SECTION
+ | SQL_SQLERROR
+ | SQL_SQLPRINT
+ | SQL_SQLWARNING
+ | SQL_STOP
+ ;
+
+ECPGKeywords_rest: SQL_CONNECT
+ | SQL_DESCRIBE
+ | SQL_DISCONNECT
+ | SQL_OPEN
+ | SQL_VAR
+ | SQL_WHENEVER
;
/* additional keywords that can be SQL type names (but not ECPGColLabels) */
-ECPGTypeName: SQL_BOOL { $$ = mm_strdup("bool"); }
- | SQL_LONG { $$ = mm_strdup("long"); }
- | SQL_OUTPUT { $$ = mm_strdup("output"); }
- | SQL_SHORT { $$ = mm_strdup("short"); }
- | SQL_STRUCT { $$ = mm_strdup("struct"); }
- | SQL_SIGNED { $$ = mm_strdup("signed"); }
- | SQL_UNSIGNED { $$ = mm_strdup("unsigned"); }
+ECPGTypeName: SQL_BOOL
+ | SQL_LONG
+ | SQL_OUTPUT
+ | SQL_SHORT
+ | SQL_STRUCT
+ | SQL_SIGNED
+ | SQL_UNSIGNED
;
-symbol: ColLabel { $$ = $1; }
+symbol: ColLabel
;
-ECPGColId: ecpg_ident { $$ = $1; }
- | unreserved_keyword { $$ = $1; }
- | col_name_keyword { $$ = $1; }
- | ECPGunreserved_interval { $$ = $1; }
- | ECPGKeywords { $$ = $1; }
- | ECPGCKeywords { $$ = $1; }
- | CHAR_P { $$ = mm_strdup("char"); }
- | VALUES { $$ = mm_strdup("values"); }
+ECPGColId: ecpg_ident
+ | unreserved_keyword
+ | col_name_keyword
+ | ECPGunreserved_interval
+ | ECPGKeywords
+ | ECPGCKeywords
+ | CHAR_P
+ | VALUES
;
/*
@@ -2018,58 +1825,58 @@ ECPGColId: ecpg_ident { $$ = $1; }
/* Column identifier --- names that can be column, table, etc names.
*/
-ColId: ecpg_ident { $$ = $1; }
- | all_unreserved_keyword { $$ = $1; }
- | col_name_keyword { $$ = $1; }
- | ECPGKeywords { $$ = $1; }
- | ECPGCKeywords { $$ = $1; }
- | CHAR_P { $$ = mm_strdup("char"); }
- | VALUES { $$ = mm_strdup("values"); }
+ColId: ecpg_ident
+ | all_unreserved_keyword
+ | col_name_keyword
+ | ECPGKeywords
+ | ECPGCKeywords
+ | CHAR_P
+ | VALUES
;
/* Type/function identifier --- names that can be type or function names.
*/
-type_function_name: ecpg_ident { $$ = $1; }
- | all_unreserved_keyword { $$ = $1; }
- | type_func_name_keyword { $$ = $1; }
- | ECPGKeywords { $$ = $1; }
- | ECPGCKeywords { $$ = $1; }
- | ECPGTypeName { $$ = $1; }
+type_function_name: ecpg_ident
+ | all_unreserved_keyword
+ | type_func_name_keyword
+ | ECPGKeywords
+ | ECPGCKeywords
+ | ECPGTypeName
;
/* Column label --- allowed labels in "AS" clauses.
* This presently includes *all* Postgres keywords.
*/
-ColLabel: ECPGColLabel { $$ = $1; }
- | ECPGTypeName { $$ = $1; }
- | CHAR_P { $$ = mm_strdup("char"); }
- | CURRENT_P { $$ = mm_strdup("current"); }
- | INPUT_P { $$ = mm_strdup("input"); }
- | INT_P { $$ = mm_strdup("int"); }
- | TO { $$ = mm_strdup("to"); }
- | UNION { $$ = mm_strdup("union"); }
- | VALUES { $$ = mm_strdup("values"); }
- | ECPGCKeywords { $$ = $1; }
- | ECPGunreserved_interval { $$ = $1; }
- ;
-
-ECPGColLabel: ecpg_ident { $$ = $1; }
- | unreserved_keyword { $$ = $1; }
- | col_name_keyword { $$ = $1; }
- | type_func_name_keyword { $$ = $1; }
- | reserved_keyword { $$ = $1; }
- | ECPGKeywords_vanames { $$ = $1; }
- | ECPGKeywords_rest { $$ = $1; }
- | CONNECTION { $$ = mm_strdup("connection"); }
- ;
-
-ECPGCKeywords: S_AUTO { $$ = mm_strdup("auto"); }
- | S_CONST { $$ = mm_strdup("const"); }
- | S_EXTERN { $$ = mm_strdup("extern"); }
- | S_REGISTER { $$ = mm_strdup("register"); }
- | S_STATIC { $$ = mm_strdup("static"); }
- | S_TYPEDEF { $$ = mm_strdup("typedef"); }
- | S_VOLATILE { $$ = mm_strdup("volatile"); }
+ColLabel: ECPGColLabel
+ | ECPGTypeName
+ | CHAR_P
+ | CURRENT_P
+ | INPUT_P
+ | INT_P
+ | TO
+ | UNION
+ | VALUES
+ | ECPGCKeywords
+ | ECPGunreserved_interval
+ ;
+
+ECPGColLabel: ecpg_ident
+ | unreserved_keyword
+ | col_name_keyword
+ | type_func_name_keyword
+ | reserved_keyword
+ | ECPGKeywords_vanames
+ | ECPGKeywords_rest
+ | CONNECTION
+ ;
+
+ECPGCKeywords: S_AUTO
+ | S_CONST
+ | S_EXTERN
+ | S_REGISTER
+ | S_STATIC
+ | S_TYPEDEF
+ | S_VOLATILE
;
/* "Unreserved" keywords --- available for use as any kind of name.
@@ -2086,17 +1893,17 @@ ECPGCKeywords: S_AUTO { $$ = mm_strdup("auto"); }
*
* The mentioned exclusions are done by $replace_line settings in parse.pl.
*/
-all_unreserved_keyword: unreserved_keyword { $$ = $1; }
- | ECPGunreserved_interval { $$ = $1; }
- | CONNECTION { $$ = mm_strdup("connection"); }
+all_unreserved_keyword: unreserved_keyword
+ | ECPGunreserved_interval
+ | CONNECTION
;
-ECPGunreserved_interval: DAY_P { $$ = mm_strdup("day"); }
- | HOUR_P { $$ = mm_strdup("hour"); }
- | MINUTE_P { $$ = mm_strdup("minute"); }
- | MONTH_P { $$ = mm_strdup("month"); }
- | SECOND_P { $$ = mm_strdup("second"); }
- | YEAR_P { $$ = mm_strdup("year"); }
+ECPGunreserved_interval: DAY_P
+ | HOUR_P
+ | MINUTE_P
+ | MONTH_P
+ | SECOND_P
+ | YEAR_P
;
into_list: coutputvariable | into_list ',' coutputvariable
@@ -2106,73 +1913,66 @@ ecpgstart: SQL_START
{
reset_variables();
pacounter = 1;
+ @$ = EMPTY;
}
;
c_args: /* EMPTY */
- {
- $$ = EMPTY;
- }
| c_list
- {
- $$ = $1;
- }
;
coutputvariable: cvariable indicator
{
- add_variable_to_head(&argsresult, find_variable($1), find_variable($2));
+ add_variable_to_head(&argsresult, find_variable(@1), find_variable(@2));
}
| cvariable
{
- add_variable_to_head(&argsresult, find_variable($1), &no_indicator);
+ add_variable_to_head(&argsresult, find_variable(@1), &no_indicator);
}
;
civarind: cvariable indicator
{
- if (find_variable($2)->type->type == ECPGt_array)
+ if (find_variable(@2)->type->type == ECPGt_array)
mmerror(PARSE_ERROR, ET_ERROR, "arrays of indicators are not allowed on input");
- add_variable_to_head(&argsinsert, find_variable($1), find_variable($2));
- $$ = create_questionmarks($1, false);
+ add_variable_to_head(&argsinsert, find_variable(@1), find_variable(@2));
+ @$ = create_questionmarks(@1, false);
}
;
char_civar: char_variable
{
- char *ptr = strstr($1, ".arr");
+ char *ptr = strstr(@1, ".arr");
if (ptr) /* varchar, we need the struct name here, not
* the struct element */
*ptr = '\0';
- add_variable_to_head(&argsinsert, find_variable($1), &no_indicator);
- $$ = $1;
+ add_variable_to_head(&argsinsert, find_variable(@1), &no_indicator);
}
;
civar: cvariable
{
- add_variable_to_head(&argsinsert, find_variable($1), &no_indicator);
- $$ = create_questionmarks($1, false);
+ add_variable_to_head(&argsinsert, find_variable(@1), &no_indicator);
+ @$ = create_questionmarks(@1, false);
}
;
indicator: cvariable
{
- check_indicator((find_variable($1))->type);
- $$ = $1;
+ check_indicator((find_variable(@1))->type);
}
| SQL_INDICATOR cvariable
{
- check_indicator((find_variable($2))->type);
- $$ = $2;
+ check_indicator((find_variable(@2))->type);
+ @$ = @2;
}
| SQL_INDICATOR name
{
- check_indicator((find_variable($2))->type);
- $$ = $2;
+ check_indicator((find_variable(@2))->type);
+ @$ = @2;
}
;
@@ -2182,7 +1982,7 @@ cvariable: CVARIABLE
* As long as multidimensional arrays are not implemented we have to
* check for those here
*/
- char *ptr = $1;
+ char *ptr = @1;
int brace_open = 0,
brace = false;
@@ -2209,57 +2009,44 @@ cvariable: CVARIABLE
break;
}
}
- $$ = $1;
}
;
ecpg_param: PARAM
{
- $$ = make_name();
+ @$ = make_name();
}
;
ecpg_bconst: BCONST
- {
- $$ = $1;
- }
;
ecpg_fconst: FCONST
{
- $$ = make_name();
+ @$ = make_name();
}
;
ecpg_sconst: SCONST
- {
- $$ = $1;
- }
;
ecpg_xconst: XCONST
- {
- $$ = $1;
- }
;
ecpg_ident: IDENT
- {
- $$ = $1;
- }
| CSTRING
{
- $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\""));
+ @$ = make3_str(mm_strdup("\""), @1, mm_strdup("\""));
}
;
quoted_ident_stringvar: name
{
- $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\""));
+ @$ = make3_str(mm_strdup("\""), @1, mm_strdup("\""));
}
| char_variable
{
- $$ = make3_str(mm_strdup("("), $1, mm_strdup(")"));
+ @$ = make3_str(mm_strdup("("), @1, mm_strdup(")"));
}
;
@@ -2268,221 +2055,151 @@ quoted_ident_stringvar: name
*/
c_stuff_item: c_anything
- {
- $$ = $1;
- }
| '(' ')'
{
- $$ = mm_strdup("()");
+ @$ = mm_strdup("()");
}
| '(' c_stuff ')'
- {
- $$ = cat_str(3, mm_strdup("("), $2, mm_strdup(")"));
- }
;
c_stuff: c_stuff_item
- {
- $$ = $1;
- }
| c_stuff c_stuff_item
- {
- $$ = cat2_str($1, $2);
- }
;
c_list: c_term
- {
- $$ = $1;
- }
| c_list ',' c_term
- {
- $$ = cat_str(3, $1, mm_strdup(","), $3);
- }
;
c_term: c_stuff
- {
- $$ = $1;
- }
| '{' c_list '}'
- {
- $$ = cat_str(3, mm_strdup("{"), $2, mm_strdup("}"));
- }
- ;
-
-c_thing: c_anything { $$ = $1; }
- | '(' { $$ = mm_strdup("("); }
- | ')' { $$ = mm_strdup(")"); }
- | ',' { $$ = mm_strdup(","); }
- | ';' { $$ = mm_strdup(";"); }
- ;
-
-c_anything: ecpg_ident { $$ = $1; }
- | Iconst { $$ = $1; }
- | ecpg_fconst { $$ = $1; }
- | ecpg_sconst { $$ = $1; }
- | '*' { $$ = mm_strdup("*"); }
- | '+' { $$ = mm_strdup("+"); }
- | '-' { $$ = mm_strdup("-"); }
- | '/' { $$ = mm_strdup("/"); }
- | '%' { $$ = mm_strdup("%"); }
- | NULL_P { $$ = mm_strdup("NULL"); }
- | S_ADD { $$ = mm_strdup("+="); }
- | S_AND { $$ = mm_strdup("&&"); }
- | S_ANYTHING { $$ = make_name(); }
- | S_AUTO { $$ = mm_strdup("auto"); }
- | S_CONST { $$ = mm_strdup("const"); }
- | S_DEC { $$ = mm_strdup("--"); }
- | S_DIV { $$ = mm_strdup("/="); }
- | S_DOTPOINT { $$ = mm_strdup(".*"); }
- | S_EQUAL { $$ = mm_strdup("=="); }
- | S_EXTERN { $$ = mm_strdup("extern"); }
- | S_INC { $$ = mm_strdup("++"); }
- | S_LSHIFT { $$ = mm_strdup("<<"); }
- | S_MEMBER { $$ = mm_strdup("->"); }
- | S_MEMPOINT { $$ = mm_strdup("->*"); }
- | S_MOD { $$ = mm_strdup("%="); }
- | S_MUL { $$ = mm_strdup("*="); }
- | S_NEQUAL { $$ = mm_strdup("!="); }
- | S_OR { $$ = mm_strdup("||"); }
- | S_REGISTER { $$ = mm_strdup("register"); }
- | S_RSHIFT { $$ = mm_strdup(">>"); }
- | S_STATIC { $$ = mm_strdup("static"); }
- | S_SUB { $$ = mm_strdup("-="); }
- | S_TYPEDEF { $$ = mm_strdup("typedef"); }
- | S_VOLATILE { $$ = mm_strdup("volatile"); }
- | SQL_BOOL { $$ = mm_strdup("bool"); }
- | ENUM_P { $$ = mm_strdup("enum"); }
- | HOUR_P { $$ = mm_strdup("hour"); }
- | INT_P { $$ = mm_strdup("int"); }
- | SQL_LONG { $$ = mm_strdup("long"); }
- | MINUTE_P { $$ = mm_strdup("minute"); }
- | MONTH_P { $$ = mm_strdup("month"); }
- | SECOND_P { $$ = mm_strdup("second"); }
- | SQL_SHORT { $$ = mm_strdup("short"); }
- | SQL_SIGNED { $$ = mm_strdup("signed"); }
- | SQL_STRUCT { $$ = mm_strdup("struct"); }
- | SQL_UNSIGNED { $$ = mm_strdup("unsigned"); }
- | YEAR_P { $$ = mm_strdup("year"); }
- | CHAR_P { $$ = mm_strdup("char"); }
- | FLOAT_P { $$ = mm_strdup("float"); }
- | TO { $$ = mm_strdup("to"); }
- | UNION { $$ = mm_strdup("union"); }
- | VARCHAR { $$ = mm_strdup("varchar"); }
- | '[' { $$ = mm_strdup("["); }
- | ']' { $$ = mm_strdup("]"); }
- | '=' { $$ = mm_strdup("="); }
- | ':' { $$ = mm_strdup(":"); }
+ ;
+
+c_thing: c_anything
+ | '('
+ | ')'
+ | ','
+ | ';'
+ ;
+
+/*
+ * Note: NULL_P is treated specially to force it to be output in upper case,
+ * since it's likely meant as a reference to the standard C macro NULL.
+ */
+c_anything: ecpg_ident
+ | Iconst
+ | ecpg_fconst
+ | ecpg_sconst
+ | '*'
+ | '+'
+ | '-'
+ | '/'
+ | '%'
+ | NULL_P { @$ = mm_strdup("NULL"); }
+ | S_ADD
+ | S_AND
+ | S_ANYTHING
+ | S_AUTO
+ | S_CONST
+ | S_DEC
+ | S_DIV
+ | S_DOTPOINT
+ | S_EQUAL
+ | S_EXTERN
+ | S_INC
+ | S_LSHIFT
+ | S_MEMBER
+ | S_MEMPOINT
+ | S_MOD
+ | S_MUL
+ | S_NEQUAL
+ | S_OR
+ | S_REGISTER
+ | S_RSHIFT
+ | S_STATIC
+ | S_SUB
+ | S_TYPEDEF
+ | S_VOLATILE
+ | SQL_BOOL
+ | ENUM_P
+ | HOUR_P
+ | INT_P
+ | SQL_LONG
+ | MINUTE_P
+ | MONTH_P
+ | SECOND_P
+ | SQL_SHORT
+ | SQL_SIGNED
+ | SQL_STRUCT
+ | SQL_UNSIGNED
+ | YEAR_P
+ | CHAR_P
+ | FLOAT_P
+ | TO
+ | UNION
+ | VARCHAR
+ | '['
+ | ']'
+ | '='
+ | ':'
;
DeallocateStmt: DEALLOCATE prepared_name
{
- check_declared_list($2);
- $$ = $2;
+ check_declared_list(@2);
+ @$ = @2;
}
| DEALLOCATE PREPARE prepared_name
{
- check_declared_list($3);
- $$ = $3;
+ check_declared_list(@3);
+ @$ = @3;
}
| DEALLOCATE ALL
{
- $$ = mm_strdup("all");
+ @$ = mm_strdup("all");
}
| DEALLOCATE PREPARE ALL
{
- $$ = mm_strdup("all");
+ @$ = mm_strdup("all");
}
;
Iresult: Iconst
- {
- $$ = $1;
- }
| '(' Iresult ')'
- {
- $$ = cat_str(3, mm_strdup("("), $2, mm_strdup(")"));
- }
| Iresult '+' Iresult
- {
- $$ = cat_str(3, $1, mm_strdup("+"), $3);
- }
| Iresult '-' Iresult
- {
- $$ = cat_str(3, $1, mm_strdup("-"), $3);
- }
| Iresult '*' Iresult
- {
- $$ = cat_str(3, $1, mm_strdup("*"), $3);
- }
| Iresult '/' Iresult
- {
- $$ = cat_str(3, $1, mm_strdup("/"), $3);
- }
| Iresult '%' Iresult
- {
- $$ = cat_str(3, $1, mm_strdup("%"), $3);
- }
| ecpg_sconst
- {
- $$ = $1;
- }
| ColId
- {
- $$ = $1;
- }
| ColId '(' var_type ')'
{
- if (pg_strcasecmp($1, "sizeof") != 0)
+ if (pg_strcasecmp(@1, "sizeof") != 0)
mmerror(PARSE_ERROR, ET_ERROR, "operator not allowed in variable definition");
else
- $$ = cat_str(4, $1, mm_strdup("("), $3.type_str, mm_strdup(")"));
+ @$ = cat_str(4, @1, mm_strdup("("), $3.type_str, mm_strdup(")"));
}
;
execute_rest: /* EMPTY */
- {
- $$ = EMPTY;
- }
| ecpg_using opt_ecpg_into
- {
- $$ = EMPTY;
- }
| ecpg_into ecpg_using
- {
- $$ = EMPTY;
- }
| ecpg_into
- {
- $$ = EMPTY;
- }
;
ecpg_into: INTO into_list
{
- $$ = EMPTY;
+ /* always suppress this from the constructed string */
+ @$ = EMPTY;
}
| into_descriptor
- {
- $$ = $1;
- }
;
opt_ecpg_into: /* EMPTY */
- {
- $$ = EMPTY;
- }
| ecpg_into
- {
- $$ = $1;
- }
;
ecpg_fetch_into: ecpg_into
- {
- $$ = $1;
- }
| using_descriptor
{
struct variable *var;
@@ -2490,18 +2207,11 @@ ecpg_fetch_into: ecpg_into
var = argsinsert->variable;
remove_variable_from_list(&argsinsert, var);
add_variable_to_head(&argsresult, var, &no_indicator);
- $$ = $1;
}
;
opt_ecpg_fetch_into: /* EMPTY */
- {
- $$ = EMPTY;
- }
| ecpg_fetch_into
- {
- $$ = $1;
- }
;
%%
diff --git a/src/interfaces/ecpg/preproc/ecpg.type b/src/interfaces/ecpg/preproc/ecpg.type
index 4fe80a5a4be..2929f358ff4 100644
--- a/src/interfaces/ecpg/preproc/ecpg.type
+++ b/src/interfaces/ecpg/preproc/ecpg.type
@@ -1,131 +1,4 @@
/* src/interfaces/ecpg/preproc/ecpg.type */
-%type <str> ECPGAllocateDescr
-%type <str> ECPGCKeywords
-%type <str> ECPGColId
-%type <str> ECPGColLabel
-%type <str> ECPGConnect
-%type <str> ECPGCursorStmt
-%type <str> ECPGDeallocateDescr
-%type <str> ECPGDeclaration
-%type <str> ECPGDeclare
-%type <str> ECPGDeclareStmt
-%type <str> ECPGDisconnect
-%type <str> ECPGExecuteImmediateStmt
-%type <str> ECPGFree
-%type <str> ECPGGetDescHeaderItem
-%type <str> ECPGGetDescItem
-%type <str> ECPGGetDescriptorHeader
-%type <str> ECPGKeywords
-%type <str> ECPGKeywords_rest
-%type <str> ECPGKeywords_vanames
-%type <str> ECPGOpen
-%type <str> ECPGSetAutocommit
-%type <str> ECPGSetConnection
-%type <str> ECPGSetDescHeaderItem
-%type <str> ECPGSetDescItem
-%type <str> ECPGSetDescriptorHeader
-%type <str> ECPGTypeName
-%type <str> ECPGTypedef
-%type <str> ECPGVar
-%type <str> ECPGVarDeclaration
-%type <str> ECPGWhenever
-%type <str> ECPGunreserved_interval
-%type <str> UsingConst
-%type <str> UsingValue
-%type <str> all_unreserved_keyword
-%type <str> c_anything
-%type <str> c_args
-%type <str> c_list
-%type <str> c_stuff
-%type <str> c_stuff_item
-%type <str> c_term
-%type <str> c_thing
-%type <str> char_variable
-%type <str> char_civar
-%type <str> civar
-%type <str> civarind
-%type <str> ColId
-%type <str> ColLabel
-%type <str> connect_options
-%type <str> connection_object
-%type <str> connection_target
-%type <str> coutputvariable
-%type <str> cvariable
-%type <str> db_prefix
-%type <str> CreateAsStmt
-%type <str> DeallocateStmt
-%type <str> dis_name
-%type <str> ecpg_bconst
-%type <str> ecpg_fconst
-%type <str> ecpg_ident
-%type <str> ecpg_interval
-%type <str> ecpg_into
-%type <str> ecpg_fetch_into
-%type <str> ecpg_param
-%type <str> ecpg_sconst
-%type <str> ecpg_using
-%type <str> ecpg_xconst
-%type <str> enum_definition
-%type <str> enum_type
-%type <str> execstring
-%type <str> execute_rest
-%type <str> indicator
-%type <str> into_descriptor
-%type <str> into_sqlda
-%type <str> Iresult
-%type <str> on_off
-%type <str> opt_bit_field
-%type <str> opt_connection_name
-%type <str> opt_database_name
-%type <str> opt_ecpg_into
-%type <str> opt_ecpg_fetch_into
-%type <str> opt_ecpg_using
-%type <str> opt_initializer
-%type <str> opt_options
-%type <str> opt_output
-%type <str> opt_pointer
-%type <str> opt_port
-%type <str> opt_reference
-%type <str> opt_scale
-%type <str> opt_server
-%type <str> opt_user
-%type <str> opt_opt_value
-%type <str> ora_user
-%type <str> precision
-%type <str> prepared_name
-%type <str> quoted_ident_stringvar
-%type <str> s_struct_union
-%type <str> server
-%type <str> server_name
-%type <str> single_vt_declaration
-%type <str> storage_clause
-%type <str> storage_declaration
-%type <str> storage_modifier
-%type <str> struct_union_type
-%type <str> struct_union_type_with_symbol
-%type <str> symbol
-%type <str> type_declaration
-%type <str> type_function_name
-%type <str> user_name
-%type <str> using_descriptor
-%type <str> var_declaration
-%type <str> var_type_declarations
-%type <str> variable
-%type <str> variable_declarations
-%type <str> variable_list
-%type <str> vt_declarations
-
-%type <str> Op
-%type <str> IntConstVar
-%type <str> AllConstVar
-%type <str> CSTRING
-%type <str> CPP_LINE
-%type <str> CVARIABLE
-%type <str> BCONST
-%type <str> SCONST
-%type <str> XCONST
-%type <str> IDENT
-
%type <struct_union> s_struct_union_symbol
%type <descriptor> ECPGGetDescriptor
diff --git a/src/interfaces/ecpg/preproc/output.c b/src/interfaces/ecpg/preproc/output.c
index 6c0b8a27b1e..8d2b6e7cb81 100644
--- a/src/interfaces/ecpg/preproc/output.c
+++ b/src/interfaces/ecpg/preproc/output.c
@@ -4,7 +4,7 @@
#include "preproc_extern.h"
-static void output_escaped_str(char *str, bool quoted);
+static void output_escaped_str(const char *str, bool quoted);
void
output_line_number(void)
@@ -16,13 +16,12 @@ output_line_number(void)
}
void
-output_simple_statement(char *stmt, int whenever_mode)
+output_simple_statement(const char *stmt, int whenever_mode)
{
output_escaped_str(stmt, false);
if (whenever_mode)
whenever_action(whenever_mode);
output_line_number();
- free(stmt);
}
@@ -133,7 +132,7 @@ static char *ecpg_statement_type_name[] = {
};
void
-output_statement(char *stmt, int whenever_mode, enum ECPG_statement_type st)
+output_statement(const char *stmt, int whenever_mode, enum ECPG_statement_type st)
{
fprintf(base_yyout, "{ ECPGdo(__LINE__, %d, %d, %s, %d, ", compat, force_indicator, connection ? connection : "NULL", questionmarks);
@@ -163,11 +162,10 @@ output_statement(char *stmt, int whenever_mode, enum ECPG_statement_type st)
reset_variables();
whenever_action(whenever_mode | 2);
- free(stmt);
}
void
-output_prepare_statement(char *name, char *stmt)
+output_prepare_statement(const char *name, const char *stmt)
{
fprintf(base_yyout, "{ ECPGprepare(__LINE__, %s, %d, ", connection ? connection : "NULL", questionmarks);
output_escaped_str(name, true);
@@ -175,11 +173,10 @@ output_prepare_statement(char *name, char *stmt)
output_escaped_str(stmt, true);
fputs(");", base_yyout);
whenever_action(2);
- free(name);
}
void
-output_deallocate_prepare_statement(char *name)
+output_deallocate_prepare_statement(const char *name)
{
const char *con = connection ? connection : "NULL";
@@ -193,11 +190,10 @@ output_deallocate_prepare_statement(char *name)
fprintf(base_yyout, "{ ECPGdeallocate_all(__LINE__, %d, %s);", compat, con);
whenever_action(2);
- free(name);
}
static void
-output_escaped_str(char *str, bool quoted)
+output_escaped_str(const char *str, bool quoted)
{
int i = 0;
int len = strlen(str);
diff --git a/src/interfaces/ecpg/preproc/parse.pl b/src/interfaces/ecpg/preproc/parse.pl
index 3df94a24af0..9ebe4bd7930 100644
--- a/src/interfaces/ecpg/preproc/parse.pl
+++ b/src/interfaces/ecpg/preproc/parse.pl
@@ -44,27 +44,10 @@ my %replace_token = (
'IDENT' => 'ecpg_ident',
'PARAM' => 'ecpg_param',);
-# Substitutions to apply to terminal token names to reconstruct the
-# literal form of the token. (There is also a hard-wired substitution
-# rule that strips trailing '_P'.)
-my %replace_string = (
- 'FORMAT_LA' => 'format',
- 'NOT_LA' => 'not',
- 'NULLS_LA' => 'nulls',
- 'WITH_LA' => 'with',
- 'WITHOUT_LA' => 'without',
- 'TYPECAST' => '::',
- 'DOT_DOT' => '..',
- 'COLON_EQUALS' => ':=',
- 'EQUALS_GREATER' => '=>',
- 'LESS_EQUALS' => '<=',
- 'GREATER_EQUALS' => '>=',
- 'NOT_EQUALS' => '<>',);
-
-# This hash can provide a result type to override '<str>' for nonterminals
+# This hash can provide a result type to override "void" for nonterminals
# that need that, or it can specify 'ignore' to cause us to skip the rule
-# for that nonterminal. (In that case, ecpg.trailer had better provide
-# a substitute rule.)
+# for that nonterminal. (In either case, ecpg.trailer had better provide
+# a substitute rule, since the default won't do.)
my %replace_types = (
'PrepareStmt' => '<prep>',
'ExecuteStmt' => '<exec>',
@@ -175,11 +158,8 @@ my $non_term_id;
# we plan to emit for the current rule.
my $line = '';
-# @fields holds the items to be emitted in the token-concatenation action
-# for the current rule (assuming we emit one). "$N" refers to the N'th
-# input token of the rule; anything else is a string to emit literally.
-# (We assume no such string can need to start with '$'.)
-my @fields;
+# count of tokens included in $line.
+my $line_count = 0;
# Open parser / output file early, to raise errors early.
@@ -244,10 +224,6 @@ sub main
$has_if_command = 1 if /^\s*if/;
}
- # We track %prec per-line, not per-rule, which is not quite right
- # but there are no counterexamples in gram.y at present.
- my $prec = 0;
-
# Make sure any braces are split into separate fields
s/{/ { /g;
s/}/ } /g;
@@ -296,7 +272,7 @@ sub main
}
# If it's "<something>", it's a type in a %token declaration,
- # which we can just drop.
+ # which we should just drop so that the tokens have void type.
if (substr($a, 0, 1) eq '<')
{
next;
@@ -376,7 +352,7 @@ sub main
if ($copymode)
{
# Print the accumulated rule.
- emit_rule(\@fields);
+ emit_rule();
add_to_buffer('rules', ";\n\n");
}
else
@@ -386,8 +362,8 @@ sub main
}
# Reset for the next rule.
- @fields = ();
$line = '';
+ $line_count = 0;
$in_rule = 0;
$alt_count = 0;
$has_feature_not_supported = 0;
@@ -401,11 +377,10 @@ sub main
{
# Print the accumulated alternative.
# Increment $alt_count for each non-ignored alternative.
- $alt_count += emit_rule(\@fields);
+ $alt_count += emit_rule();
}
# Reset for the next alternative.
- @fields = ();
# Start the next line with '|' if we've printed at least one
# alternative.
if ($alt_count > 1)
@@ -416,6 +391,7 @@ sub main
{
$line = '';
}
+ $line_count = 0;
$has_feature_not_supported = 0;
$has_if_command = 0;
next;
@@ -444,13 +420,9 @@ sub main
$fieldIndexer++;
}
- # Check for %replace_types override of nonterminal's type
- if (not defined $replace_types{$non_term_id})
- {
- # By default, the type is <str>
- $replace_types{$non_term_id} = '<str>';
- }
- elsif ($replace_types{$non_term_id} eq 'ignore')
+ # Check for %replace_types entry indicating to ignore it.
+ if (defined $replace_types{$non_term_id}
+ && $replace_types{$non_term_id} eq 'ignore')
{
# We'll ignore this nonterminal and rule altogether.
$copymode = 0;
@@ -470,22 +442,26 @@ sub main
$stmt_mode = 0;
}
- # Emit appropriate %type declaration for this nonterminal.
- my $tstr =
- '%type '
- . $replace_types{$non_term_id} . ' '
- . $non_term_id;
- add_to_buffer('types', $tstr);
+ # Emit appropriate %type declaration for this nonterminal,
+ # if it has a type; otherwise omit that.
+ if (defined $replace_types{$non_term_id})
+ {
+ my $tstr =
+ '%type '
+ . $replace_types{$non_term_id} . ' '
+ . $non_term_id;
+ add_to_buffer('types', $tstr);
+ }
# Emit the target part of the rule.
# Note: the leading space is just to match
# the rather weird pre-v18 output logic.
- $tstr = ' ' . $non_term_id . ':';
+ my $tstr = ' ' . $non_term_id . ':';
add_to_buffer('rules', $tstr);
- # Prepare for reading the fields (tokens) of the rule.
+ # Prepare for reading the tokens of the rule.
$line = '';
- @fields = ();
+ $line_count = 0;
die "unterminated rule at grammar line $.\n"
if $in_rule;
$in_rule = 1;
@@ -496,48 +472,7 @@ sub main
{
# Not a nonterminal declaration, so just add it to $line.
$line = $line . ' ' . $arr[$fieldIndexer];
- }
-
- # %prec and whatever follows it should get added to $line,
- # but not to @fields.
- if ($arr[$fieldIndexer] eq '%prec')
- {
- $prec = 1;
- next;
- }
-
- # Emit transformed version of token to @fields if appropriate.
- if ( $copymode
- && !$prec
- && !$comment
- && $in_rule)
- {
- my $S = $arr[$fieldIndexer];
-
- # If it's a known terminal token (other than Op) or a literal
- # character, we need to emit the equivalent string, which'll
- # later get wrapped into a C string literal, perhaps after
- # merging with adjacent strings.
- if ($S ne 'Op'
- && (defined $tokens{$S}
- || $S =~ /^'.+'$/))
- {
- # Apply replace_string substitution if any.
- $S = $replace_string{$S} if (exists $replace_string{$S});
- # Automatically strip _P if present.
- $S =~ s/_P$//;
- # And get rid of quotes if it's a literal character.
- $S =~ tr/'//d;
- # Finally, downcase and push into @fields.
- push(@fields, lc($S));
- }
- else
- {
- # Otherwise, push a $N reference to this input token.
- # (We assume this cannot be confused with anything the
- # above code would produce.)
- push(@fields, '$' . (scalar(@fields) + 1));
- }
+ $line_count++;
}
}
}
@@ -568,13 +503,13 @@ sub include_file
# by an ecpg.addons entry.
sub emit_rule_action
{
- my ($tag, $fields) = @_;
+ my ($tag) = @_;
# See if we have an addons entry; if not, just emit default action
my $rec = $addons{$tag};
if (!$rec)
{
- emit_default_action($fields, 0);
+ emit_default_action(0);
return;
}
@@ -585,7 +520,7 @@ sub emit_rule_action
if ($rectype eq 'rule')
{
# Emit default action and then the code block.
- emit_default_action($fields, 0);
+ emit_default_action(0);
}
elsif ($rectype eq 'addon')
{
@@ -600,7 +535,7 @@ sub emit_rule_action
if ($rectype eq 'addon')
{
- emit_default_action($fields, 1);
+ emit_default_action(1);
}
return;
}
@@ -626,12 +561,11 @@ sub dump_buffer
}
# Emit the default action (usually token concatenation) for the current rule.
-# Pass: fields array, brace_printed boolean
+# Pass: brace_printed boolean
# brace_printed should be true if caller already printed action's open brace.
sub emit_default_action
{
- my ($flds, $brace_printed) = @_;
- my $len = scalar(@$flds);
+ my ($brace_printed) = @_;
if ($stmt_mode == 0)
{
@@ -651,91 +585,21 @@ sub emit_default_action
);
}
- if ($len == 0)
- {
- # Empty rule
- if (!$brace_printed)
- {
- add_to_buffer('rules', ' { ');
- $brace_printed = 1;
- }
- add_to_buffer('rules', ' $$=EMPTY; }');
- }
- else
- {
- # Go through each field and aggregate consecutive literal tokens
- # into a single 'mm_strdup' call.
- my @flds_new;
- my $str;
- for (my $z = 0; $z < $len; $z++)
- {
- if (substr($flds->[$z], 0, 1) eq '$')
- {
- push(@flds_new, $flds->[$z]);
- next;
- }
-
- $str = $flds->[$z];
-
- while (1)
- {
- if ($z >= $len - 1
- || substr($flds->[ $z + 1 ], 0, 1) eq '$')
- {
- # Can't combine any more literals; push to @flds_new.
- # This code would need work if any literals contain
- # backslash or double quote, but right now that never
- # happens.
- push(@flds_new, "mm_strdup(\"$str\")");
- last;
- }
- $z++;
- $str = $str . ' ' . $flds->[$z];
- }
- }
-
- # So - how many fields did we end up with ?
- $len = scalar(@flds_new);
- if ($len == 1)
- {
- # Single field can be handled by straight assignment
- if (!$brace_printed)
- {
- add_to_buffer('rules', ' { ');
- $brace_printed = 1;
- }
- $str = ' $$ = ' . $flds_new[0] . ';';
- add_to_buffer('rules', $str);
- }
- else
- {
- # Need to concatenate the results to form our final string
- if (!$brace_printed)
- {
- add_to_buffer('rules', ' { ');
- $brace_printed = 1;
- }
- $str =
- ' $$ = cat_str(' . $len . ',' . join(',', @flds_new) . ');';
- add_to_buffer('rules', $str);
- }
- add_to_buffer('rules', '}') if ($brace_printed);
- }
+ add_to_buffer('rules', '}') if ($brace_printed);
}
else
{
# We're in the "stmt:" rule, where we need to output special actions.
# This code assumes that no ecpg.addons entry applies.
- if ($len)
+ if ($line_count)
{
# Any regular kind of statement calls output_statement
add_to_buffer('rules',
- ' { output_statement($1, 0, ECPGst_normal); }');
+ ' { output_statement(@1, 0, ECPGst_normal); }');
}
else
{
# The empty production for stmt: do nothing
- add_to_buffer('rules', ' { $$ = NULL; }');
}
}
return;
@@ -746,8 +610,6 @@ sub emit_default_action
# entry in %replace_line, then do nothing and return 0.
sub emit_rule
{
- my ($fields) = @_;
-
# compute tag to be used as lookup key in %replace_line and %addons
my $tag = $non_term_id . $line;
$tag =~ tr/ |//d;
@@ -761,7 +623,8 @@ sub emit_rule
return 0;
}
- # non-ignore entries replace the line, but we'd better keep any '|'
+ # non-ignore entries replace the line, but we'd better keep any '|';
+ # we don't bother to update $line_count here.
if (index($line, '|') != -1)
{
$line = '| ' . $rep;
@@ -778,7 +641,7 @@ sub emit_rule
# Emit $line, then print the appropriate action.
add_to_buffer('rules', $line);
- emit_rule_action($tag, $fields);
+ emit_rule_action($tag);
return 1;
}
diff --git a/src/interfaces/ecpg/preproc/parser.c b/src/interfaces/ecpg/preproc/parser.c
index 9daeee33034..ca0dead26d0 100644
--- a/src/interfaces/ecpg/preproc/parser.c
+++ b/src/interfaces/ecpg/preproc/parser.c
@@ -31,6 +31,7 @@ static YYSTYPE lookahead_yylval; /* yylval for lookahead token */
static YYLTYPE lookahead_yylloc; /* yylloc for lookahead token */
static char *lookahead_yytext; /* start current token */
+static int base_yylex_location(void);
static bool check_uescapechar(unsigned char escape);
static bool ecpg_isspace(char ch);
@@ -71,7 +72,7 @@ filtered_base_yylex(void)
have_lookahead = false;
}
else
- cur_token = base_yylex();
+ cur_token = base_yylex_location();
/*
* If this token isn't one that requires lookahead, just return it.
@@ -96,7 +97,7 @@ filtered_base_yylex(void)
cur_yytext = base_yytext;
/* Get next token, saving outputs into lookahead variables */
- next_token = base_yylex();
+ next_token = base_yylex_location();
lookahead_token = next_token;
lookahead_yylval = base_yylval;
@@ -184,7 +185,7 @@ filtered_base_yylex(void)
cur_yytext = base_yytext;
/* Get third token */
- next_token = base_yylex();
+ next_token = base_yylex_location();
if (next_token != SCONST)
mmerror(PARSE_ERROR, ET_ERROR, "UESCAPE must be followed by a simple string literal");
@@ -203,6 +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);
/* Clear have_lookahead, thereby consuming all three tokens */
have_lookahead = false;
@@ -219,6 +221,56 @@ filtered_base_yylex(void)
}
/*
+ * Call base_yylex() and fill in base_yylloc.
+ *
+ * pgc.l does not worry about setting yylloc, and given what we want for
+ * that, trying to set it there would be pretty inconvenient. What we
+ * want is: if the returned token has type <str>, then duplicate its
+ * string value as yylloc; otherwise, make a downcased copy of yytext.
+ * The downcasing is ASCII-only because all that we care about there
+ * is producing uniformly-cased output of keywords. (That's mostly
+ * cosmetic, but there are places in ecpglib that expect to receive
+ * downcased keywords, plus it keeps us regression-test-compatible
+ * with the pre-v18 implementation of ecpg.)
+ */
+static int
+base_yylex_location(void)
+{
+ int token = base_yylex();
+
+ switch (token)
+ {
+ /* List a token here if pgc.l assigns to base_yylval.str for it */
+ case Op:
+ case CSTRING:
+ case CPP_LINE:
+ case CVARIABLE:
+ case BCONST:
+ case SCONST:
+ case USCONST:
+ case XCONST:
+ case FCONST:
+ case IDENT:
+ case UIDENT:
+ case IP:
+ /* Duplicate the <str> value */
+ base_yylloc = mm_strdup(base_yylval.str);
+ break;
+ default:
+ /* Else just use the input, i.e., yytext */
+ base_yylloc = mm_strdup(base_yytext);
+ /* Apply an ASCII-only downcasing */
+ for (unsigned char *ptr = (unsigned char *) base_yylloc; *ptr; ptr++)
+ {
+ if (*ptr >= 'A' && *ptr <= 'Z')
+ *ptr += 'a' - 'A';
+ }
+ break;
+ }
+ return token;
+}
+
+/*
* check_uescapechar() and ecpg_isspace() should match their equivalents
* in pgc.l.
*/
diff --git a/src/interfaces/ecpg/preproc/preproc_extern.h b/src/interfaces/ecpg/preproc/preproc_extern.h
index c5fd07fbd8b..da939674620 100644
--- a/src/interfaces/ecpg/preproc/preproc_extern.h
+++ b/src/interfaces/ecpg/preproc/preproc_extern.h
@@ -15,6 +15,13 @@
#define STRUCT_DEPTH 128
#define EMPTY mm_strdup("")
+/*
+ * "Location tracking" support --- see ecpg.header for more comments.
+ */
+typedef char *YYLTYPE;
+
+#define YYLTYPE_IS_DECLARED 1
+
/* variables */
extern bool autocommit,
@@ -65,10 +72,10 @@ extern const uint16 SQLScanKeywordTokens[];
extern const char *get_dtype(enum ECPGdtype);
extern void lex_init(void);
extern void output_line_number(void);
-extern void output_statement(char *stmt, int whenever_mode, enum ECPG_statement_type st);
-extern void output_prepare_statement(char *name, char *stmt);
-extern void output_deallocate_prepare_statement(char *name);
-extern void output_simple_statement(char *stmt, int whenever_mode);
+extern void output_statement(const char *stmt, int whenever_mode, enum ECPG_statement_type st);
+extern void output_prepare_statement(const char *name, const char *stmt);
+extern void output_deallocate_prepare_statement(const char *name);
+extern void output_simple_statement(const char *stmt, int whenever_mode);
extern char *hashline_number(void);
extern int base_yyparse(void);
extern int base_yylex(void);