1/* src/interfaces/ecpg/preproc/type.c */
2
3#include "postgres_fe.h"
4
5#include "preproc_extern.h"
6
7#define indicator_set ind_type != NULL && ind_type->type != ECPGt_NO_INDICATOR
8
9static struct ECPGstruct_member struct_no_indicator = {"no_indicator", &ecpg_no_indicator, NULL};
10
11/* malloc + error check */
12void *
13mm_alloc(size_t size)
14{
15 void *ptr = malloc(size);
16
17 if (ptr == NULL)
18 mmfatal(OUT_OF_MEMORY, "out of memory");
19
20 return ptr;
21}
22
23/* strdup + error check */
24char *
25mm_strdup(const char *string)
26{
27 char *new = strdup(string);
28
29 if (new == NULL)
30 mmfatal(OUT_OF_MEMORY, "out of memory");
31
32 return new;
33}
34
35/* duplicate memberlist */
36struct ECPGstruct_member *
37ECPGstruct_member_dup(struct ECPGstruct_member *rm)
38{
39 struct ECPGstruct_member *new = NULL;
40
41 while (rm)
42 {
43 struct ECPGtype *type;
44
45 switch (rm->type->type)
46 {
47 case ECPGt_struct:
48 case ECPGt_union:
49 type = ECPGmake_struct_type(rm->type->u.members, rm->type->type, rm->type->type_name, rm->type->struct_sizeof);
50 break;
51 case ECPGt_array:
52
53 /*
54 * if this array does contain a struct again, we have to
55 * create the struct too
56 */
57 if (rm->type->u.element->type == ECPGt_struct || rm->type->u.element->type == ECPGt_union)
58 type = ECPGmake_struct_type(rm->type->u.element->u.members, rm->type->u.element->type, rm->type->u.element->type_name, 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->counter), rm->type->size);
61 break;
62 default:
63 type = ECPGmake_simple_type(rm->type->type, rm->type->size, rm->type->counter);
64 break;
65 }
66
67 ECPGmake_struct_member(rm->name, type, &new);
68
69 rm = rm->next;
70 }
71
72 return new;
73}
74
75/* The NAME argument is copied. The type argument is preserved as a pointer. */
76void
77ECPGmake_struct_member(const char *name, struct ECPGtype *type, struct ECPGstruct_member **start)
78{
79 struct ECPGstruct_member *ptr,
80 *ne =
81 (struct ECPGstruct_member *) mm_alloc(sizeof(struct ECPGstruct_member));
82
83 ne->name = mm_strdup(name);
84 ne->type = type;
85 ne->next = NULL;
86
87 for (ptr = *start; ptr && ptr->next; ptr = ptr->next);
88
89 if (ptr)
90 ptr->next = ne;
91 else
92 *start = ne;
93}
94
95struct ECPGtype *
96ECPGmake_simple_type(enum ECPGttype type, char *size, int counter)
97{
98 struct ECPGtype *ne = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype));
99
100 ne->type = type;
101 ne->type_name = NULL;
102 ne->size = size;
103 ne->u.element = NULL;
104 ne->struct_sizeof = NULL;
105 ne->counter = counter; /* only needed for varchar and bytea */
106
107 return ne;
108}
109
110struct ECPGtype *
111ECPGmake_array_type(struct ECPGtype *type, char *size)
112{
113 struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_array, size, 0);
114
115 ne->u.element = type;
116
117 return ne;
118}
119
120struct ECPGtype *
121ECPGmake_struct_type(struct ECPGstruct_member *rm, enum ECPGttype type, char *type_name, char *struct_sizeof)
122{
123 struct ECPGtype *ne = ECPGmake_simple_type(type, mm_strdup("1"), 0);
124
125 ne->type_name = mm_strdup(type_name);
126 ne->u.members = ECPGstruct_member_dup(rm);
127 ne->struct_sizeof = struct_sizeof;
128
129 return ne;
130}
131
132static const char *
133get_type(enum ECPGttype type)
134{
135 switch (type)
136 {
137 case ECPGt_char:
138 return "ECPGt_char";
139 break;
140 case ECPGt_unsigned_char:
141 return "ECPGt_unsigned_char";
142 break;
143 case ECPGt_short:
144 return "ECPGt_short";
145 break;
146 case ECPGt_unsigned_short:
147 return "ECPGt_unsigned_short";
148 break;
149 case ECPGt_int:
150 return "ECPGt_int";
151 break;
152 case ECPGt_unsigned_int:
153 return "ECPGt_unsigned_int";
154 break;
155 case ECPGt_long:
156 return "ECPGt_long";
157 break;
158 case ECPGt_unsigned_long:
159 return "ECPGt_unsigned_long";
160 break;
161 case ECPGt_long_long:
162 return "ECPGt_long_long";
163 break;
164 case ECPGt_unsigned_long_long:
165 return "ECPGt_unsigned_long_long";
166 break;
167 case ECPGt_float:
168 return "ECPGt_float";
169 break;
170 case ECPGt_double:
171 return "ECPGt_double";
172 break;
173 case ECPGt_bool:
174 return "ECPGt_bool";
175 break;
176 case ECPGt_varchar:
177 return "ECPGt_varchar";
178 case ECPGt_bytea:
179 return "ECPGt_bytea";
180 case ECPGt_NO_INDICATOR: /* no indicator */
181 return "ECPGt_NO_INDICATOR";
182 break;
183 case ECPGt_char_variable: /* string that should not be quoted */
184 return "ECPGt_char_variable";
185 break;
186 case ECPGt_const: /* constant string quoted */
187 return "ECPGt_const";
188 break;
189 case ECPGt_decimal:
190 return "ECPGt_decimal";
191 break;
192 case ECPGt_numeric:
193 return "ECPGt_numeric";
194 break;
195 case ECPGt_interval:
196 return "ECPGt_interval";
197 break;
198 case ECPGt_descriptor:
199 return "ECPGt_descriptor";
200 break;
201 case ECPGt_sqlda:
202 return "ECPGt_sqlda";
203 break;
204 case ECPGt_date:
205 return "ECPGt_date";
206 break;
207 case ECPGt_timestamp:
208 return "ECPGt_timestamp";
209 break;
210 case ECPGt_string:
211 return "ECPGt_string";
212 break;
213 default:
214 mmerror(PARSE_ERROR, ET_ERROR, "unrecognized variable type code %d", type);
215 }
216
217 return NULL;
218}
219
220/* Dump a type.
221 The type is dumped as:
222 type-tag <comma> - enum ECPGttype
223 reference-to-variable <comma> - char *
224 size <comma> - long size of this field (if varchar)
225 arrsize <comma> - long number of elements in the arr
226 offset <comma> - offset to the next element
227 Where:
228 type-tag is one of the simple types or varchar.
229 reference-to-variable can be a reference to a struct element.
230 arrsize is the size of the array in case of array fetches. Otherwise 0.
231 size is the maxsize in case it is a varchar. Otherwise it is the size of
232 the variable (required to do array fetches of structs).
233 */
234static void ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type,
235 char *varcharsize,
236 char *arrsize, const char *size, const char *prefix, int);
237static void ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, char *arrsize,
238 struct ECPGtype *type, struct ECPGtype *ind_type, const char *prefix, const char *ind_prefix);
239
240void
241ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype *type, const int brace_level,
242 const char *ind_name, struct ECPGtype *ind_type, const int ind_brace_level,
243 const char *prefix, const char *ind_prefix,
244 char *arr_str_size, const char *struct_sizeof,
245 const char *ind_struct_sizeof)
246{
247 struct variable *var;
248
249 if (type->type != ECPGt_descriptor && type->type != ECPGt_sqlda &&
250 type->type != ECPGt_char_variable && type->type != ECPGt_const &&
251 brace_level >= 0)
252 {
253 char *str;
254
255 str = mm_strdup(name);
256 var = find_variable(str);
257 free(str);
258
259 if ((var->type->type != type->type) ||
260 (var->type->type_name && !type->type_name) ||
261 (!var->type->type_name && type->type_name) ||
262 (var->type->type_name && type->type_name && strcmp(var->type->type_name, type->type_name) != 0))
263 mmerror(PARSE_ERROR, ET_ERROR, "variable \"%s\" is hidden by a local variable of a different type", name);
264 else if (var->brace_level != brace_level)
265 mmerror(PARSE_ERROR, ET_WARNING, "variable \"%s\" is hidden by a local variable", name);
266
267 if (ind_name && ind_type && ind_type->type != ECPGt_NO_INDICATOR && ind_brace_level >= 0)
268 {
269 str = mm_strdup(ind_name);
270 var = find_variable(str);
271 free(str);
272
273 if ((var->type->type != ind_type->type) ||
274 (var->type->type_name && !ind_type->type_name) ||
275 (!var->type->type_name && ind_type->type_name) ||
276 (var->type->type_name && ind_type->type_name && strcmp(var->type->type_name, ind_type->type_name) != 0))
277 mmerror(PARSE_ERROR, ET_ERROR, "indicator variable \"%s\" is hidden by a local variable of a different type", ind_name);
278 else if (var->brace_level != ind_brace_level)
279 mmerror(PARSE_ERROR, ET_WARNING, "indicator variable \"%s\" is hidden by a local variable", ind_name);
280 }
281 }
282
283 switch (type->type)
284 {
285 case ECPGt_array:
286 if (indicator_set && ind_type->type != ECPGt_array)
287 mmfatal(INDICATOR_NOT_ARRAY, "indicator for array/pointer has to be array/pointer");
288 switch (type->u.element->type)
289 {
290 case ECPGt_array:
291 mmerror(PARSE_ERROR, ET_ERROR, "nested arrays are not supported (except strings)"); /* array of array */
292 break;
293 case ECPGt_struct:
294 case ECPGt_union:
295 ECPGdump_a_struct(o, name,
296 ind_name,
297 type->size,
298 type->u.element,
299 (ind_type == NULL) ? NULL : ((ind_type->type == ECPGt_NO_INDICATOR) ? ind_type : ind_type->u.element),
300 prefix, ind_prefix);
301 break;
302 default:
303 if (!IS_SIMPLE_TYPE(type->u.element->type))
304 base_yyerror("internal error: unknown datatype, please report this to <pgsql-bugs@lists.postgresql.org>");
305
306 ECPGdump_a_simple(o, name,
307 type->u.element->type,
308 type->u.element->size, type->size, struct_sizeof ? struct_sizeof : NULL,
309 prefix, type->u.element->counter);
310
311 if (ind_type != NULL)
312 {
313 if (ind_type->type == ECPGt_NO_INDICATOR)
314 {
315 char *str_neg_one = mm_strdup("-1");
316
317 ECPGdump_a_simple(o, ind_name, ind_type->type, ind_type->size, str_neg_one, NULL, ind_prefix, 0);
318 free(str_neg_one);
319 }
320 else
321 {
322 ECPGdump_a_simple(o, ind_name, ind_type->u.element->type,
323 ind_type->u.element->size, ind_type->size, NULL, ind_prefix, 0);
324 }
325 }
326 }
327 break;
328 case ECPGt_struct:
329 {
330 char *str_one = mm_strdup("1");
331
332 if (indicator_set && ind_type->type != ECPGt_struct)
333 mmfatal(INDICATOR_NOT_STRUCT, "indicator for struct has to be a struct");
334
335 ECPGdump_a_struct(o, name, ind_name, str_one, type, ind_type, prefix, ind_prefix);
336 free(str_one);
337 }
338 break;
339 case ECPGt_union: /* cannot dump a complete union */
340 base_yyerror("type of union has to be specified");
341 break;
342 case ECPGt_char_variable:
343 {
344 /*
345 * Allocate for each, as there are code-paths where the values
346 * get stomped on.
347 */
348 char *str_varchar_one = mm_strdup("1");
349 char *str_arr_one = mm_strdup("1");
350 char *str_neg_one = mm_strdup("-1");
351
352 if (indicator_set && (ind_type->type == ECPGt_struct || ind_type->type == ECPGt_array))
353 mmfatal(INDICATOR_NOT_SIMPLE, "indicator for simple data type has to be simple");
354
355 ECPGdump_a_simple(o, name, type->type, str_varchar_one, (arr_str_size && strcmp(arr_str_size, "0") != 0) ? arr_str_size : str_arr_one, struct_sizeof, prefix, 0);
356 if (ind_type != NULL)
357 ECPGdump_a_simple(o, ind_name, ind_type->type, ind_type->size, (arr_str_size && strcmp(arr_str_size, "0") != 0) ? arr_str_size : str_neg_one, ind_struct_sizeof, ind_prefix, 0);
358
359 free(str_varchar_one);
360 free(str_arr_one);
361 free(str_neg_one);
362 }
363 break;
364 case ECPGt_descriptor:
365 {
366 /*
367 * Allocate for each, as there are code-paths where the values
368 * get stomped on.
369 */
370 char *str_neg_one = mm_strdup("-1");
371 char *ind_type_neg_one = mm_strdup("-1");
372
373 if (indicator_set && (ind_type->type == ECPGt_struct || ind_type->type == ECPGt_array))
374 mmfatal(INDICATOR_NOT_SIMPLE, "indicator for simple data type has to be simple");
375
376 ECPGdump_a_simple(o, name, type->type, NULL, str_neg_one, NULL, prefix, 0);
377 if (ind_type != NULL)
378 ECPGdump_a_simple(o, ind_name, ind_type->type, ind_type->size, ind_type_neg_one, NULL, ind_prefix, 0);
379
380 free(str_neg_one);
381 free(ind_type_neg_one);
382 }
383 break;
384 default:
385 {
386 /*
387 * Allocate for each, as there are code-paths where the values
388 * get stomped on.
389 */
390 char *str_neg_one = mm_strdup("-1");
391 char *ind_type_neg_one = mm_strdup("-1");
392
393 if (indicator_set && (ind_type->type == ECPGt_struct || ind_type->type == ECPGt_array))
394 mmfatal(INDICATOR_NOT_SIMPLE, "indicator for simple data type has to be simple");
395
396 ECPGdump_a_simple(o, name, type->type, type->size, (arr_str_size && strcmp(arr_str_size, "0") != 0) ? arr_str_size : str_neg_one, struct_sizeof, prefix, type->counter);
397 if (ind_type != NULL)
398 ECPGdump_a_simple(o, ind_name, ind_type->type, ind_type->size, (arr_str_size && strcmp(arr_str_size, "0") != 0) ? arr_str_size : ind_type_neg_one, ind_struct_sizeof, ind_prefix, 0);
399
400 free(str_neg_one);
401 free(ind_type_neg_one);
402 }
403 break;
404 }
405}
406
407
408/* If size is NULL, then the offset is 0, if not use size as a
409 string, it represents the offset needed if we are in an array of structs. */
410static void
411ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type,
412 char *varcharsize,
413 char *arrsize,
414 const char *size,
415 const char *prefix,
416 int counter)
417{
418 if (type == ECPGt_NO_INDICATOR)
419 fprintf(o, "\n\tECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ");
420 else if (type == ECPGt_descriptor)
421 /* remember that name here already contains quotes (if needed) */
422 fprintf(o, "\n\tECPGt_descriptor, %s, 1L, 1L, 1L, ", name);
423 else if (type == ECPGt_sqlda)
424 fprintf(o, "\n\tECPGt_sqlda, &%s, 0L, 0L, 0L, ", name);
425 else
426 {
427 char *variable = (char *) mm_alloc(strlen(name) + ((prefix == NULL) ? 0 : strlen(prefix)) + 4);
428 char *offset = (char *) mm_alloc(strlen(name) + strlen("sizeof(struct varchar_)") + 1 + strlen(varcharsize) + sizeof(int) * CHAR_BIT * 10 / 3);
429 char *struct_name;
430
431 switch (type)
432 {
433 /*
434 * we have to use the & operator except for arrays and
435 * pointers
436 */
437
438 case ECPGt_varchar:
439 case ECPGt_bytea:
440
441 /*
442 * we have to use the pointer except for arrays with given
443 * bounds
444 */
445 if (((atoi(arrsize) > 0) ||
446 (atoi(arrsize) == 0 && strcmp(arrsize, "0") != 0)) &&
447 size == NULL)
448 sprintf(variable, "(%s%s)", prefix ? prefix : "", name);
449 else
450 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
451
452 /*
453 * If we created a varchar structure automatically, counter is
454 * greater than 0.
455 */
456 if (type == ECPGt_varchar)
457 struct_name = "struct varchar";
458 else
459 struct_name = "struct bytea";
460
461 if (counter)
462 sprintf(offset, "sizeof(%s_%d)", struct_name, counter);
463 else
464 sprintf(offset, "sizeof(%s)", struct_name);
465 break;
466 case ECPGt_char:
467 case ECPGt_unsigned_char:
468 case ECPGt_char_variable:
469 case ECPGt_string:
470 {
471 char *sizeof_name = "char";
472
473 /*
474 * we have to use the pointer except for arrays with given
475 * bounds, ecpglib will distinguish between * and []
476 */
477 if ((atoi(varcharsize) > 1 ||
478 (atoi(arrsize) > 0) ||
479 (atoi(varcharsize) == 0 && strcmp(varcharsize, "0") != 0) ||
480 (atoi(arrsize) == 0 && strcmp(arrsize, "0") != 0))
481 && size == NULL)
482 {
483 sprintf(variable, "(%s%s)", prefix ? prefix : "", name);
484 if ((type == ECPGt_char || type == ECPGt_unsigned_char) &&
485 strcmp(varcharsize, "0") == 0)
486 {
487 /*
488 * If this is an array of char *, the offset would
489 * be sizeof(char *) and not sizeof(char).
490 */
491 sizeof_name = "char *";
492 }
493 }
494 else
495 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
496
497 sprintf(offset, "(%s)*sizeof(%s)", strcmp(varcharsize, "0") == 0 ? "1" : varcharsize, sizeof_name);
498 break;
499 }
500 case ECPGt_numeric:
501
502 /*
503 * we have to use a pointer here
504 */
505 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
506 sprintf(offset, "sizeof(numeric)");
507 break;
508 case ECPGt_interval:
509
510 /*
511 * we have to use a pointer here
512 */
513 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
514 sprintf(offset, "sizeof(interval)");
515 break;
516 case ECPGt_date:
517
518 /*
519 * we have to use a pointer and translate the variable type
520 */
521 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
522 sprintf(offset, "sizeof(date)");
523 break;
524 case ECPGt_timestamp:
525
526 /*
527 * we have to use a pointer and translate the variable type
528 */
529 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
530 sprintf(offset, "sizeof(timestamp)");
531 break;
532 case ECPGt_const:
533
534 /*
535 * just dump the const as string
536 */
537 sprintf(variable, "\"%s\"", name);
538 sprintf(offset, "strlen(\"%s\")", name);
539 break;
540 default:
541
542 /*
543 * we have to use the pointer except for arrays with given
544 * bounds
545 */
546 if (((atoi(arrsize) > 0) ||
547 (atoi(arrsize) == 0 && strcmp(arrsize, "0") != 0)) &&
548 size == NULL)
549 sprintf(variable, "(%s%s)", prefix ? prefix : "", name);
550 else
551 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
552
553 sprintf(offset, "sizeof(%s)", ecpg_type_name(type));
554 break;
555 }
556
557 /*
558 * Array size would be -1 for addresses of members within structure,
559 * when pointer to structure is being dumped.
560 */
561 if (atoi(arrsize) < 0 && !size)
562 strcpy(arrsize, "1");
563
564 /*
565 * If size i.e. the size of structure of which this variable is part
566 * of, that gives the offset to the next element, if required
567 */
568 if (size == NULL || strlen(size) == 0)
569 fprintf(o, "\n\t%s,%s,(long)%s,(long)%s,%s, ", get_type(type), variable, varcharsize, arrsize, offset);
570 else
571 fprintf(o, "\n\t%s,%s,(long)%s,(long)%s,%s, ", get_type(type), variable, varcharsize, arrsize, size);
572
573 free(variable);
574 free(offset);
575 }
576}
577
578
579/* Penetrate a struct and dump the contents. */
580static void
581ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, char *arrsize, struct ECPGtype *type, struct ECPGtype *ind_type, const char *prefix, const char *ind_prefix)
582{
583 /*
584 * If offset is NULL, then this is the first recursive level. If not then
585 * we are in a struct and the offset is used as offset.
586 */
587 struct ECPGstruct_member *p,
588 *ind_p = NULL;
589 char *pbuf = (char *) mm_alloc(strlen(name) + ((prefix == NULL) ? 0 : strlen(prefix)) + 3);
590 char *ind_pbuf = (char *) mm_alloc(strlen(ind_name) + ((ind_prefix == NULL) ? 0 : strlen(ind_prefix)) + 3);
591
592 if (atoi(arrsize) == 1)
593 sprintf(pbuf, "%s%s.", prefix ? prefix : "", name);
594 else
595 sprintf(pbuf, "%s%s->", prefix ? prefix : "", name);
596
597 prefix = pbuf;
598
599 if (ind_type == &ecpg_no_indicator)
600 ind_p = &struct_no_indicator;
601 else if (ind_type != NULL)
602 {
603 if (atoi(arrsize) == 1)
604 sprintf(ind_pbuf, "%s%s.", ind_prefix ? ind_prefix : "", ind_name);
605 else
606 sprintf(ind_pbuf, "%s%s->", ind_prefix ? ind_prefix : "", ind_name);
607
608 ind_prefix = ind_pbuf;
609 ind_p = ind_type->u.members;
610 }
611
612 for (p = type->u.members; p; p = p->next)
613 {
614 ECPGdump_a_type(o, p->name, p->type, -1,
615 (ind_p != NULL) ? ind_p->name : NULL,
616 (ind_p != NULL) ? ind_p->type : NULL,
617 -1,
618 prefix, ind_prefix, arrsize, type->struct_sizeof,
619 (ind_p != NULL) ? ind_type->struct_sizeof : NULL);
620 if (ind_p != NULL && ind_p != &struct_no_indicator)
621 {
622 ind_p = ind_p->next;
623 if (ind_p == NULL && p->next != NULL)
624 {
625 mmerror(PARSE_ERROR, ET_WARNING, "indicator struct \"%s\" has too few members", ind_name);
626 ind_p = &struct_no_indicator;
627 }
628 }
629 }
630
631 if (ind_type != NULL && ind_p != NULL && ind_p != &struct_no_indicator)
632 {
633 mmerror(PARSE_ERROR, ET_WARNING, "indicator struct \"%s\" has too many members", ind_name);
634 }
635
636 free(pbuf);
637 free(ind_pbuf);
638}
639
640void
641ECPGfree_struct_member(struct ECPGstruct_member *rm)
642{
643 while (rm)
644 {
645 struct ECPGstruct_member *p = rm;
646
647 rm = rm->next;
648 free(p->name);
649 free(p->type);
650 free(p);
651 }
652}
653
654void
655ECPGfree_type(struct ECPGtype *type)
656{
657 if (!IS_SIMPLE_TYPE(type->type))
658 {
659 switch (type->type)
660 {
661 case ECPGt_array:
662 switch (type->u.element->type)
663 {
664 case ECPGt_array:
665 base_yyerror("internal error: found multidimensional array\n");
666 break;
667 case ECPGt_struct:
668 case ECPGt_union:
669 /* Array of structs. */
670 ECPGfree_struct_member(type->u.element->u.members);
671 free(type->u.element);
672 break;
673 default:
674 if (!IS_SIMPLE_TYPE(type->u.element->type))
675 base_yyerror("internal error: unknown datatype, please report this to <pgsql-bugs@lists.postgresql.org>");
676
677 free(type->u.element);
678 }
679 break;
680 case ECPGt_struct:
681 case ECPGt_union:
682 ECPGfree_struct_member(type->u.members);
683 break;
684 default:
685 mmerror(PARSE_ERROR, ET_ERROR, "unrecognized variable type code %d", type->type);
686 break;
687 }
688 }
689 free(type);
690}
691
692const char *
693get_dtype(enum ECPGdtype type)
694{
695 switch (type)
696 {
697 case ECPGd_count:
698 return "ECPGd_countr";
699 break;
700 case ECPGd_data:
701 return "ECPGd_data";
702 break;
703 case ECPGd_di_code:
704 return "ECPGd_di_code";
705 break;
706 case ECPGd_di_precision:
707 return "ECPGd_di_precision";
708 break;
709 case ECPGd_indicator:
710 return "ECPGd_indicator";
711 break;
712 case ECPGd_key_member:
713 return "ECPGd_key_member";
714 break;
715 case ECPGd_length:
716 return "ECPGd_length";
717 break;
718 case ECPGd_name:
719 return "ECPGd_name";
720 break;
721 case ECPGd_nullable:
722 return "ECPGd_nullable";
723 break;
724 case ECPGd_octet:
725 return "ECPGd_octet";
726 break;
727 case ECPGd_precision:
728 return "ECPGd_precision";
729 break;
730 case ECPGd_ret_length:
731 return "ECPGd_ret_length";
732 case ECPGd_ret_octet:
733 return "ECPGd_ret_octet";
734 break;
735 case ECPGd_scale:
736 return "ECPGd_scale";
737 break;
738 case ECPGd_type:
739 return "ECPGd_type";
740 break;
741 case ECPGd_cardinality:
742 return "ECPGd_cardinality";
743 default:
744 mmerror(PARSE_ERROR, ET_ERROR, "unrecognized descriptor item code %d", type);
745 }
746
747 return NULL;
748}
749