diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:15:05 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:15:05 +0000 |
commit | 46651ce6fe013220ed397add242004d764fc0153 (patch) | |
tree | 6e5299f990f88e60174a1d3ae6e48eedd2688b2b /src/interfaces/ecpg/preproc/output.c | |
parent | Initial commit. (diff) | |
download | postgresql-14-upstream.tar.xz postgresql-14-upstream.zip |
Adding upstream version 14.5.upstream/14.5upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/interfaces/ecpg/preproc/output.c')
-rw-r--r-- | src/interfaces/ecpg/preproc/output.c | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/src/interfaces/ecpg/preproc/output.c b/src/interfaces/ecpg/preproc/output.c new file mode 100644 index 0000000..cf8aadd --- /dev/null +++ b/src/interfaces/ecpg/preproc/output.c @@ -0,0 +1,251 @@ +/* src/interfaces/ecpg/preproc/output.c */ + +#include "postgres_fe.h" + +#include "preproc_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, int whenever_mode) +{ + output_escaped_str(stmt, false); + if (whenever_mode) + whenever_action(whenever_mode); + 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; + case W_CONTINUE: + fprintf(base_yyout, "continue;"); + 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", + "ECPGst_prepare", + "ECPGst_exec_with_exprlist" +}; + +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_prepnormal && !auto_prepare) + st = ECPGst_normal; + + /* + * In following cases, stmt is CSTRING or char_variable. They must be + * output directly. - prepared_name of EXECUTE without exprlist - + * execstring of EXECUTE IMMEDIATE + */ + fprintf(base_yyout, "%s, ", ecpg_statement_type_name[st]); + if (st == ECPGst_execute || st == ECPGst_exec_immediate) + fprintf(base_yyout, "%s, ", stmt); + else + { + fputs("\"", 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); +} + +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); +} + +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); +} + +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); +} |