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
18static struct assignment *assignments;
19
20void
21push_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
32static void
33drop_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
45static void
46ECPGnumeric_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
73static struct descriptor *descriptors;
74
75void
76add_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
98void
99drop_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 mmerror(PARSE_ERROR, ET_WARNING, "descriptor \"%s\" does not exist", name);
125}
126
127struct descriptor
128 *
129lookup_descriptor(char *name, char *connection)
130{
131 struct descriptor *i;
132
133 if (name[0] != '"')
134 return NULL;
135
136 for (i = descriptors; i; i = i->next)
137 {
138 if (strcmp(name, i->name) == 0)
139 {
140 if ((!connection && !i->connection)
141 || (connection && i->connection
142 && strcmp(connection, i->connection) == 0))
143 return i;
144 }
145 }
146 mmerror(PARSE_ERROR, ET_WARNING, "descriptor \"%s\" does not exist", name);
147 return NULL;
148}
149
150void
151output_get_descr_header(char *desc_name)
152{
153 struct assignment *results;
154
155 fprintf(base_yyout, "{ ECPGget_desc_header(__LINE__, %s, &(", desc_name);
156 for (results = assignments; results != NULL; results = results->next)
157 {
158 if (results->value == ECPGd_count)
159 ECPGnumeric_lvalue(results->variable);
160 else
161 mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value);
162 }
163
164 drop_assignments();
165 fprintf(base_yyout, "));\n");
166 whenever_action(3);
167}
168
169void
170output_get_descr(char *desc_name, char *index)
171{
172 struct assignment *results;
173
174 fprintf(base_yyout, "{ ECPGget_desc(__LINE__, %s, %s,", desc_name, index);
175 for (results = assignments; results != NULL; results = results->next)
176 {
177 const struct variable *v = find_variable(results->variable);
178 char *str_zero = mm_strdup("0");
179
180 switch (results->value)
181 {
182 case ECPGd_nullable:
183 mmerror(PARSE_ERROR, ET_WARNING, "nullable is always 1");
184 break;
185 case ECPGd_key_member:
186 mmerror(PARSE_ERROR, ET_WARNING, "key_member is always 0");
187 break;
188 default:
189 break;
190 }
191 fprintf(base_yyout, "%s,", get_dtype(results->value));
192 ECPGdump_a_type(base_yyout, v->name, v->type, v->brace_level,
193 NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL);
194 free(str_zero);
195 }
196 drop_assignments();
197 fputs("ECPGd_EODT);\n", base_yyout);
198
199 whenever_action(2 | 1);
200}
201
202void
203output_set_descr_header(char *desc_name)
204{
205 struct assignment *results;
206
207 fprintf(base_yyout, "{ ECPGset_desc_header(__LINE__, %s, (int)(", desc_name);
208 for (results = assignments; results != NULL; results = results->next)
209 {
210 if (results->value == ECPGd_count)
211 ECPGnumeric_lvalue(results->variable);
212 else
213 mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value);
214 }
215
216 drop_assignments();
217 fprintf(base_yyout, "));\n");
218 whenever_action(3);
219}
220
221static const char *
222descriptor_item_name(enum ECPGdtype itemcode)
223{
224 switch (itemcode)
225 {
226 case ECPGd_cardinality:
227 return "CARDINALITY";
228 case ECPGd_count:
229 return "COUNT";
230 case ECPGd_data:
231 return "DATA";
232 case ECPGd_di_code:
233 return "DATETIME_INTERVAL_CODE";
234 case ECPGd_di_precision:
235 return "DATETIME_INTERVAL_PRECISION";
236 case ECPGd_indicator:
237 return "INDICATOR";
238 case ECPGd_key_member:
239 return "KEY_MEMBER";
240 case ECPGd_length:
241 return "LENGTH";
242 case ECPGd_name:
243 return "NAME";
244 case ECPGd_nullable:
245 return "NULLABLE";
246 case ECPGd_octet:
247 return "OCTET_LENGTH";
248 case ECPGd_precision:
249 return "PRECISION";
250 case ECPGd_ret_length:
251 return "RETURNED_LENGTH";
252 case ECPGd_ret_octet:
253 return "RETURNED_OCTET_LENGTH";
254 case ECPGd_scale:
255 return "SCALE";
256 case ECPGd_type:
257 return "TYPE";
258 default:
259 return NULL;
260 }
261}
262
263void
264output_set_descr(char *desc_name, char *index)
265{
266 struct assignment *results;
267
268 fprintf(base_yyout, "{ ECPGset_desc(__LINE__, %s, %s,", desc_name, index);
269 for (results = assignments; results != NULL; results = results->next)
270 {
271 const struct variable *v = find_variable(results->variable);
272
273 switch (results->value)
274 {
275 case ECPGd_cardinality:
276 case ECPGd_di_code:
277 case ECPGd_di_precision:
278 case ECPGd_precision:
279 case ECPGd_scale:
280 mmfatal(PARSE_ERROR, "descriptor item \"%s\" is not implemented",
281 descriptor_item_name(results->value));
282 break;
283
284 case ECPGd_key_member:
285 case ECPGd_name:
286 case ECPGd_nullable:
287 case ECPGd_octet:
288 case ECPGd_ret_length:
289 case ECPGd_ret_octet:
290 mmfatal(PARSE_ERROR, "descriptor item \"%s\" cannot be set",
291 descriptor_item_name(results->value));
292 break;
293
294 case ECPGd_data:
295 case ECPGd_indicator:
296 case ECPGd_length:
297 case ECPGd_type:
298 {
299 char *str_zero = mm_strdup("0");
300
301 fprintf(base_yyout, "%s,", get_dtype(results->value));
302 ECPGdump_a_type(base_yyout, v->name, v->type, v->brace_level,
303 NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL);
304 free(str_zero);
305 }
306 break;
307
308 default:
309 ;
310 }
311 }
312 drop_assignments();
313 fputs("ECPGd_EODT);\n", base_yyout);
314
315 whenever_action(2 | 1);
316}
317
318/* I consider dynamic allocation overkill since at most two descriptor
319 variables are possible per statement. (input and output descriptor)
320 And descriptors are no normal variables, so they don't belong into
321 the variable list.
322*/
323
324#define MAX_DESCRIPTOR_NAMELEN 128
325struct variable *
326descriptor_variable(const char *name, int input)
327{
328 static char descriptor_names[2][MAX_DESCRIPTOR_NAMELEN];
329 static struct ECPGtype descriptor_type = {ECPGt_descriptor, NULL, NULL, NULL, {NULL}, 0};
330 static struct variable varspace[2] = {
331 {descriptor_names[0], &descriptor_type, 0, NULL},
332 {descriptor_names[1], &descriptor_type, 0, NULL}
333 };
334
335 strlcpy(descriptor_names[input], name, sizeof(descriptor_names[input]));
336 return &varspace[input];
337}
338
339struct variable *
340sqlda_variable(const char *name)
341{
342 struct variable *p = (struct variable *) mm_alloc(sizeof(struct variable));
343
344 p->name = mm_strdup(name);
345 p->type = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype));
346 p->type->type = ECPGt_sqlda;
347 p->type->size = NULL;
348 p->type->struct_sizeof = NULL;
349 p->type->u.element = NULL;
350 p->type->counter = 0;
351 p->brace_level = 0;
352 p->next = NULL;
353
354 return p;
355}
356