mirror of
https://github.com/postgres/postgres.git
synced 2025-05-08 07:21:33 +03:00
ecpg: invent a saner syntax for ecpg.addons entries.
Put the rule type at the start not the end, and put spaces between the constitutent token names instead of smashing them into an illegible mess. This has no functional impact but I think it makes the rules a great deal more readable. Discussion: https://postgr.es/m/1185216.1724001216@sss.pgh.pa.us
This commit is contained in:
parent
143e3a1ab8
commit
dbedc461b4
@ -40,19 +40,19 @@ continue to use the normal Bison notations.)
|
|||||||
|
|
||||||
|
|
||||||
ecpg.addons contains entries that begin with a line like
|
ecpg.addons contains entries that begin with a line like
|
||||||
ECPG: concattokens ruletype
|
ECPG: ruletype tokenlist
|
||||||
and typically have one or more following lines that are the code
|
and typically have one or more following lines that are the code
|
||||||
for a grammar action. Any line not starting with "ECPG:" is taken
|
for a grammar action. Any line not starting with "ECPG:" is taken
|
||||||
to be part of the code block for the preceding "ECPG:" line.
|
to be part of the code block for the preceding "ECPG:" line.
|
||||||
|
|
||||||
"concattokens" identifies which gram.y production this entry affects.
|
"tokenlist" identifies which gram.y production this entry affects.
|
||||||
It is simply the target nonterminal and the tokens from the gram.y rule
|
It is simply a list of the target nonterminal and the input tokens
|
||||||
concatenated together. For example, to modify the action for a gram.y
|
from the gram.y rule. For example, to modify the action for a
|
||||||
rule like this:
|
gram.y rule like this:
|
||||||
target: tokenA tokenB tokenC {...}
|
target: tokenA tokenB tokenC {...}
|
||||||
"concattokens" would be "targettokenAtokenBtokenC". If we want to
|
"tokenlist" would be "target tokenA tokenB tokenC". If we want to
|
||||||
modify a non-first alternative for a nonterminal, we still write the
|
modify a non-first alternative for a nonterminal, we still write the
|
||||||
nonterminal. For example, "concattokens" should be "targettokenDtokenE"
|
nonterminal. For example, "tokenlist" should be "target tokenD tokenE"
|
||||||
to affect the second alternative in:
|
to affect the second alternative in:
|
||||||
target: tokenA tokenB tokenC {...}
|
target: tokenA tokenB tokenC {...}
|
||||||
| tokenD tokenE {...}
|
| tokenD tokenE {...}
|
||||||
@ -72,7 +72,7 @@ c) "rule" - the automatic action is emitted, but then the entry's
|
|||||||
code block is added verbatim afterwards. This typically is
|
code block is added verbatim afterwards. This typically is
|
||||||
used to add new alternatives to a nonterminal of the core grammar.
|
used to add new alternatives to a nonterminal of the core grammar.
|
||||||
For example, given the entry:
|
For example, given the entry:
|
||||||
ECPG: targettokenAtokenBtokenC rule
|
ECPG: rule target tokenA tokenB tokenC
|
||||||
| tokenD tokenE { custom_action; }
|
| tokenD tokenE { custom_action; }
|
||||||
what will be emitted is
|
what will be emitted is
|
||||||
target: tokenA tokenB tokenC { automatic_action; }
|
target: tokenA tokenB tokenC { automatic_action; }
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* src/interfaces/ecpg/preproc/ecpg.addons */
|
/* src/interfaces/ecpg/preproc/ecpg.addons */
|
||||||
ECPG: stmtClosePortalStmt block
|
ECPG: block stmt ClosePortalStmt
|
||||||
{
|
{
|
||||||
if (INFORMIX_MODE)
|
if (INFORMIX_MODE)
|
||||||
{
|
{
|
||||||
@ -16,23 +16,23 @@ ECPG: stmtClosePortalStmt block
|
|||||||
|
|
||||||
output_statement(@1, 0, ECPGst_normal);
|
output_statement(@1, 0, ECPGst_normal);
|
||||||
}
|
}
|
||||||
ECPG: stmtDeallocateStmt block
|
ECPG: block stmt DeallocateStmt
|
||||||
{
|
{
|
||||||
output_deallocate_prepare_statement(@1);
|
output_deallocate_prepare_statement(@1);
|
||||||
}
|
}
|
||||||
ECPG: stmtDeclareCursorStmt block
|
ECPG: block stmt DeclareCursorStmt
|
||||||
{
|
{
|
||||||
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: block stmt DiscardStmt
|
||||||
ECPG: stmtFetchStmt block
|
ECPG: block stmt FetchStmt
|
||||||
{ output_statement(@1, 1, ECPGst_normal); }
|
{ output_statement(@1, 1, ECPGst_normal); }
|
||||||
ECPG: stmtDeleteStmt block
|
ECPG: block stmt DeleteStmt
|
||||||
ECPG: stmtInsertStmt block
|
ECPG: block stmt InsertStmt
|
||||||
ECPG: stmtSelectStmt block
|
ECPG: block stmt SelectStmt
|
||||||
ECPG: stmtUpdateStmt block
|
ECPG: block stmt UpdateStmt
|
||||||
{ output_statement(@1, 1, ECPGst_prepnormal); }
|
{ output_statement(@1, 1, ECPGst_prepnormal); }
|
||||||
ECPG: stmtExecuteStmt block
|
ECPG: block stmt ExecuteStmt
|
||||||
{
|
{
|
||||||
check_declared_list($1.name);
|
check_declared_list($1.name);
|
||||||
if ($1.type == NULL || strlen($1.type) == 0)
|
if ($1.type == NULL || strlen($1.type) == 0)
|
||||||
@ -57,7 +57,7 @@ ECPG: stmtExecuteStmt block
|
|||||||
output_statement(cat_str(3, "execute", "$0", $1.type), 0, ECPGst_exec_with_exprlist);
|
output_statement(cat_str(3, "execute", "$0", $1.type), 0, ECPGst_exec_with_exprlist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ECPG: stmtPrepareStmt block
|
ECPG: block stmt PrepareStmt
|
||||||
{
|
{
|
||||||
check_declared_list($1.name);
|
check_declared_list($1.name);
|
||||||
if ($1.type == NULL)
|
if ($1.type == NULL)
|
||||||
@ -87,17 +87,17 @@ ECPG: stmtPrepareStmt block
|
|||||||
output_statement(cat_str(5, "prepare", "$0", $1.type, "as", $1.stmt), 0, ECPGst_prepare);
|
output_statement(cat_str(5, "prepare", "$0", $1.type, "as", $1.stmt), 0, ECPGst_prepare);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ECPG: stmtTransactionStmt block
|
ECPG: block stmt TransactionStmt
|
||||||
{
|
{
|
||||||
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);
|
whenever_action(2);
|
||||||
}
|
}
|
||||||
ECPG: toplevel_stmtTransactionStmtLegacy block
|
ECPG: block toplevel_stmt TransactionStmtLegacy
|
||||||
{
|
{
|
||||||
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);
|
whenever_action(2);
|
||||||
}
|
}
|
||||||
ECPG: stmtViewStmt rule
|
ECPG: rule stmt ViewStmt
|
||||||
| ECPGAllocateDescr
|
| ECPGAllocateDescr
|
||||||
{
|
{
|
||||||
fprintf(base_yyout, "ECPGallocate_desc(__LINE__, %s);", @1);
|
fprintf(base_yyout, "ECPGallocate_desc(__LINE__, %s);", @1);
|
||||||
@ -231,45 +231,45 @@ ECPG: stmtViewStmt rule
|
|||||||
|
|
||||||
output_simple_statement(@1, 0);
|
output_simple_statement(@1, 0);
|
||||||
}
|
}
|
||||||
ECPG: where_or_current_clauseWHERECURRENT_POFcursor_name block
|
ECPG: block where_or_current_clause WHERE CURRENT_P OF cursor_name
|
||||||
{
|
{
|
||||||
const char *cursor_marker = @4[0] == ':' ? "$0" : @4;
|
const char *cursor_marker = @4[0] == ':' ? "$0" : @4;
|
||||||
|
|
||||||
@$ = cat_str(2, "where current of", cursor_marker);
|
@$ = cat_str(2, "where current of", cursor_marker);
|
||||||
}
|
}
|
||||||
ECPG: CopyStmtCOPYopt_binaryqualified_nameopt_column_listcopy_fromopt_programcopy_file_namecopy_delimiteropt_withcopy_optionswhere_clause addon
|
ECPG: addon CopyStmt COPY opt_binary qualified_name opt_column_list copy_from opt_program copy_file_name copy_delimiter opt_with copy_options where_clause
|
||||||
if (strcmp(@6, "from") == 0 &&
|
if (strcmp(@6, "from") == 0 &&
|
||||||
(strcmp(@7, "stdin") == 0 || strcmp(@7, "stdout") == 0))
|
(strcmp(@7, "stdin") == 0 || strcmp(@7, "stdout") == 0))
|
||||||
mmerror(PARSE_ERROR, ET_WARNING, "COPY FROM STDIN is not implemented");
|
mmerror(PARSE_ERROR, ET_WARNING, "COPY FROM STDIN is not implemented");
|
||||||
ECPG: var_valueNumericOnly addon
|
ECPG: addon var_value NumericOnly
|
||||||
if (@1[0] == '$')
|
if (@1[0] == '$')
|
||||||
@$ = "$0";
|
@$ = "$0";
|
||||||
ECPG: fetch_argscursor_name addon
|
ECPG: addon fetch_args cursor_name
|
||||||
struct cursor *ptr = add_additional_variables(@1, false);
|
struct cursor *ptr = add_additional_variables(@1, false);
|
||||||
|
|
||||||
if (ptr->connection)
|
if (ptr->connection)
|
||||||
connection = mm_strdup(ptr->connection);
|
connection = mm_strdup(ptr->connection);
|
||||||
if (@1[0] == ':')
|
if (@1[0] == ':')
|
||||||
@$ = "$0";
|
@$ = "$0";
|
||||||
ECPG: fetch_argsfrom_incursor_name addon
|
ECPG: addon fetch_args from_in cursor_name
|
||||||
struct cursor *ptr = add_additional_variables(@2, false);
|
struct cursor *ptr = add_additional_variables(@2, false);
|
||||||
|
|
||||||
if (ptr->connection)
|
if (ptr->connection)
|
||||||
connection = mm_strdup(ptr->connection);
|
connection = mm_strdup(ptr->connection);
|
||||||
if (@2[0] == ':')
|
if (@2[0] == ':')
|
||||||
@$ = cat2_str(@1, "$0");
|
@$ = cat2_str(@1, "$0");
|
||||||
ECPG: fetch_argsNEXTopt_from_incursor_name addon
|
ECPG: addon fetch_args NEXT opt_from_in cursor_name
|
||||||
ECPG: fetch_argsPRIORopt_from_incursor_name addon
|
ECPG: addon fetch_args PRIOR opt_from_in cursor_name
|
||||||
ECPG: fetch_argsFIRST_Popt_from_incursor_name addon
|
ECPG: addon fetch_args FIRST_P opt_from_in cursor_name
|
||||||
ECPG: fetch_argsLAST_Popt_from_incursor_name addon
|
ECPG: addon fetch_args LAST_P opt_from_in cursor_name
|
||||||
ECPG: fetch_argsALLopt_from_incursor_name addon
|
ECPG: addon fetch_args ALL opt_from_in cursor_name
|
||||||
struct cursor *ptr = add_additional_variables(@3, false);
|
struct cursor *ptr = add_additional_variables(@3, false);
|
||||||
|
|
||||||
if (ptr->connection)
|
if (ptr->connection)
|
||||||
connection = mm_strdup(ptr->connection);
|
connection = mm_strdup(ptr->connection);
|
||||||
if (@3[0] == ':')
|
if (@3[0] == ':')
|
||||||
@$ = cat_str(3, @1, @2, "$0");
|
@$ = cat_str(3, @1, @2, "$0");
|
||||||
ECPG: fetch_argsSignedIconstopt_from_incursor_name addon
|
ECPG: addon fetch_args SignedIconst opt_from_in cursor_name
|
||||||
struct cursor *ptr = add_additional_variables(@3, false);
|
struct cursor *ptr = add_additional_variables(@3, false);
|
||||||
bool replace = false;
|
bool replace = false;
|
||||||
|
|
||||||
@ -287,18 +287,18 @@ ECPG: fetch_argsSignedIconstopt_from_incursor_name addon
|
|||||||
}
|
}
|
||||||
if (replace)
|
if (replace)
|
||||||
@$ = cat_str(3, @1, @2, @3);
|
@$ = cat_str(3, @1, @2, @3);
|
||||||
ECPG: fetch_argsFORWARDALLopt_from_incursor_name addon
|
ECPG: addon fetch_args FORWARD ALL opt_from_in cursor_name
|
||||||
ECPG: fetch_argsBACKWARDALLopt_from_incursor_name addon
|
ECPG: addon fetch_args BACKWARD ALL opt_from_in cursor_name
|
||||||
struct cursor *ptr = add_additional_variables(@4, false);
|
struct cursor *ptr = add_additional_variables(@4, false);
|
||||||
|
|
||||||
if (ptr->connection)
|
if (ptr->connection)
|
||||||
connection = mm_strdup(ptr->connection);
|
connection = mm_strdup(ptr->connection);
|
||||||
if (@4[0] == ':')
|
if (@4[0] == ':')
|
||||||
@$ = cat_str(4, @1, @2, @3, "$0");
|
@$ = cat_str(4, @1, @2, @3, "$0");
|
||||||
ECPG: fetch_argsABSOLUTE_PSignedIconstopt_from_incursor_name addon
|
ECPG: addon fetch_args ABSOLUTE_P SignedIconst opt_from_in cursor_name
|
||||||
ECPG: fetch_argsRELATIVE_PSignedIconstopt_from_incursor_name addon
|
ECPG: addon fetch_args RELATIVE_P SignedIconst opt_from_in cursor_name
|
||||||
ECPG: fetch_argsFORWARDSignedIconstopt_from_incursor_name addon
|
ECPG: addon fetch_args FORWARD SignedIconst opt_from_in cursor_name
|
||||||
ECPG: fetch_argsBACKWARDSignedIconstopt_from_incursor_name addon
|
ECPG: addon fetch_args BACKWARD SignedIconst opt_from_in cursor_name
|
||||||
struct cursor *ptr = add_additional_variables(@4, false);
|
struct cursor *ptr = add_additional_variables(@4, false);
|
||||||
bool replace = false;
|
bool replace = false;
|
||||||
|
|
||||||
@ -316,7 +316,7 @@ ECPG: fetch_argsBACKWARDSignedIconstopt_from_incursor_name addon
|
|||||||
}
|
}
|
||||||
if (replace)
|
if (replace)
|
||||||
@$ = cat_str(4, @1, @2, @3, @4);
|
@$ = cat_str(4, @1, @2, @3, @4);
|
||||||
ECPG: cursor_namename block
|
ECPG: block cursor_name name
|
||||||
| char_civar
|
| char_civar
|
||||||
{
|
{
|
||||||
char *curname = loc_alloc(strlen(@1) + 2);
|
char *curname = loc_alloc(strlen(@1) + 2);
|
||||||
@ -324,11 +324,11 @@ ECPG: cursor_namename block
|
|||||||
sprintf(curname, ":%s", @1);
|
sprintf(curname, ":%s", @1);
|
||||||
@$ = curname;
|
@$ = curname;
|
||||||
}
|
}
|
||||||
ECPG: ExplainableStmtExecuteStmt block
|
ECPG: block ExplainableStmt ExecuteStmt
|
||||||
{
|
{
|
||||||
@$ = $1.name;
|
@$ = $1.name;
|
||||||
}
|
}
|
||||||
ECPG: PrepareStmtPREPAREprepared_nameprep_type_clauseASPreparableStmt block
|
ECPG: block PrepareStmt PREPARE prepared_name prep_type_clause AS PreparableStmt
|
||||||
{
|
{
|
||||||
$$.name = @2;
|
$$.name = @2;
|
||||||
$$.type = @3;
|
$$.type = @3;
|
||||||
@ -340,20 +340,20 @@ ECPG: PrepareStmtPREPAREprepared_nameprep_type_clauseASPreparableStmt block
|
|||||||
$$.type = NULL;
|
$$.type = NULL;
|
||||||
$$.stmt = @4;
|
$$.stmt = @4;
|
||||||
}
|
}
|
||||||
ECPG: ExecuteStmtEXECUTEprepared_nameexecute_param_clauseexecute_rest block
|
ECPG: block ExecuteStmt EXECUTE prepared_name execute_param_clause execute_rest
|
||||||
{
|
{
|
||||||
$$.name = @2;
|
$$.name = @2;
|
||||||
$$.type = @3;
|
$$.type = @3;
|
||||||
}
|
}
|
||||||
ECPG: ExecuteStmtCREATEOptTempTABLEcreate_as_targetASEXECUTEprepared_nameexecute_param_clauseopt_with_dataexecute_rest block
|
ECPG: block ExecuteStmt CREATE OptTemp TABLE create_as_target AS EXECUTE prepared_name execute_param_clause opt_with_data execute_rest
|
||||||
{
|
{
|
||||||
$$.name = @$;
|
$$.name = @$;
|
||||||
}
|
}
|
||||||
ECPG: ExecuteStmtCREATEOptTempTABLEIF_PNOTEXISTScreate_as_targetASEXECUTEprepared_nameexecute_param_clauseopt_with_dataexecute_rest block
|
ECPG: block ExecuteStmt CREATE OptTemp TABLE IF_P NOT EXISTS create_as_target AS EXECUTE prepared_name execute_param_clause opt_with_data execute_rest
|
||||||
{
|
{
|
||||||
$$.name = @$;
|
$$.name = @$;
|
||||||
}
|
}
|
||||||
ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectStmt block
|
ECPG: block DeclareCursorStmt DECLARE cursor_name cursor_options CURSOR opt_hold FOR SelectStmt
|
||||||
{
|
{
|
||||||
struct cursor *ptr,
|
struct cursor *ptr,
|
||||||
*this;
|
*this;
|
||||||
@ -403,7 +403,7 @@ ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectSt
|
|||||||
|
|
||||||
@$ = cat2_str(adjust_outofscope_cursor_vars(this), comment);
|
@$ = cat2_str(adjust_outofscope_cursor_vars(this), comment);
|
||||||
}
|
}
|
||||||
ECPG: ClosePortalStmtCLOSEcursor_name block
|
ECPG: block ClosePortalStmt CLOSE cursor_name
|
||||||
{
|
{
|
||||||
const char *cursor_marker = @2[0] == ':' ? "$0" : @2;
|
const char *cursor_marker = @2[0] == ':' ? "$0" : @2;
|
||||||
struct cursor *ptr = NULL;
|
struct cursor *ptr = NULL;
|
||||||
@ -419,14 +419,14 @@ ECPG: ClosePortalStmtCLOSEcursor_name block
|
|||||||
}
|
}
|
||||||
@$ = cat2_str("close", cursor_marker);
|
@$ = cat2_str("close", cursor_marker);
|
||||||
}
|
}
|
||||||
ECPG: opt_hold block
|
ECPG: block opt_hold
|
||||||
{
|
{
|
||||||
if (compat == ECPG_COMPAT_INFORMIX_SE && autocommit)
|
if (compat == ECPG_COMPAT_INFORMIX_SE && autocommit)
|
||||||
@$ = "with hold";
|
@$ = "with hold";
|
||||||
else
|
else
|
||||||
@$ = "";
|
@$ = "";
|
||||||
}
|
}
|
||||||
ECPG: into_clauseINTOOptTempTableName block
|
ECPG: block into_clause INTO OptTempTableName
|
||||||
{
|
{
|
||||||
FoundInto = 1;
|
FoundInto = 1;
|
||||||
@$ = cat2_str("into", @2);
|
@$ = cat2_str("into", @2);
|
||||||
@ -435,15 +435,15 @@ ECPG: into_clauseINTOOptTempTableName block
|
|||||||
{
|
{
|
||||||
@$ = "";
|
@$ = "";
|
||||||
}
|
}
|
||||||
ECPG: TypenameSimpleTypenameopt_array_bounds block
|
ECPG: block Typename SimpleTypename opt_array_bounds
|
||||||
{
|
{
|
||||||
@$ = cat2_str(@1, $2.str);
|
@$ = cat2_str(@1, $2.str);
|
||||||
}
|
}
|
||||||
ECPG: TypenameSETOFSimpleTypenameopt_array_bounds block
|
ECPG: block Typename SETOF SimpleTypename opt_array_bounds
|
||||||
{
|
{
|
||||||
@$ = cat_str(3, "setof", @2, $3.str);
|
@$ = cat_str(3, "setof", @2, $3.str);
|
||||||
}
|
}
|
||||||
ECPG: opt_array_boundsopt_array_bounds'['']' block
|
ECPG: block opt_array_bounds opt_array_bounds '[' ']'
|
||||||
{
|
{
|
||||||
$$.index1 = $1.index1;
|
$$.index1 = $1.index1;
|
||||||
$$.index2 = $1.index2;
|
$$.index2 = $1.index2;
|
||||||
@ -463,20 +463,20 @@ ECPG: opt_array_boundsopt_array_bounds'['']' block
|
|||||||
$$.index2 = @3;
|
$$.index2 = @3;
|
||||||
$$.str = cat_str(4, $1.str, "[", @3, "]");
|
$$.str = cat_str(4, $1.str, "[", @3, "]");
|
||||||
}
|
}
|
||||||
ECPG: opt_array_bounds block
|
ECPG: block opt_array_bounds
|
||||||
{
|
{
|
||||||
$$.index1 = "-1";
|
$$.index1 = "-1";
|
||||||
$$.index2 = "-1";
|
$$.index2 = "-1";
|
||||||
$$.str = "";
|
$$.str = "";
|
||||||
}
|
}
|
||||||
ECPG: AexprConstNULL_P rule
|
ECPG: rule AexprConst NULL_P
|
||||||
| civar
|
| civar
|
||||||
| civarind
|
| civarind
|
||||||
ECPG: VariableShowStmtSHOWALL block
|
ECPG: block VariableShowStmt SHOW ALL
|
||||||
{
|
{
|
||||||
mmerror(PARSE_ERROR, ET_ERROR, "SHOW ALL is not implemented");
|
mmerror(PARSE_ERROR, ET_ERROR, "SHOW ALL is not implemented");
|
||||||
}
|
}
|
||||||
ECPG: FetchStmtMOVEfetch_args rule
|
ECPG: rule FetchStmt MOVE fetch_args
|
||||||
| FETCH fetch_args ecpg_fetch_into
|
| FETCH fetch_args ecpg_fetch_into
|
||||||
| FETCH FORWARD cursor_name opt_ecpg_fetch_into
|
| FETCH FORWARD cursor_name opt_ecpg_fetch_into
|
||||||
{
|
{
|
||||||
@ -558,9 +558,9 @@ ECPG: FetchStmtMOVEfetch_args rule
|
|||||||
|
|
||||||
@$ = cat_str(2, "move backward from", cursor_marker);
|
@$ = cat_str(2, "move backward from", cursor_marker);
|
||||||
}
|
}
|
||||||
ECPG: limit_clauseLIMITselect_limit_value','select_offset_value block
|
ECPG: block limit_clause LIMIT select_limit_value ',' select_offset_value
|
||||||
{
|
{
|
||||||
mmerror(PARSE_ERROR, ET_WARNING, "no longer supported LIMIT #,# syntax passed to server");
|
mmerror(PARSE_ERROR, ET_WARNING, "no longer supported LIMIT #,# syntax passed to server");
|
||||||
}
|
}
|
||||||
ECPG: SignedIconstIconst rule
|
ECPG: rule SignedIconst Iconst
|
||||||
| civar
|
| civar
|
||||||
|
@ -75,47 +75,47 @@ my %replace_types = (
|
|||||||
my %replace_types_used;
|
my %replace_types_used;
|
||||||
|
|
||||||
# This hash provides an "ignore" option or substitute expansion for any
|
# This hash provides an "ignore" option or substitute expansion for any
|
||||||
# rule or rule alternative. The hash key is the same "concattokens" tag
|
# rule or rule alternative. The hash key is the same "tokenlist" tag
|
||||||
# used for lookup in ecpg.addons.
|
# used for lookup in ecpg.addons.
|
||||||
my %replace_line = (
|
my %replace_line = (
|
||||||
# These entries excise certain keywords from the core keyword lists.
|
# These entries excise certain keywords from the core keyword lists.
|
||||||
# Be sure to account for these in ColLabel and related productions.
|
# Be sure to account for these in ColLabel and related productions.
|
||||||
'unreserved_keywordCONNECTION' => 'ignore',
|
'unreserved_keyword CONNECTION' => 'ignore',
|
||||||
'unreserved_keywordCURRENT_P' => 'ignore',
|
'unreserved_keyword CURRENT_P' => 'ignore',
|
||||||
'unreserved_keywordDAY_P' => 'ignore',
|
'unreserved_keyword DAY_P' => 'ignore',
|
||||||
'unreserved_keywordHOUR_P' => 'ignore',
|
'unreserved_keyword HOUR_P' => 'ignore',
|
||||||
'unreserved_keywordINPUT_P' => 'ignore',
|
'unreserved_keyword INPUT_P' => 'ignore',
|
||||||
'unreserved_keywordMINUTE_P' => 'ignore',
|
'unreserved_keyword MINUTE_P' => 'ignore',
|
||||||
'unreserved_keywordMONTH_P' => 'ignore',
|
'unreserved_keyword MONTH_P' => 'ignore',
|
||||||
'unreserved_keywordSECOND_P' => 'ignore',
|
'unreserved_keyword SECOND_P' => 'ignore',
|
||||||
'unreserved_keywordYEAR_P' => 'ignore',
|
'unreserved_keyword YEAR_P' => 'ignore',
|
||||||
'col_name_keywordCHAR_P' => 'ignore',
|
'col_name_keyword CHAR_P' => 'ignore',
|
||||||
'col_name_keywordINT_P' => 'ignore',
|
'col_name_keyword INT_P' => 'ignore',
|
||||||
'col_name_keywordVALUES' => 'ignore',
|
'col_name_keyword VALUES' => 'ignore',
|
||||||
'reserved_keywordTO' => 'ignore',
|
'reserved_keyword TO' => 'ignore',
|
||||||
'reserved_keywordUNION' => 'ignore',
|
'reserved_keyword UNION' => 'ignore',
|
||||||
|
|
||||||
# some other production rules have to be ignored or replaced
|
# some other production rules have to be ignored or replaced
|
||||||
'fetch_argsFORWARDopt_from_incursor_name' => 'ignore',
|
'fetch_args FORWARD opt_from_in cursor_name' => 'ignore',
|
||||||
'fetch_argsBACKWARDopt_from_incursor_name' => 'ignore',
|
'fetch_args BACKWARD opt_from_in cursor_name' => 'ignore',
|
||||||
"opt_array_boundsopt_array_bounds'['Iconst']'" => 'ignore',
|
"opt_array_bounds opt_array_bounds '[' Iconst ']'" => 'ignore',
|
||||||
'VariableShowStmtSHOWvar_name' => 'SHOW var_name ecpg_into',
|
'VariableShowStmt SHOW var_name' => 'SHOW var_name ecpg_into',
|
||||||
'VariableShowStmtSHOWTIMEZONE' => 'SHOW TIME ZONE ecpg_into',
|
'VariableShowStmt SHOW TIME ZONE' => 'SHOW TIME ZONE ecpg_into',
|
||||||
'VariableShowStmtSHOWTRANSACTIONISOLATIONLEVEL' =>
|
'VariableShowStmt SHOW TRANSACTION ISOLATION LEVEL' =>
|
||||||
'SHOW TRANSACTION ISOLATION LEVEL ecpg_into',
|
'SHOW TRANSACTION ISOLATION LEVEL ecpg_into',
|
||||||
'VariableShowStmtSHOWSESSIONAUTHORIZATION' =>
|
'VariableShowStmt SHOW SESSION AUTHORIZATION' =>
|
||||||
'SHOW SESSION AUTHORIZATION ecpg_into',
|
'SHOW SESSION AUTHORIZATION ecpg_into',
|
||||||
'returning_clauseRETURNINGtarget_list' =>
|
'returning_clause RETURNING target_list' =>
|
||||||
'RETURNING target_list opt_ecpg_into',
|
'RETURNING target_list opt_ecpg_into',
|
||||||
'ExecuteStmtEXECUTEnameexecute_param_clause' =>
|
'ExecuteStmt EXECUTE name execute_param_clause' =>
|
||||||
'EXECUTE prepared_name execute_param_clause execute_rest',
|
'EXECUTE prepared_name execute_param_clause execute_rest',
|
||||||
'ExecuteStmtCREATEOptTempTABLEcreate_as_targetASEXECUTEnameexecute_param_clauseopt_with_data'
|
'ExecuteStmt CREATE OptTemp TABLE create_as_target AS EXECUTE name execute_param_clause opt_with_data'
|
||||||
=> 'CREATE OptTemp TABLE create_as_target AS EXECUTE prepared_name execute_param_clause opt_with_data execute_rest',
|
=> 'CREATE OptTemp TABLE create_as_target AS EXECUTE prepared_name execute_param_clause opt_with_data execute_rest',
|
||||||
'ExecuteStmtCREATEOptTempTABLEIF_PNOTEXISTScreate_as_targetASEXECUTEnameexecute_param_clauseopt_with_data'
|
'ExecuteStmt CREATE OptTemp TABLE IF_P NOT EXISTS create_as_target AS EXECUTE name execute_param_clause opt_with_data'
|
||||||
=> 'CREATE OptTemp TABLE IF_P NOT EXISTS create_as_target AS EXECUTE prepared_name execute_param_clause opt_with_data execute_rest',
|
=> 'CREATE OptTemp TABLE IF_P NOT EXISTS create_as_target AS EXECUTE prepared_name execute_param_clause opt_with_data execute_rest',
|
||||||
'PrepareStmtPREPAREnameprep_type_clauseASPreparableStmt' =>
|
'PrepareStmt PREPARE name prep_type_clause AS PreparableStmt' =>
|
||||||
'PREPARE prepared_name prep_type_clause AS PreparableStmt',
|
'PREPARE prepared_name prep_type_clause AS PreparableStmt',
|
||||||
'var_nameColId' => 'ECPGColId');
|
'var_name ColId' => 'ECPGColId');
|
||||||
|
|
||||||
my %replace_line_used;
|
my %replace_line_used;
|
||||||
|
|
||||||
@ -645,8 +645,9 @@ sub emit_default_action
|
|||||||
sub emit_rule
|
sub emit_rule
|
||||||
{
|
{
|
||||||
# compute tag to be used as lookup key in %replace_line and %addons
|
# compute tag to be used as lookup key in %replace_line and %addons
|
||||||
my $tag = $non_term_id . $line;
|
my $tag = $non_term_id . ' ' . $line;
|
||||||
$tag =~ tr/ |//d;
|
$tag =~ tr/|//d;
|
||||||
|
$tag = join(' ', split(/\s+/, $tag));
|
||||||
|
|
||||||
# apply replace_line substitution if any
|
# apply replace_line substitution if any
|
||||||
my $rep = $replace_line{$tag};
|
my $rep = $replace_line{$tag};
|
||||||
@ -671,8 +672,9 @@ sub emit_rule
|
|||||||
}
|
}
|
||||||
|
|
||||||
# recompute tag for use in emit_rule_action
|
# recompute tag for use in emit_rule_action
|
||||||
$tag = $non_term_id . $line;
|
$tag = $non_term_id . ' ' . $line;
|
||||||
$tag =~ tr/ |//d;
|
$tag =~ tr/|//d;
|
||||||
|
$tag = join(' ', split(/\s+/, $tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
# Emit $line, then print the appropriate action.
|
# Emit $line, then print the appropriate action.
|
||||||
@ -684,8 +686,8 @@ sub emit_rule
|
|||||||
=top
|
=top
|
||||||
load ecpg.addons into %addons hash. The result is something like
|
load ecpg.addons into %addons hash. The result is something like
|
||||||
%addons = {
|
%addons = {
|
||||||
stmtClosePortalStmt => { 'type' => 'block', 'lines' => [ "{", "if (INFORMIX_MODE)" ..., "}" ], 'used' => 0 },
|
'stmt ClosePortalStmt' => { 'type' => 'block', 'lines' => [ "{", "if (INFORMIX_MODE)" ..., "}" ], 'used' => 0 },
|
||||||
stmtViewStmt => { 'type' => 'rule', 'lines' => [ "| ECPGAllocateDescr", ... ], 'used' => 0 }
|
'stmt ViewStmt' => { 'type' => 'rule', 'lines' => [ "| ECPGAllocateDescr", ... ], 'used' => 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
@ -704,14 +706,21 @@ sub preload_addons
|
|||||||
my $skip = 1;
|
my $skip = 1;
|
||||||
while (<$fh>)
|
while (<$fh>)
|
||||||
{
|
{
|
||||||
if (/^ECPG:\s+(\S+)\s+(\w+)\s*$/)
|
if (/^ECPG:\s+(\w+)\s+(.*)$/)
|
||||||
{
|
{
|
||||||
# Found an "ECPG:" line, so we're done skipping the header
|
# Found an "ECPG:" line, so we're done skipping the header
|
||||||
$skip = 0;
|
$skip = 0;
|
||||||
|
my $type = $1;
|
||||||
|
my $target = $2;
|
||||||
|
# Normalize target so there's exactly one space between tokens
|
||||||
|
$target = join(' ', split(/\s+/, $target));
|
||||||
# Validate record type and target
|
# Validate record type and target
|
||||||
die "invalid record type $2 in addon rule for $1\n"
|
die "invalid record type $type in addon rule for $target\n"
|
||||||
unless ($2 eq 'block' or $2 eq 'addon' or $2 eq 'rule');
|
unless ($type eq 'block'
|
||||||
die "duplicate addon rule for $1\n" if (exists $addons{$1});
|
or $type eq 'addon'
|
||||||
|
or $type eq 'rule');
|
||||||
|
die "duplicate addon rule for $target\n"
|
||||||
|
if (exists $addons{$target});
|
||||||
# If we had some preceding code lines, attach them to all
|
# If we had some preceding code lines, attach them to all
|
||||||
# as-yet-unfinished records.
|
# as-yet-unfinished records.
|
||||||
if (@code)
|
if (@code)
|
||||||
@ -724,10 +733,10 @@ sub preload_addons
|
|||||||
@needsRules = ();
|
@needsRules = ();
|
||||||
}
|
}
|
||||||
my $record = {};
|
my $record = {};
|
||||||
$record->{type} = $2;
|
$record->{type} = $type;
|
||||||
$record->{lines} = [];
|
$record->{lines} = [];
|
||||||
$record->{used} = 0;
|
$record->{used} = 0;
|
||||||
$addons{$1} = $record;
|
$addons{$target} = $record;
|
||||||
push(@needsRules, $record);
|
push(@needsRules, $record);
|
||||||
}
|
}
|
||||||
elsif (/^ECPG:/)
|
elsif (/^ECPG:/)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user