Fix xslt_process() to ensure that it inserts a NULL terminator after the
[PostgreSQL.git] / src / interfaces / ecpg / preproc / descriptor.c
blob2b4ea79695f2efa74820a68c72bfe6b54522d193
1 /*
2 * functions needed for descriptor handling
4 * $PostgreSQL$
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 */
10 #include "postgres_fe.h"
12 #include "extern.h"
15 * assignment handling function (descriptor)
18 static struct assignment *assignments;
20 void
21 push_assignment(char *var, enum ECPGdtype value)
23 struct assignment *new = (struct assignment *) mm_alloc(sizeof(struct assignment));
25 new->next = assignments;
26 new->variable = mm_alloc(strlen(var) + 1);
27 strcpy(new->variable, var);
28 new->value = value;
29 assignments = new;
32 static void
33 drop_assignments(void)
35 while (assignments)
37 struct assignment *old_head = assignments;
39 assignments = old_head->next;
40 free(old_head->variable);
41 free(old_head);
45 static void
46 ECPGnumeric_lvalue(char *name)
48 const struct variable *v = find_variable(name);
50 switch (v->type->type)
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, yyout);
62 break;
63 default:
64 mmerror(PARSE_ERROR, ET_ERROR, "variable \"%s\" must have a numeric type", name);
65 break;
70 * descriptor name lookup
73 static struct descriptor *descriptors;
75 void
76 add_descriptor(char *name, char *connection)
78 struct descriptor *new;
80 if (name[0] != '"')
81 return;
83 new = (struct descriptor *) mm_alloc(sizeof(struct descriptor));
85 new->next = descriptors;
86 new->name = mm_alloc(strlen(name) + 1);
87 strcpy(new->name, name);
88 if (connection)
90 new->connection = mm_alloc(strlen(connection) + 1);
91 strcpy(new->connection, connection);
93 else
94 new->connection = connection;
95 descriptors = new;
98 void
99 drop_descriptor(char *name, char *connection)
101 struct descriptor *i;
102 struct descriptor **lastptr = &descriptors;
104 if (name[0] != '"')
105 return;
107 for (i = descriptors; i; lastptr = &i->next, i = i->next)
109 if (!strcmp(name, i->name))
111 if ((!connection && !i->connection)
112 || (connection && i->connection
113 && !strcmp(connection, i->connection)))
115 *lastptr = i->next;
116 if (i->connection)
117 free(i->connection);
118 free(i->name);
119 free(i);
120 return;
124 mmerror(PARSE_ERROR, ET_WARNING, "descriptor \"%s\" does not exist", name);
127 struct descriptor
129 lookup_descriptor(char *name, char *connection)
131 struct descriptor *i;
133 if (name[0] != '"')
134 return NULL;
136 for (i = descriptors; i; i = i->next)
138 if (!strcmp(name, i->name))
140 if ((!connection && !i->connection)
141 || (connection && i->connection
142 && !strcmp(connection, i->connection)))
143 return i;
146 mmerror(PARSE_ERROR, ET_WARNING, "descriptor \"%s\" does not exist", name);
147 return NULL;
150 void
151 output_get_descr_header(char *desc_name)
153 struct assignment *results;
155 fprintf(yyout, "{ ECPGget_desc_header(__LINE__, %s, &(", desc_name);
156 for (results = assignments; results != NULL; results = results->next)
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);
164 drop_assignments();
165 fprintf(yyout, "));\n");
166 whenever_action(3);
169 void
170 output_get_descr(char *desc_name, char *index)
172 struct assignment *results;
174 fprintf(yyout, "{ ECPGget_desc(__LINE__, %s, %s,", desc_name, index);
175 for (results = assignments; results != NULL; results = results->next)
177 const struct variable *v = find_variable(results->variable);
179 switch (results->value)
181 case ECPGd_nullable:
182 mmerror(PARSE_ERROR, ET_WARNING, "nullable is always 1");
183 break;
184 case ECPGd_key_member:
185 mmerror(PARSE_ERROR, ET_WARNING, "key_member is always 0");
186 break;
187 default:
188 break;
190 fprintf(yyout, "%s,", get_dtype(results->value));
191 ECPGdump_a_type(yyout, v->name, v->type, NULL, NULL, NULL, NULL, make_str("0"), NULL, NULL);
193 drop_assignments();
194 fputs("ECPGd_EODT);\n", yyout);
196 whenever_action(2 | 1);
199 void
200 output_set_descr_header(char *desc_name)
202 struct assignment *results;
204 fprintf(yyout, "{ ECPGset_desc_header(__LINE__, %s, (int)(", desc_name);
205 for (results = assignments; results != NULL; results = results->next)
207 if (results->value == ECPGd_count)
208 ECPGnumeric_lvalue(results->variable);
209 else
210 mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value);
213 drop_assignments();
214 fprintf(yyout, "));\n");
215 whenever_action(3);
218 static const char *
219 descriptor_item_name(enum ECPGdtype itemcode)
221 switch (itemcode)
223 case ECPGd_cardinality:
224 return "CARDINALITY";
225 case ECPGd_count:
226 return "COUNT";
227 case ECPGd_data:
228 return "DATA";
229 case ECPGd_di_code:
230 return "DATETIME_INTERVAL_CODE";
231 case ECPGd_di_precision:
232 return "DATETIME_INTERVAL_PRECISION";
233 case ECPGd_indicator:
234 return "INDICATOR";
235 case ECPGd_key_member:
236 return "KEY_MEMBER";
237 case ECPGd_length:
238 return "LENGTH";
239 case ECPGd_name:
240 return "NAME";
241 case ECPGd_nullable:
242 return "NULLABLE";
243 case ECPGd_octet:
244 return "OCTET_LENGTH";
245 case ECPGd_precision:
246 return "PRECISION";
247 case ECPGd_ret_length:
248 return "RETURNED_LENGTH";
249 case ECPGd_ret_octet:
250 return "RETURNED_OCTET_LENGTH";
251 case ECPGd_scale:
252 return "SCALE";
253 case ECPGd_type:
254 return "TYPE";
255 default:
256 return NULL;
260 void
261 output_set_descr(char *desc_name, char *index)
263 struct assignment *results;
265 fprintf(yyout, "{ ECPGset_desc(__LINE__, %s, %s,", desc_name, index);
266 for (results = assignments; results != NULL; results = results->next)
268 const struct variable *v = find_variable(results->variable);
270 switch (results->value)
272 case ECPGd_cardinality:
273 case ECPGd_di_code:
274 case ECPGd_di_precision:
275 case ECPGd_precision:
276 case ECPGd_scale:
277 mmerror(PARSE_ERROR, ET_FATAL, "descriptor item \"%s\" is not implemented",
278 descriptor_item_name(results->value));
279 break;
281 case ECPGd_key_member:
282 case ECPGd_name:
283 case ECPGd_nullable:
284 case ECPGd_octet:
285 case ECPGd_ret_length:
286 case ECPGd_ret_octet:
287 mmerror(PARSE_ERROR, ET_FATAL, "descriptor item \"%s\" cannot be set",
288 descriptor_item_name(results->value));
289 break;
291 case ECPGd_data:
292 case ECPGd_indicator:
293 case ECPGd_length:
294 case ECPGd_type:
295 fprintf(yyout, "%s,", get_dtype(results->value));
296 ECPGdump_a_type(yyout, v->name, v->type, NULL, NULL, NULL, NULL, make_str("0"), NULL, NULL);
297 break;
299 default:
303 drop_assignments();
304 fputs("ECPGd_EODT);\n", yyout);
306 whenever_action(2 | 1);
309 /* I consider dynamic allocation overkill since at most two descriptor
310 variables are possible per statement. (input and output descriptor)
311 And descriptors are no normal variables, so they don't belong into
312 the variable list.
315 #define MAX_DESCRIPTOR_NAMELEN 128
316 struct variable *
317 descriptor_variable(const char *name, int input)
319 static char descriptor_names[2][MAX_DESCRIPTOR_NAMELEN];
320 static const struct ECPGtype descriptor_type = {ECPGt_descriptor, NULL, NULL, {NULL}, 0};
321 static const struct variable varspace[2] = {
322 {descriptor_names[0], (struct ECPGtype *) & descriptor_type, 0, NULL},
323 {descriptor_names[1], (struct ECPGtype *) & descriptor_type, 0, NULL}
326 strlcpy(descriptor_names[input], name, sizeof(descriptor_names[input]));
327 return (struct variable *) & varspace[input];