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