mirror of
https://github.com/postgres/postgres.git
synced 2026-03-09 09:40:40 -04:00
Back-patch commit 92fb64983 into the pre-9.6 branches.
Without this, ecpg fails to build with the latest version of flex.
It's not unreasonable that people would want to compile our old branches
with recent tools. Per report from Дилян Палаузов.
Discussion: https://postgr.es/m/d845c1af-e18d-6651-178f-9f08cdf37e10@aegee.org
246 lines
5.1 KiB
C
246 lines
5.1 KiB
C
/* src/interfaces/ecpg/preproc/output.c */
|
|
|
|
#include "postgres_fe.h"
|
|
|
|
#include "extern.h"
|
|
|
|
static void output_escaped_str(char *cmd, bool quoted);
|
|
|
|
void
|
|
output_line_number(void)
|
|
{
|
|
char *line = hashline_number();
|
|
|
|
fprintf(base_yyout, "%s", line);
|
|
free(line);
|
|
}
|
|
|
|
void
|
|
output_simple_statement(char *stmt)
|
|
{
|
|
output_escaped_str(stmt, false);
|
|
output_line_number();
|
|
free(stmt);
|
|
}
|
|
|
|
|
|
/*
|
|
* store the whenever action here
|
|
*/
|
|
struct when when_error,
|
|
when_nf,
|
|
when_warn;
|
|
|
|
static void
|
|
print_action(struct when * w)
|
|
{
|
|
switch (w->code)
|
|
{
|
|
case W_SQLPRINT:
|
|
fprintf(base_yyout, "sqlprint();");
|
|
break;
|
|
case W_GOTO:
|
|
fprintf(base_yyout, "goto %s;", w->command);
|
|
break;
|
|
case W_DO:
|
|
fprintf(base_yyout, "%s;", w->command);
|
|
break;
|
|
case W_STOP:
|
|
fprintf(base_yyout, "exit (1);");
|
|
break;
|
|
case W_BREAK:
|
|
fprintf(base_yyout, "break;");
|
|
break;
|
|
default:
|
|
fprintf(base_yyout, "{/* %d not implemented yet */}", w->code);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
whenever_action(int mode)
|
|
{
|
|
if ((mode & 1) == 1 && when_nf.code != W_NOTHING)
|
|
{
|
|
output_line_number();
|
|
fprintf(base_yyout, "\nif (sqlca.sqlcode == ECPG_NOT_FOUND) ");
|
|
print_action(&when_nf);
|
|
}
|
|
if (when_warn.code != W_NOTHING)
|
|
{
|
|
output_line_number();
|
|
fprintf(base_yyout, "\nif (sqlca.sqlwarn[0] == 'W') ");
|
|
print_action(&when_warn);
|
|
}
|
|
if (when_error.code != W_NOTHING)
|
|
{
|
|
output_line_number();
|
|
fprintf(base_yyout, "\nif (sqlca.sqlcode < 0) ");
|
|
print_action(&when_error);
|
|
}
|
|
|
|
if ((mode & 2) == 2)
|
|
fputc('}', base_yyout);
|
|
|
|
output_line_number();
|
|
}
|
|
|
|
char *
|
|
hashline_number(void)
|
|
{
|
|
/* do not print line numbers if we are in debug mode */
|
|
if (input_filename
|
|
#ifdef YYDEBUG
|
|
&& !base_yydebug
|
|
#endif
|
|
)
|
|
{
|
|
/* "* 2" here is for escaping '\' and '"' below */
|
|
char *line = mm_alloc(strlen("\n#line %d \"%s\"\n") + sizeof(int) * CHAR_BIT * 10 / 3 + strlen(input_filename) * 2);
|
|
char *src,
|
|
*dest;
|
|
|
|
sprintf(line, "\n#line %d \"", base_yylineno);
|
|
src = input_filename;
|
|
dest = line + strlen(line);
|
|
while (*src)
|
|
{
|
|
if (*src == '\\' || *src == '"')
|
|
*dest++ = '\\';
|
|
*dest++ = *src++;
|
|
}
|
|
*dest = '\0';
|
|
strcat(dest, "\"\n");
|
|
|
|
return line;
|
|
}
|
|
|
|
return EMPTY;
|
|
}
|
|
|
|
static char *ecpg_statement_type_name[] = {
|
|
"ECPGst_normal",
|
|
"ECPGst_execute",
|
|
"ECPGst_exec_immediate",
|
|
"ECPGst_prepnormal"
|
|
};
|
|
|
|
void
|
|
output_statement(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);
|
|
if (st == ECPGst_execute || st == ECPGst_exec_immediate)
|
|
{
|
|
fprintf(base_yyout, "%s, %s, ", ecpg_statement_type_name[st], stmt);
|
|
}
|
|
else
|
|
{
|
|
if (st == ECPGst_prepnormal && auto_prepare)
|
|
fputs("ECPGst_prepnormal, \"", base_yyout);
|
|
else
|
|
fputs("ECPGst_normal, \"", base_yyout);
|
|
|
|
output_escaped_str(stmt, false);
|
|
fputs("\", ", base_yyout);
|
|
}
|
|
|
|
/* dump variables to C file */
|
|
dump_variables(argsinsert, 1);
|
|
fputs("ECPGt_EOIT, ", base_yyout);
|
|
dump_variables(argsresult, 1);
|
|
fputs("ECPGt_EORT);", base_yyout);
|
|
reset_variables();
|
|
|
|
whenever_action(whenever_mode | 2);
|
|
free(stmt);
|
|
if (connection != NULL)
|
|
free(connection);
|
|
}
|
|
|
|
void
|
|
output_prepare_statement(char *name, char *stmt)
|
|
{
|
|
fprintf(base_yyout, "{ ECPGprepare(__LINE__, %s, %d, ", connection ? connection : "NULL", questionmarks);
|
|
output_escaped_str(name, true);
|
|
fputs(", ", base_yyout);
|
|
output_escaped_str(stmt, true);
|
|
fputs(");", base_yyout);
|
|
whenever_action(2);
|
|
free(name);
|
|
if (connection != NULL)
|
|
free(connection);
|
|
}
|
|
|
|
void
|
|
output_deallocate_prepare_statement(char *name)
|
|
{
|
|
const char *con = connection ? connection : "NULL";
|
|
|
|
if (strcmp(name, "all") != 0)
|
|
{
|
|
fprintf(base_yyout, "{ ECPGdeallocate(__LINE__, %d, %s, ", compat, con);
|
|
output_escaped_str(name, true);
|
|
fputs(");", base_yyout);
|
|
}
|
|
else
|
|
fprintf(base_yyout, "{ ECPGdeallocate_all(__LINE__, %d, %s);", compat, con);
|
|
|
|
whenever_action(2);
|
|
free(name);
|
|
if (connection != NULL)
|
|
free(connection);
|
|
}
|
|
|
|
static void
|
|
output_escaped_str(char *str, bool quoted)
|
|
{
|
|
int i = 0;
|
|
int len = strlen(str);
|
|
|
|
if (quoted && str[0] == '\"' && str[len - 1] == '\"') /* do not escape quotes
|
|
* at beginning and end
|
|
* if quoted string */
|
|
{
|
|
i = 1;
|
|
len--;
|
|
fputs("\"", base_yyout);
|
|
}
|
|
|
|
/* output this char by char as we have to filter " and \n */
|
|
for (; i < len; i++)
|
|
{
|
|
if (str[i] == '"')
|
|
fputs("\\\"", base_yyout);
|
|
else if (str[i] == '\n')
|
|
fputs("\\\n", base_yyout);
|
|
else if (str[i] == '\\')
|
|
{
|
|
int j = i;
|
|
|
|
/*
|
|
* check whether this is a continuation line if it is, do not
|
|
* output anything because newlines are escaped anyway
|
|
*/
|
|
|
|
/* accept blanks after the '\' as some other compilers do too */
|
|
do
|
|
{
|
|
j++;
|
|
} while (str[j] == ' ' || str[j] == '\t');
|
|
|
|
if ((str[j] != '\n') && (str[j] != '\r' || str[j + 1] != '\n')) /* not followed by a
|
|
* newline */
|
|
fputs("\\\\", base_yyout);
|
|
}
|
|
else if (str[i] == '\r' && str[i + 1] == '\n')
|
|
{
|
|
fputs("\\\r\n", base_yyout);
|
|
i++;
|
|
}
|
|
else
|
|
fputc(str[i], base_yyout);
|
|
}
|
|
|
|
if (quoted && str[0] == '\"' && str[len] == '\"')
|
|
fputs("\"", base_yyout);
|
|
}
|