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