1 /*
2 * functions needed for descriptor handling
3 *
4 * src/interfaces/ecpg/preproc/descriptor.c
5 *
6 * since descriptor might be either a string constant or a string var
7 * we need to check for a constant if we expect a constant
8 */
9
10 #include "postgres_fe.h"
11
12 #include "preproc_extern.h"
13
14 /*
15 * assignment handling function (descriptor)
16 */
17
18 static struct assignment *assignments;
19
20 void
push_assignment(char * var,enum ECPGdtype value)21 push_assignment(char *var, enum ECPGdtype value)
22 {
23 struct assignment *new = (struct assignment *) mm_alloc(sizeof(struct assignment));
24
25 new->next = assignments;
26 new->variable = mm_alloc(strlen(var) + 1);
27 strcpy(new->variable, var);
28 new->value = value;
29 assignments = new;
30 }
31
32 static void
drop_assignments(void)33 drop_assignments(void)
34 {
35 while (assignments)
36 {
37 struct assignment *old_head = assignments;
38
39 assignments = old_head->next;
40 free(old_head->variable);
41 free(old_head);
42 }
43 }
44
45 static void
ECPGnumeric_lvalue(char * name)46 ECPGnumeric_lvalue(char *name)
47 {
48 const struct variable *v = find_variable(name);
49
50 switch (v->type->type)
51 {
52 case ECPGt_short:
53 case ECPGt_int:
54 case ECPGt_long:
55 case ECPGt_long_long:
56 case ECPGt_unsigned_short:
57 case ECPGt_unsigned_int:
58 case ECPGt_unsigned_long:
59 case ECPGt_unsigned_long_long:
60 case ECPGt_const:
61 fputs(name, base_yyout);
62 break;
63 default:
64 mmerror(PARSE_ERROR, ET_ERROR, "variable \"%s\" must have a numeric type", name);
65 break;
66 }
67 }
68
69 /*
70 * descriptor name lookup
71 */
72
73 static struct descriptor *descriptors;
74
75 void
add_descriptor(char * name,char * connection)76 add_descriptor(char *name, char *connection)
77 {
78 struct descriptor *new;
79
80 if (name[0] != '"')
81 return;
82
83 new = (struct descriptor *) mm_alloc(sizeof(struct descriptor));
84
85 new->next = descriptors;
86 new->name = mm_alloc(strlen(name) + 1);
87 strcpy(new->name, name);
88 if (connection)
89 {
90 new->connection = mm_alloc(strlen(connection) + 1);
91 strcpy(new->connection, connection);
92 }
93 else
94 new->connection = connection;
95 descriptors = new;
96 }
97
98 void
drop_descriptor(char * name,char * connection)99 drop_descriptor(char *name, char *connection)
100 {
101 struct descriptor *i;
102 struct descriptor **lastptr = &descriptors;
103
104 if (name[0] != '"')
105 return;
106
107 for (i = descriptors; i; lastptr = &i->next, i = i->next)
108 {
109 if (strcmp(name, i->name) == 0)
110 {
111 if ((!connection && !i->connection)
112 || (connection && i->connection
113 && strcmp(connection, i->connection) == 0))
114 {
115 *lastptr = i->next;
116 if (i->connection)
117 free(i->connection);
118 free(i->name);
119 free(i);
120 return;
121 }
122 }
123 }
124 if (connection)
125 mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to connection %s does not exist", name, connection);
126 else
127 mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to the default connection does not exist", name);
128 }
129
130 struct descriptor
131 *
lookup_descriptor(char * name,char * connection)132 lookup_descriptor(char *name, char *connection)
133 {
134 struct descriptor *i;
135
136 if (name[0] != '"')
137 return NULL;
138
139 for (i = descriptors; i; i = i->next)
140 {
141 if (strcmp(name, i->name) == 0)
142 {
143 if ((!connection && !i->connection)
144 || (connection && i->connection
145 && strcmp(connection, i->connection) == 0))
146 return i;
147 if (connection && !i->connection)
148 {
149 /* overwrite descriptor's connection */
150 i->connection = mm_strdup(connection);
151 return i;
152 }
153 }
154 }
155 if (connection)
156 mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to connection %s does not exist", name, connection);
157 else
158 mmerror(PARSE_ERROR, ET_WARNING, "descriptor %s bound to the default connection does not exist", name);
159 return NULL;
160 }
161
162 void
output_get_descr_header(char * desc_name)163 output_get_descr_header(char *desc_name)
164 {
165 struct assignment *results;
166
167 fprintf(base_yyout, "{ ECPGget_desc_header(__LINE__, %s, &(", desc_name);
168 for (results = assignments; results != NULL; results = results->next)
169 {
170 if (results->value == ECPGd_count)
171 ECPGnumeric_lvalue(results->variable);
172 else
173 mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value);
174 }
175
176 drop_assignments();
177 fprintf(base_yyout, "));\n");
178 whenever_action(3);
179 }
180
181 void
output_get_descr(char * desc_name,char * index)182 output_get_descr(char *desc_name, char *index)
183 {
184 struct assignment *results;
185
186 fprintf(base_yyout, "{ ECPGget_desc(__LINE__, %s, %s,", desc_name, index);
187 for (results = assignments; results != NULL; results = results->next)
188 {
189 const struct variable *v = find_variable(results->variable);
190 char *str_zero = mm_strdup("0");
191
192 switch (results->value)
193 {
194 case ECPGd_nullable:
195 mmerror(PARSE_ERROR, ET_WARNING, "nullable is always 1");
196 break;
197 case ECPGd_key_member:
198 mmerror(PARSE_ERROR, ET_WARNING, "key_member is always 0");
199 break;
200 default:
201 break;
202 }
203 fprintf(base_yyout, "%s,", get_dtype(results->value));
204 ECPGdump_a_type(base_yyout, v->name, v->type, v->brace_level,
205 NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL);
206 free(str_zero);
207 }
208 drop_assignments();
209 fputs("ECPGd_EODT);\n", base_yyout);
210
211 whenever_action(2 | 1);
212 }
213
214 void
output_set_descr_header(char * desc_name)215 output_set_descr_header(char *desc_name)
216 {
217 struct assignment *results;
218
219 fprintf(base_yyout, "{ ECPGset_desc_header(__LINE__, %s, (int)(", desc_name);
220 for (results = assignments; results != NULL; results = results->next)
221 {
222 if (results->value == ECPGd_count)
223 ECPGnumeric_lvalue(results->variable);
224 else
225 mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value);
226 }
227
228 drop_assignments();
229 fprintf(base_yyout, "));\n");
230 whenever_action(3);
231 }
232
233 static const char *
descriptor_item_name(enum ECPGdtype itemcode)234 descriptor_item_name(enum ECPGdtype itemcode)
235 {
236 switch (itemcode)
237 {
238 case ECPGd_cardinality:
239 return "CARDINALITY";
240 case ECPGd_count:
241 return "COUNT";
242 case ECPGd_data:
243 return "DATA";
244 case ECPGd_di_code:
245 return "DATETIME_INTERVAL_CODE";
246 case ECPGd_di_precision:
247 return "DATETIME_INTERVAL_PRECISION";
248 case ECPGd_indicator:
249 return "INDICATOR";
250 case ECPGd_key_member:
251 return "KEY_MEMBER";
252 case ECPGd_length:
253 return "LENGTH";
254 case ECPGd_name:
255 return "NAME";
256 case ECPGd_nullable:
257 return "NULLABLE";
258 case ECPGd_octet:
259 return "OCTET_LENGTH";
260 case ECPGd_precision:
261 return "PRECISION";
262 case ECPGd_ret_length:
263 return "RETURNED_LENGTH";
264 case ECPGd_ret_octet:
265 return "RETURNED_OCTET_LENGTH";
266 case ECPGd_scale:
267 return "SCALE";
268 case ECPGd_type:
269 return "TYPE";
270 default:
271 return NULL;
272 }
273 }
274
275 void
output_set_descr(char * desc_name,char * index)276 output_set_descr(char *desc_name, char *index)
277 {
278 struct assignment *results;
279
280 fprintf(base_yyout, "{ ECPGset_desc(__LINE__, %s, %s,", desc_name, index);
281 for (results = assignments; results != NULL; results = results->next)
282 {
283 const struct variable *v = find_variable(results->variable);
284
285 switch (results->value)
286 {
287 case ECPGd_cardinality:
288 case ECPGd_di_code:
289 case ECPGd_di_precision:
290 case ECPGd_precision:
291 case ECPGd_scale:
292 mmfatal(PARSE_ERROR, "descriptor item \"%s\" is not implemented",
293 descriptor_item_name(results->value));
294 break;
295
296 case ECPGd_key_member:
297 case ECPGd_name:
298 case ECPGd_nullable:
299 case ECPGd_octet:
300 case ECPGd_ret_length:
301 case ECPGd_ret_octet:
302 mmfatal(PARSE_ERROR, "descriptor item \"%s\" cannot be set",
303 descriptor_item_name(results->value));
304 break;
305
306 case ECPGd_data:
307 case ECPGd_indicator:
308 case ECPGd_length:
309 case ECPGd_type:
310 {
311 char *str_zero = mm_strdup("0");
312
313 fprintf(base_yyout, "%s,", get_dtype(results->value));
314 ECPGdump_a_type(base_yyout, v->name, v->type, v->brace_level,
315 NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL);
316 free(str_zero);
317 }
318 break;
319
320 default:
321 ;
322 }
323 }
324 drop_assignments();
325 fputs("ECPGd_EODT);\n", base_yyout);
326
327 whenever_action(2 | 1);
328 }
329
330 /* I consider dynamic allocation overkill since at most two descriptor
331 variables are possible per statement. (input and output descriptor)
332 And descriptors are no normal variables, so they don't belong into
333 the variable list.
334 */
335
336 #define MAX_DESCRIPTOR_NAMELEN 128
337 struct variable *
descriptor_variable(const char * name,int input)338 descriptor_variable(const char *name, int input)
339 {
340 static char descriptor_names[2][MAX_DESCRIPTOR_NAMELEN];
341 static struct ECPGtype descriptor_type = {ECPGt_descriptor, NULL, NULL, NULL, {NULL}, 0};
342 static struct variable varspace[2] = {
343 {descriptor_names[0], &descriptor_type, 0, NULL},
344 {descriptor_names[1], &descriptor_type, 0, NULL}
345 };
346
347 strlcpy(descriptor_names[input], name, sizeof(descriptor_names[input]));
348 return &varspace[input];
349 }
350
351 struct variable *
sqlda_variable(const char * name)352 sqlda_variable(const char *name)
353 {
354 struct variable *p = (struct variable *) mm_alloc(sizeof(struct variable));
355
356 p->name = mm_strdup(name);
357 p->type = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype));
358 p->type->type = ECPGt_sqlda;
359 p->type->size = NULL;
360 p->type->struct_sizeof = NULL;
361 p->type->u.element = NULL;
362 p->type->counter = 0;
363 p->brace_level = 0;
364 p->next = NULL;
365
366 return p;
367 }
368