Fix obsolete comment regarding FSM truncation.
[PostgreSQL.git] / src / interfaces / ecpg / preproc / type.c
blob961666372cec8cc88a6edaaa4acbf65fce2d8d1d
1 /* $PostgreSQL$ */
3 #include "postgres_fe.h"
5 #include "extern.h"
7 #define indicator_set ind_type != NULL && ind_type->type != ECPGt_NO_INDICATOR
9 static struct ECPGstruct_member struct_no_indicator = {"no_indicator", &ecpg_no_indicator, NULL};
11 /* malloc + error check */
12 void *
13 mm_alloc(size_t size)
15 void *ptr = malloc(size);
17 if (ptr == NULL)
18 mmerror(OUT_OF_MEMORY, ET_FATAL, "out of memory\n");
20 return ptr;
23 /* strdup + error check */
24 char *
25 mm_strdup(const char *string)
27 char *new = strdup(string);
29 if (new == NULL)
30 mmerror(OUT_OF_MEMORY, ET_FATAL, "out of memory\n");
32 return new;
35 /* duplicate memberlist */
36 struct ECPGstruct_member *
37 ECPGstruct_member_dup(struct ECPGstruct_member * rm)
39 struct ECPGstruct_member *new = NULL;
41 while (rm)
43 struct ECPGtype *type;
45 switch (rm->type->type)
47 case ECPGt_struct:
48 case ECPGt_union:
49 type = ECPGmake_struct_type(rm->type->u.members, rm->type->type, rm->type->struct_sizeof);
50 break;
51 case ECPGt_array:
54 * if this array does contain a struct again, we have to
55 * create the struct too
57 if (rm->type->u.element->type == ECPGt_struct)
58 type = ECPGmake_struct_type(rm->type->u.element->u.members, rm->type->u.element->type, rm->type->u.element->struct_sizeof);
59 else
60 type = ECPGmake_array_type(ECPGmake_simple_type(rm->type->u.element->type, rm->type->u.element->size, rm->type->u.element->lineno), rm->type->size);
61 break;
62 default:
63 type = ECPGmake_simple_type(rm->type->type, rm->type->size, rm->type->lineno);
64 break;
67 ECPGmake_struct_member(rm->name, type, &new);
69 rm = rm->next;
72 return (new);
75 /* The NAME argument is copied. The type argument is preserved as a pointer. */
76 void
77 ECPGmake_struct_member(char *name, struct ECPGtype * type, struct ECPGstruct_member ** start)
79 struct ECPGstruct_member *ptr,
80 *ne =
81 (struct ECPGstruct_member *) mm_alloc(sizeof(struct ECPGstruct_member));
83 ne->name = mm_strdup(name);
84 ne->type = type;
85 ne->next = NULL;
87 for (ptr = *start; ptr && ptr->next; ptr = ptr->next);
89 if (ptr)
90 ptr->next = ne;
91 else
92 *start = ne;
95 struct ECPGtype *
96 ECPGmake_simple_type(enum ECPGttype type, char *size, int lineno)
98 struct ECPGtype *ne = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype));
100 ne->type = type;
101 ne->size = size;
102 ne->u.element = NULL;
103 ne->struct_sizeof = NULL;
104 ne->lineno = lineno; /* only needed for varchar */
106 return ne;
109 struct ECPGtype *
110 ECPGmake_array_type(struct ECPGtype * type, char *size)
112 struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_array, size, 0);
114 ne->u.element = type;
116 return ne;
119 struct ECPGtype *
120 ECPGmake_struct_type(struct ECPGstruct_member * rm, enum ECPGttype type, char *struct_sizeof)
122 struct ECPGtype *ne = ECPGmake_simple_type(type, make_str("1"), 0);
124 ne->u.members = ECPGstruct_member_dup(rm);
125 ne->struct_sizeof = struct_sizeof;
127 return ne;
130 static const char *
131 get_type(enum ECPGttype type)
133 switch (type)
135 case ECPGt_char:
136 return ("ECPGt_char");
137 break;
138 case ECPGt_unsigned_char:
139 return ("ECPGt_unsigned_char");
140 break;
141 case ECPGt_short:
142 return ("ECPGt_short");
143 break;
144 case ECPGt_unsigned_short:
145 return ("ECPGt_unsigned_short");
146 break;
147 case ECPGt_int:
148 return ("ECPGt_int");
149 break;
150 case ECPGt_unsigned_int:
151 return ("ECPGt_unsigned_int");
152 break;
153 case ECPGt_long:
154 return ("ECPGt_long");
155 break;
156 case ECPGt_unsigned_long:
157 return ("ECPGt_unsigned_long");
158 break;
159 case ECPGt_long_long:
160 return ("ECPGt_long_long");
161 break;
162 case ECPGt_unsigned_long_long:
163 return ("ECPGt_unsigned_long_long");
164 break;
165 case ECPGt_float:
166 return ("ECPGt_float");
167 break;
168 case ECPGt_double:
169 return ("ECPGt_double");
170 break;
171 case ECPGt_bool:
172 return ("ECPGt_bool");
173 break;
174 case ECPGt_varchar:
175 return ("ECPGt_varchar");
176 case ECPGt_NO_INDICATOR: /* no indicator */
177 return ("ECPGt_NO_INDICATOR");
178 break;
179 case ECPGt_char_variable: /* string that should not be quoted */
180 return ("ECPGt_char_variable");
181 break;
182 case ECPGt_const: /* constant string quoted */
183 return ("ECPGt_const");
184 break;
185 case ECPGt_decimal:
186 return ("ECPGt_decimal");
187 break;
188 case ECPGt_numeric:
189 return ("ECPGt_numeric");
190 break;
191 case ECPGt_interval:
192 return ("ECPGt_interval");
193 break;
194 case ECPGt_descriptor:
195 return ("ECPGt_descriptor");
196 break;
197 case ECPGt_date:
198 return ("ECPGt_date");
199 break;
200 case ECPGt_timestamp:
201 return ("ECPGt_timestamp");
202 break;
203 default:
204 mmerror(PARSE_ERROR, ET_ERROR, "illegal variable type %d\n", type);
207 return NULL;
210 /* Dump a type.
211 The type is dumped as:
212 type-tag <comma> - enum ECPGttype
213 reference-to-variable <comma> - char *
214 size <comma> - long size of this field (if varchar)
215 arrsize <comma> - long number of elements in the arr
216 offset <comma> - offset to the next element
217 Where:
218 type-tag is one of the simple types or varchar.
219 reference-to-variable can be a reference to a struct element.
220 arrsize is the size of the array in case of array fetches. Otherwise 0.
221 size is the maxsize in case it is a varchar. Otherwise it is the size of
222 the variable (required to do array fetches of structs).
224 static void ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type,
225 char *varcharsize,
226 char *arrsiz, const char *siz, const char *prefix, int);
227 static void ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, char *arrsiz,
228 struct ECPGtype * type, struct ECPGtype * ind_type, const char *offset, const char *prefix, const char *ind_prefix);
230 void
231 ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * type,
232 const char *ind_name, struct ECPGtype * ind_type,
233 const char *prefix, const char *ind_prefix,
234 char *arr_str_siz, const char *struct_sizeof,
235 const char *ind_struct_sizeof)
237 switch (type->type)
239 case ECPGt_array:
240 if (indicator_set && ind_type->type != ECPGt_array)
241 mmerror(INDICATOR_NOT_ARRAY, ET_FATAL, "indicator for array/pointer has to be array/pointer\n");
242 switch (type->u.element->type)
244 case ECPGt_array:
245 mmerror(PARSE_ERROR, ET_ERROR, "no nested arrays allowed (except strings)"); /* array of array */
246 break;
247 case ECPGt_struct:
248 case ECPGt_union:
249 ECPGdump_a_struct(o, name,
250 ind_name,
251 type->size,
252 type->u.element,
253 (ind_type == NULL) ? NULL : ((ind_type->type == ECPGt_NO_INDICATOR) ? ind_type : ind_type->u.element),
254 NULL, prefix, ind_prefix);
255 break;
256 default:
257 if (!IS_SIMPLE_TYPE(type->u.element->type))
258 base_yyerror("internal error: unknown datatype, please report this to <pgsql-bugs@postgresql.org>");
260 ECPGdump_a_simple(o, name,
261 type->u.element->type,
262 type->u.element->size, type->size, NULL, prefix, type->u.element->lineno);
264 if (ind_type != NULL)
266 if (ind_type->type == ECPGt_NO_INDICATOR)
267 ECPGdump_a_simple(o, ind_name, ind_type->type, ind_type->size, make_str("-1"), NULL, ind_prefix, 0);
268 else
270 ECPGdump_a_simple(o, ind_name, ind_type->u.element->type,
271 ind_type->u.element->size, ind_type->size, NULL, ind_prefix, 0);
275 break;
276 case ECPGt_struct:
277 if (indicator_set && ind_type->type != ECPGt_struct)
278 mmerror(INDICATOR_NOT_STRUCT, ET_FATAL, "indicator for struct has to be struct\n");
280 ECPGdump_a_struct(o, name, ind_name, make_str("1"), type, ind_type, NULL, prefix, ind_prefix);
281 break;
282 case ECPGt_union: /* cannot dump a complete union */
283 base_yyerror("type of union has to be specified");
284 break;
285 case ECPGt_char_variable:
286 if (indicator_set && (ind_type->type == ECPGt_struct || ind_type->type == ECPGt_array))
287 mmerror(INDICATOR_NOT_SIMPLE, ET_FATAL, "indicator for simple datatype has to be simple\n");
289 ECPGdump_a_simple(o, name, type->type, make_str("1"), (arr_str_siz && strcmp(arr_str_siz, "0") != 0) ? arr_str_siz : make_str("1"), struct_sizeof, prefix, 0);
290 if (ind_type != NULL)
291 ECPGdump_a_simple(o, ind_name, ind_type->type, ind_type->size, (arr_str_siz && strcmp(arr_str_siz, "0") != 0) ? arr_str_siz : make_str("-1"), ind_struct_sizeof, ind_prefix, 0);
292 break;
293 case ECPGt_descriptor:
294 if (indicator_set && (ind_type->type == ECPGt_struct || ind_type->type == ECPGt_array))
295 mmerror(INDICATOR_NOT_SIMPLE, ET_FATAL, "indicator for simple datatype has to be simple\n");
297 ECPGdump_a_simple(o, name, type->type, NULL, make_str("-1"), NULL, prefix, 0);
298 if (ind_type != NULL)
299 ECPGdump_a_simple(o, ind_name, ind_type->type, ind_type->size, make_str("-1"), NULL, ind_prefix, 0);
300 break;
301 default:
302 if (indicator_set && (ind_type->type == ECPGt_struct || ind_type->type == ECPGt_array))
303 mmerror(INDICATOR_NOT_SIMPLE, ET_FATAL, "indicator for simple datatype has to be simple\n");
305 ECPGdump_a_simple(o, name, type->type, type->size, (arr_str_siz && strcmp(arr_str_siz, "0") != 0) ? arr_str_siz : make_str("-1"), struct_sizeof, prefix, type->lineno);
306 if (ind_type != NULL)
307 ECPGdump_a_simple(o, ind_name, ind_type->type, ind_type->size, (arr_str_siz && strcmp(arr_str_siz, "0") != 0) ? arr_str_siz : make_str("-1"), ind_struct_sizeof, ind_prefix, 0);
308 break;
313 /* If siz is NULL, then the offset is 0, if not use siz as a
314 string, it represents the offset needed if we are in an array of structs. */
315 static void
316 ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type,
317 char *varcharsize,
318 char *arrsize,
319 const char *siz,
320 const char *prefix,
321 int lineno)
323 if (type == ECPGt_NO_INDICATOR)
324 fprintf(o, "\n\tECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ");
325 else if (type == ECPGt_descriptor)
326 /* remember that name here already contains quotes (if needed) */
327 fprintf(o, "\n\tECPGt_descriptor, %s, 0L, 0L, 0L, ", name);
328 else
330 char *variable = (char *) mm_alloc(strlen(name) + ((prefix == NULL) ? 0 : strlen(prefix)) + 4);
331 char *offset = (char *) mm_alloc(strlen(name) + strlen("sizeof(struct varchar_)") + 1 + strlen(varcharsize) + sizeof(int) * CHAR_BIT * 10 / 3);
332 char *var_name, *ptr;
334 switch (type)
337 * we have to use the & operator except for arrays and
338 * pointers
341 case ECPGt_varchar:
344 * we have to use the pointer except for arrays with given
345 * bounds
347 if (((atoi(arrsize) > 0) ||
348 (atoi(arrsize) == 0 && strcmp(arrsize, "0") != 0)) &&
349 siz == NULL)
350 sprintf(variable, "(%s%s)", prefix ? prefix : "", name);
351 else
352 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
354 /* remove trailing [] is name is array element */
355 var_name = mm_strdup(name);
356 ptr = strchr(var_name, '[');
357 if (ptr) *ptr = '\0';
358 if (lineno)
359 sprintf(offset, "sizeof(struct varchar_%s_%d)", var_name, lineno);
360 else
361 sprintf(offset, "sizeof(struct varchar_%s)", var_name);
362 free(var_name);
363 break;
364 case ECPGt_char:
365 case ECPGt_unsigned_char:
366 case ECPGt_char_variable:
369 * we have to use the pointer except for arrays with given
370 * bounds, ecpglib will distinguish between * and []
372 if ((atoi(varcharsize) > 1 ||
373 (atoi(arrsize) > 0) ||
374 (atoi(varcharsize) == 0 && strcmp(varcharsize, "0") != 0) ||
375 (atoi(arrsize) == 0 && strcmp(arrsize, "0") != 0))
376 && siz == NULL)
377 sprintf(variable, "(%s%s)", prefix ? prefix : "", name);
378 else
379 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
381 sprintf(offset, "(%s)*sizeof(char)", strcmp(varcharsize, "0") == 0 ? "1" : varcharsize);
382 break;
383 case ECPGt_numeric:
386 * we have to use a pointer here
388 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
389 sprintf(offset, "sizeof(numeric)");
390 break;
391 case ECPGt_interval:
394 * we have to use a pointer here
396 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
397 sprintf(offset, "sizeof(interval)");
398 break;
399 case ECPGt_date:
402 * we have to use a pointer and translate the variable type
404 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
405 sprintf(offset, "sizeof(date)");
406 break;
407 case ECPGt_timestamp:
410 * we have to use a pointer and translate the variable type
412 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
413 sprintf(offset, "sizeof(timestamp)");
414 break;
415 case ECPGt_const:
418 * just dump the const as string
420 sprintf(variable, "\"%s\"", name);
421 sprintf(offset, "strlen(\"%s\")", name);
422 break;
423 default:
426 * we have to use the pointer except for arrays with given
427 * bounds
429 if (((atoi(arrsize) > 0) ||
430 (atoi(arrsize) == 0 && strcmp(arrsize, "0") != 0)) &&
431 siz == NULL)
432 sprintf(variable, "(%s%s)", prefix ? prefix : "", name);
433 else
434 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
436 sprintf(offset, "sizeof(%s)", ecpg_type_name(type));
437 break;
440 if (atoi(arrsize) < 0)
441 strcpy(arrsize, "1");
443 if (siz == NULL || strlen(siz) == 0 || strcmp(arrsize, "0") == 0 || strcmp(arrsize, "1") == 0)
444 fprintf(o, "\n\t%s,%s,(long)%s,(long)%s,%s, ", get_type(type), variable, varcharsize, arrsize, offset);
445 else
446 fprintf(o, "\n\t%s,%s,(long)%s,(long)%s,%s, ", get_type(type), variable, varcharsize, arrsize, siz);
448 free(variable);
449 free(offset);
454 /* Penetrate a struct and dump the contents. */
455 static void
456 ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, char *arrsiz, struct ECPGtype * type, struct ECPGtype * ind_type, const char *offsetarg, const char *prefix, const char *ind_prefix)
459 * If offset is NULL, then this is the first recursive level. If not then
460 * we are in a struct in a struct and the offset is used as offset.
462 struct ECPGstruct_member *p,
463 *ind_p = NULL;
464 char obuf[BUFSIZ];
465 char pbuf[BUFSIZ],
466 ind_pbuf[BUFSIZ];
467 const char *offset;
469 if (offsetarg == NULL)
471 sprintf(obuf, "sizeof(%s)", name);
472 offset = obuf;
474 else
475 offset = offsetarg;
477 if (atoi(arrsiz) == 1)
478 sprintf(pbuf, "%s%s.", prefix ? prefix : "", name);
479 else
480 sprintf(pbuf, "%s%s->", prefix ? prefix : "", name);
482 prefix = pbuf;
484 if (ind_type == &ecpg_no_indicator)
485 ind_p = &struct_no_indicator;
486 else if (ind_type != NULL)
488 if (atoi(arrsiz) == 1)
489 sprintf(ind_pbuf, "%s%s.", ind_prefix ? ind_prefix : "", ind_name);
490 else
491 sprintf(ind_pbuf, "%s%s->", ind_prefix ? ind_prefix : "", ind_name);
493 ind_prefix = ind_pbuf;
494 ind_p = ind_type->u.members;
497 for (p = type->u.members; p; p = p->next)
499 ECPGdump_a_type(o, p->name, p->type,
500 (ind_p != NULL) ? ind_p->name : NULL,
501 (ind_p != NULL) ? ind_p->type : NULL,
502 prefix, ind_prefix, arrsiz, type->struct_sizeof,
503 (ind_p != NULL) ? ind_type->struct_sizeof : NULL);
504 if (ind_p != NULL && ind_p != &struct_no_indicator)
505 ind_p = ind_p->next;
509 void
510 ECPGfree_struct_member(struct ECPGstruct_member * rm)
512 while (rm)
514 struct ECPGstruct_member *p = rm;
516 rm = rm->next;
517 free(p->name);
518 free(p->type);
519 free(p);
523 void
524 ECPGfree_type(struct ECPGtype * type)
526 if (!IS_SIMPLE_TYPE(type->type))
528 switch (type->type)
530 case ECPGt_array:
531 switch (type->u.element->type)
533 case ECPGt_array:
534 base_yyerror("internal error: found multidimensional array\n");
535 break;
536 case ECPGt_struct:
537 case ECPGt_union:
538 /* Array of structs. */
539 ECPGfree_struct_member(type->u.element->u.members);
540 free(type->u.element);
541 break;
542 default:
543 if (!IS_SIMPLE_TYPE(type->u.element->type))
544 base_yyerror("internal error: unknown datatype, please report this to <pgsql-bugs@postgresql.org>");
546 free(type->u.element);
548 break;
549 case ECPGt_struct:
550 case ECPGt_union:
551 ECPGfree_struct_member(type->u.members);
552 break;
553 default:
554 mmerror(PARSE_ERROR, ET_ERROR, "illegal variable type %d\n", type->type);
555 break;
558 free(type);
561 const char *
562 get_dtype(enum ECPGdtype type)
564 switch (type)
566 case ECPGd_count:
567 return ("ECPGd_countr");
568 break;
569 case ECPGd_data:
570 return ("ECPGd_data");
571 break;
572 case ECPGd_di_code:
573 return ("ECPGd_di_code");
574 break;
575 case ECPGd_di_precision:
576 return ("ECPGd_di_precision");
577 break;
578 case ECPGd_indicator:
579 return ("ECPGd_indicator");
580 break;
581 case ECPGd_key_member:
582 return ("ECPGd_key_member");
583 break;
584 case ECPGd_length:
585 return ("ECPGd_length");
586 break;
587 case ECPGd_name:
588 return ("ECPGd_name");
589 break;
590 case ECPGd_nullable:
591 return ("ECPGd_nullable");
592 break;
593 case ECPGd_octet:
594 return ("ECPGd_octet");
595 break;
596 case ECPGd_precision:
597 return ("ECPGd_precision");
598 break;
599 case ECPGd_ret_length:
600 return ("ECPGd_ret_length");
601 case ECPGd_ret_octet:
602 return ("ECPGd_ret_octet");
603 break;
604 case ECPGd_scale:
605 return ("ECPGd_scale");
606 break;
607 case ECPGd_type:
608 return ("ECPGd_type");
609 break;
610 case ECPGd_cardinality:
611 return ("ECPGd_cardinality");
612 default:
613 mmerror(PARSE_ERROR, ET_ERROR, "illegal descriptor item %d\n", type);
616 return NULL;