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