1 /* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/type.c,v 1.80 2008/11/26 13:18:22 meskes Exp $ */
3 #include "postgres_fe.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 */
15 void *ptr = malloc(size);
18 mmerror(OUT_OF_MEMORY, ET_FATAL, "out of memory\n");
23 /* strdup + error check */
25 mm_strdup(const char *string)
27 char *new = strdup(string);
30 mmerror(OUT_OF_MEMORY, ET_FATAL, "out of memory\n");
35 /* duplicate memberlist */
36 struct ECPGstruct_member *
37 ECPGstruct_member_dup(struct ECPGstruct_member * rm)
39 struct ECPGstruct_member *new = NULL;
43 struct ECPGtype *type;
45 switch (rm->type->type)
49 type = ECPGmake_struct_type(rm->type->u.members, rm->type->type, rm->type->struct_sizeof);
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);
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);
63 type = ECPGmake_simple_type(rm->type->type, rm->type->size, rm->type->lineno);
67 ECPGmake_struct_member(rm->name, type, &new);
75 /* The NAME argument is copied. The type argument is preserved as a pointer. */
77 ECPGmake_struct_member(char *name, struct ECPGtype * type, struct ECPGstruct_member ** start)
79 struct ECPGstruct_member *ptr,
81 (struct ECPGstruct_member *) mm_alloc(sizeof(struct ECPGstruct_member));
83 ne->name = mm_strdup(name);
87 for (ptr = *start; ptr && ptr->next; ptr = ptr->next);
96 ECPGmake_simple_type(enum ECPGttype type, char *size, int lineno)
98 struct ECPGtype *ne = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype));
102 ne->u.element = NULL;
103 ne->struct_sizeof = NULL;
104 ne->lineno = lineno; /* only needed for varchar */
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;
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;
131 get_type(enum ECPGttype type)
136 return ("ECPGt_char");
138 case ECPGt_unsigned_char:
139 return ("ECPGt_unsigned_char");
142 return ("ECPGt_short");
144 case ECPGt_unsigned_short:
145 return ("ECPGt_unsigned_short");
148 return ("ECPGt_int");
150 case ECPGt_unsigned_int:
151 return ("ECPGt_unsigned_int");
154 return ("ECPGt_long");
156 case ECPGt_unsigned_long:
157 return ("ECPGt_unsigned_long");
159 case ECPGt_long_long:
160 return ("ECPGt_long_long");
162 case ECPGt_unsigned_long_long:
163 return ("ECPGt_unsigned_long_long");
166 return ("ECPGt_float");
169 return ("ECPGt_double");
172 return ("ECPGt_bool");
175 return ("ECPGt_varchar");
176 case ECPGt_NO_INDICATOR: /* no indicator */
177 return ("ECPGt_NO_INDICATOR");
179 case ECPGt_char_variable: /* string that should not be quoted */
180 return ("ECPGt_char_variable");
182 case ECPGt_const: /* constant string quoted */
183 return ("ECPGt_const");
186 return ("ECPGt_decimal");
189 return ("ECPGt_numeric");
192 return ("ECPGt_interval");
194 case ECPGt_descriptor:
195 return ("ECPGt_descriptor");
198 return ("ECPGt_date");
200 case ECPGt_timestamp:
201 return ("ECPGt_timestamp");
204 mmerror(PARSE_ERROR, ET_ERROR, "illegal variable type %d\n", 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
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,
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);
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)
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)
245 mmerror(PARSE_ERROR, ET_ERROR, "no nested arrays allowed (except strings)"); /* array of array */
249 ECPGdump_a_struct(o, name,
253 (ind_type == NULL) ? NULL : ((ind_type->type == ECPGt_NO_INDICATOR) ? ind_type : ind_type->u.element),
254 NULL, prefix, ind_prefix);
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);
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);
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);
282 case ECPGt_union: /* cannot dump a complete union */
283 base_yyerror("type of union has to be specified");
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);
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);
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);
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. */
316 ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type,
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);
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);
337 * we have to use the & operator except for arrays and
344 * we have to use the pointer except for arrays with given
347 if (((atoi(arrsize) > 0) ||
348 (atoi(arrsize) == 0 && strcmp(arrsize, "0") != 0)) &&
350 sprintf(variable, "(%s%s)", prefix ? prefix : "", name);
352 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
354 /* remove trailing [] is name is array element */
355 var_name = strdup(name);
356 *(strchrnul(var_name, '[')) = '\0';
358 sprintf(offset, "sizeof(struct varchar_%s_%d)", var_name, lineno);
360 sprintf(offset, "sizeof(struct varchar_%s)", var_name);
364 case ECPGt_unsigned_char:
365 case ECPGt_char_variable:
368 * we have to use the pointer except for arrays with given
369 * bounds, ecpglib will distinguish between * and []
371 if ((atoi(varcharsize) > 1 ||
372 (atoi(arrsize) > 0) ||
373 (atoi(varcharsize) == 0 && strcmp(varcharsize, "0") != 0) ||
374 (atoi(arrsize) == 0 && strcmp(arrsize, "0") != 0))
376 sprintf(variable, "(%s%s)", prefix ? prefix : "", name);
378 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
380 sprintf(offset, "(%s)*sizeof(char)", strcmp(varcharsize, "0") == 0 ? "1" : varcharsize);
385 * we have to use a pointer here
387 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
388 sprintf(offset, "sizeof(numeric)");
393 * we have to use a pointer here
395 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
396 sprintf(offset, "sizeof(interval)");
401 * we have to use a pointer and translate the variable type
403 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
404 sprintf(offset, "sizeof(date)");
406 case ECPGt_timestamp:
409 * we have to use a pointer and translate the variable type
411 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
412 sprintf(offset, "sizeof(timestamp)");
417 * just dump the const as string
419 sprintf(variable, "\"%s\"", name);
420 sprintf(offset, "strlen(\"%s\")", name);
425 * we have to use the pointer except for arrays with given
428 if (((atoi(arrsize) > 0) ||
429 (atoi(arrsize) == 0 && strcmp(arrsize, "0") != 0)) &&
431 sprintf(variable, "(%s%s)", prefix ? prefix : "", name);
433 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
435 sprintf(offset, "sizeof(%s)", ecpg_type_name(type));
439 if (atoi(arrsize) < 0)
440 strcpy(arrsize, "1");
442 if (siz == NULL || strlen(siz) == 0 || strcmp(arrsize, "0") == 0 || strcmp(arrsize, "1") == 0)
443 fprintf(o, "\n\t%s,%s,(long)%s,(long)%s,%s, ", get_type(type), variable, varcharsize, arrsize, offset);
445 fprintf(o, "\n\t%s,%s,(long)%s,(long)%s,%s, ", get_type(type), variable, varcharsize, arrsize, siz);
453 /* Penetrate a struct and dump the contents. */
455 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)
458 * If offset is NULL, then this is the first recursive level. If not then
459 * we are in a struct in a struct and the offset is used as offset.
461 struct ECPGstruct_member *p,
468 if (offsetarg == NULL)
470 sprintf(obuf, "sizeof(%s)", name);
476 if (atoi(arrsiz) == 1)
477 sprintf(pbuf, "%s%s.", prefix ? prefix : "", name);
479 sprintf(pbuf, "%s%s->", prefix ? prefix : "", name);
483 if (ind_type == &ecpg_no_indicator)
484 ind_p = &struct_no_indicator;
485 else if (ind_type != NULL)
487 if (atoi(arrsiz) == 1)
488 sprintf(ind_pbuf, "%s%s.", ind_prefix ? ind_prefix : "", ind_name);
490 sprintf(ind_pbuf, "%s%s->", ind_prefix ? ind_prefix : "", ind_name);
492 ind_prefix = ind_pbuf;
493 ind_p = ind_type->u.members;
496 for (p = type->u.members; p; p = p->next)
498 ECPGdump_a_type(o, p->name, p->type,
499 (ind_p != NULL) ? ind_p->name : NULL,
500 (ind_p != NULL) ? ind_p->type : NULL,
501 prefix, ind_prefix, arrsiz, type->struct_sizeof,
502 (ind_p != NULL) ? ind_type->struct_sizeof : NULL);
503 if (ind_p != NULL && ind_p != &struct_no_indicator)
509 ECPGfree_struct_member(struct ECPGstruct_member * rm)
513 struct ECPGstruct_member *p = rm;
523 ECPGfree_type(struct ECPGtype * type)
525 if (!IS_SIMPLE_TYPE(type->type))
530 switch (type->u.element->type)
533 base_yyerror("internal error: found multidimensional array\n");
537 /* Array of structs. */
538 ECPGfree_struct_member(type->u.element->u.members);
539 free(type->u.element);
542 if (!IS_SIMPLE_TYPE(type->u.element->type))
543 base_yyerror("internal error: unknown datatype, please report this to <pgsql-bugs@postgresql.org>");
545 free(type->u.element);
550 ECPGfree_struct_member(type->u.members);
553 mmerror(PARSE_ERROR, ET_ERROR, "illegal variable type %d\n", type->type);
561 get_dtype(enum ECPGdtype type)
566 return ("ECPGd_countr");
569 return ("ECPGd_data");
572 return ("ECPGd_di_code");
574 case ECPGd_di_precision:
575 return ("ECPGd_di_precision");
577 case ECPGd_indicator:
578 return ("ECPGd_indicator");
580 case ECPGd_key_member:
581 return ("ECPGd_key_member");
584 return ("ECPGd_length");
587 return ("ECPGd_name");
590 return ("ECPGd_nullable");
593 return ("ECPGd_octet");
595 case ECPGd_precision:
596 return ("ECPGd_precision");
598 case ECPGd_ret_length:
599 return ("ECPGd_ret_length");
600 case ECPGd_ret_octet:
601 return ("ECPGd_ret_octet");
604 return ("ECPGd_scale");
607 return ("ECPGd_type");
609 case ECPGd_cardinality:
610 return ("ECPGd_cardinality");
612 mmerror(PARSE_ERROR, ET_ERROR, "illegal descriptor item %d\n", type);