Line data Source code
1 : /* src/interfaces/ecpg/preproc/output.c */
2 :
3 : #include "postgres_fe.h"
4 :
5 : #include "preproc_extern.h"
6 :
7 : static void output_escaped_str(const char *str, bool quoted);
8 :
9 : void
10 5174 : output_line_number(void)
11 : {
12 5174 : char *line = hashline_number();
13 :
14 5174 : fprintf(base_yyout, "%s", line);
15 5174 : }
16 :
17 : void
18 288 : output_simple_statement(const char *stmt, int whenever_mode)
19 : {
20 288 : output_escaped_str(stmt, false);
21 288 : if (whenever_mode)
22 22 : whenever_action(whenever_mode);
23 288 : output_line_number();
24 288 : }
25 :
26 :
27 : /*
28 : * store the whenever action here
29 : */
30 : struct when when_error,
31 : when_nf,
32 : when_warn;
33 :
34 : static void
35 2094 : print_action(struct when *w)
36 : {
37 2094 : switch (w->code)
38 : {
39 1124 : case W_SQLPRINT:
40 1124 : fprintf(base_yyout, "sqlprint();");
41 1124 : break;
42 4 : case W_GOTO:
43 4 : fprintf(base_yyout, "goto %s;", w->command);
44 4 : break;
45 346 : case W_DO:
46 346 : fprintf(base_yyout, "%s;", w->command);
47 346 : break;
48 594 : case W_STOP:
49 594 : fprintf(base_yyout, "exit (1);");
50 594 : break;
51 24 : case W_BREAK:
52 24 : fprintf(base_yyout, "break;");
53 24 : break;
54 2 : case W_CONTINUE:
55 2 : fprintf(base_yyout, "continue;");
56 2 : break;
57 0 : default:
58 0 : fprintf(base_yyout, "{/* %d not implemented yet */}", w->code);
59 0 : break;
60 : }
61 2094 : }
62 :
63 : void
64 2044 : whenever_action(int mode)
65 : {
66 2044 : if ((mode & 1) == 1 && when_nf.code != W_NOTHING)
67 : {
68 58 : output_line_number();
69 58 : fprintf(base_yyout, "\nif (sqlca.sqlcode == ECPG_NOT_FOUND) ");
70 58 : print_action(&when_nf);
71 : }
72 2044 : if (when_warn.code != W_NOTHING)
73 : {
74 296 : output_line_number();
75 296 : fprintf(base_yyout, "\nif (sqlca.sqlwarn[0] == 'W') ");
76 296 : print_action(&when_warn);
77 : }
78 2044 : if (when_error.code != W_NOTHING)
79 : {
80 1740 : output_line_number();
81 1740 : fprintf(base_yyout, "\nif (sqlca.sqlcode < 0) ");
82 1740 : print_action(&when_error);
83 : }
84 :
85 2044 : if ((mode & 2) == 2)
86 1954 : fputc('}', base_yyout);
87 :
88 2044 : output_line_number();
89 2044 : }
90 :
91 : char *
92 5766 : hashline_number(void)
93 : {
94 : /* do not print line numbers if we are in debug mode */
95 5766 : if (input_filename
96 : #ifdef YYDEBUG
97 : && !base_yydebug
98 : #endif
99 : )
100 : {
101 : /* "* 2" here is for escaping '\' and '"' below */
102 5766 : char *line = loc_alloc(strlen("\n#line %d \"%s\"\n") + sizeof(int) * CHAR_BIT * 10 / 3 + strlen(input_filename) * 2);
103 : char *src,
104 : *dest;
105 :
106 5766 : sprintf(line, "\n#line %d \"", base_yylineno);
107 5766 : src = input_filename;
108 5766 : dest = line + strlen(line);
109 74342 : while (*src)
110 : {
111 68576 : if (*src == '\\' || *src == '"')
112 0 : *dest++ = '\\';
113 68576 : *dest++ = *src++;
114 : }
115 5766 : *dest = '\0';
116 5766 : strcat(dest, "\"\n");
117 :
118 5766 : return line;
119 : }
120 :
121 0 : return "";
122 : }
123 :
124 : static char *ecpg_statement_type_name[] = {
125 : "ECPGst_normal",
126 : "ECPGst_execute",
127 : "ECPGst_exec_immediate",
128 : "ECPGst_prepnormal",
129 : "ECPGst_prepare",
130 : "ECPGst_exec_with_exprlist"
131 : };
132 :
133 : void
134 1106 : output_statement(const char *stmt, int whenever_mode, enum ECPG_statement_type st)
135 : {
136 1106 : fprintf(base_yyout, "{ ECPGdo(__LINE__, %d, %d, %s, %d, ", compat, force_indicator, connection ? connection : "NULL", questionmarks);
137 :
138 1106 : if (st == ECPGst_prepnormal && !auto_prepare)
139 432 : st = ECPGst_normal;
140 :
141 : /*
142 : * In following cases, stmt is CSTRING or char_variable. They must be
143 : * output directly. - prepared_name of EXECUTE without exprlist -
144 : * execstring of EXECUTE IMMEDIATE
145 : */
146 1106 : fprintf(base_yyout, "%s, ", ecpg_statement_type_name[st]);
147 1106 : if (st == ECPGst_execute || st == ECPGst_exec_immediate)
148 62 : fprintf(base_yyout, "%s, ", stmt);
149 : else
150 : {
151 1044 : fputs("\"", base_yyout);
152 1044 : output_escaped_str(stmt, false);
153 1044 : fputs("\", ", base_yyout);
154 : }
155 :
156 : /* dump variables to C file */
157 1106 : dump_variables(argsinsert, 1);
158 1106 : argsinsert = NULL;
159 1106 : fputs("ECPGt_EOIT, ", base_yyout);
160 1106 : dump_variables(argsresult, 1);
161 1106 : argsresult = NULL;
162 1106 : fputs("ECPGt_EORT);", base_yyout);
163 :
164 1106 : whenever_action(whenever_mode | 2);
165 1106 : }
166 :
167 : void
168 96 : output_prepare_statement(const char *name, const char *stmt)
169 : {
170 96 : fprintf(base_yyout, "{ ECPGprepare(__LINE__, %s, %d, ", connection ? connection : "NULL", questionmarks);
171 96 : output_escaped_str(name, true);
172 96 : fputs(", ", base_yyout);
173 96 : output_escaped_str(stmt, true);
174 96 : fputs(");", base_yyout);
175 96 : whenever_action(2);
176 96 : }
177 :
178 : void
179 76 : output_deallocate_prepare_statement(const char *name)
180 : {
181 76 : const char *con = connection ? connection : "NULL";
182 :
183 76 : if (strcmp(name, "all") != 0)
184 : {
185 74 : fprintf(base_yyout, "{ ECPGdeallocate(__LINE__, %d, %s, ", compat, con);
186 74 : output_escaped_str(name, true);
187 74 : fputs(");", base_yyout);
188 : }
189 : else
190 2 : fprintf(base_yyout, "{ ECPGdeallocate_all(__LINE__, %d, %s);", compat, con);
191 :
192 76 : whenever_action(2);
193 76 : }
194 :
195 : static void
196 1598 : output_escaped_str(const char *str, bool quoted)
197 : {
198 1598 : int i = 0;
199 1598 : int len = strlen(str);
200 :
201 1598 : if (quoted && str[0] == '"' && str[len - 1] == '"') /* do not escape quotes
202 : * at beginning and end
203 : * if quoted string */
204 : {
205 170 : i = 1;
206 170 : len--;
207 170 : fputs("\"", base_yyout);
208 : }
209 :
210 : /* output this char by char as we have to filter " and \n */
211 60050 : for (; i < len; i++)
212 : {
213 58452 : if (str[i] == '"')
214 208 : fputs("\\\"", base_yyout);
215 58244 : else if (str[i] == '\n')
216 36 : fputs("\\\n", base_yyout);
217 58208 : else if (str[i] == '\\')
218 : {
219 44 : int j = i;
220 :
221 : /*
222 : * check whether this is a continuation line if it is, do not
223 : * output anything because newlines are escaped anyway
224 : */
225 :
226 : /* accept blanks after the '\' as some other compilers do too */
227 : do
228 : {
229 44 : j++;
230 44 : } while (str[j] == ' ' || str[j] == '\t');
231 :
232 44 : if ((str[j] != '\n') && (str[j] != '\r' || str[j + 1] != '\n')) /* not followed by a
233 : * newline */
234 44 : fputs("\\\\", base_yyout);
235 : }
236 58164 : else if (str[i] == '\r' && str[i + 1] == '\n')
237 : {
238 0 : fputs("\\\r\n", base_yyout);
239 0 : i++;
240 : }
241 : else
242 58164 : fputc(str[i], base_yyout);
243 : }
244 :
245 1598 : if (quoted && str[0] == '"' && str[len] == '"')
246 170 : fputs("\"", base_yyout);
247 1598 : }
|