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