aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);