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);
332 char *var_name
, *ptr
;
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
= mm_strdup(name
);
356 ptr
= strchr(var_name
, '[');
357 if (ptr
) *ptr
= '\0';
359 sprintf(offset
, "sizeof(struct varchar_%s_%d)", var_name
, lineno
);
361 sprintf(offset
, "sizeof(struct varchar_%s)", var_name
);
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))
377 sprintf(variable
, "(%s%s)", prefix
? prefix
: "", name
);
379 sprintf(variable
, "&(%s%s)", prefix
? prefix
: "", name
);
381 sprintf(offset
, "(%s)*sizeof(char)", strcmp(varcharsize
, "0") == 0 ? "1" : varcharsize
);
386 * we have to use a pointer here
388 sprintf(variable
, "&(%s%s)", prefix
? prefix
: "", name
);
389 sprintf(offset
, "sizeof(numeric)");
394 * we have to use a pointer here
396 sprintf(variable
, "&(%s%s)", prefix
? prefix
: "", name
);
397 sprintf(offset
, "sizeof(interval)");
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)");
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)");
418 * just dump the const as string
420 sprintf(variable
, "\"%s\"", name
);
421 sprintf(offset
, "strlen(\"%s\")", name
);
426 * we have to use the pointer except for arrays with given
429 if (((atoi(arrsize
) > 0) ||
430 (atoi(arrsize
) == 0 && strcmp(arrsize
, "0") != 0)) &&
432 sprintf(variable
, "(%s%s)", prefix
? prefix
: "", name
);
434 sprintf(variable
, "&(%s%s)", prefix
? prefix
: "", name
);
436 sprintf(offset
, "sizeof(%s)", ecpg_type_name(type
));
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
);
446 fprintf(o
, "\n\t%s,%s,(long)%s,(long)%s,%s, ", get_type(type
), variable
, varcharsize
, arrsize
, siz
);
454 /* Penetrate a struct and dump the contents. */
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
,
469 if (offsetarg
== NULL
)
471 sprintf(obuf
, "sizeof(%s)", name
);
477 if (atoi(arrsiz
) == 1)
478 sprintf(pbuf
, "%s%s.", prefix
? prefix
: "", name
);
480 sprintf(pbuf
, "%s%s->", prefix
? prefix
: "", name
);
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
);
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
)
510 ECPGfree_struct_member(struct ECPGstruct_member
* rm
)
514 struct ECPGstruct_member
*p
= rm
;
524 ECPGfree_type(struct ECPGtype
* type
)
526 if (!IS_SIMPLE_TYPE(type
->type
))
531 switch (type
->u
.element
->type
)
534 base_yyerror("internal error: found multidimensional array\n");
538 /* Array of structs. */
539 ECPGfree_struct_member(type
->u
.element
->u
.members
);
540 free(type
->u
.element
);
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
);
551 ECPGfree_struct_member(type
->u
.members
);
554 mmerror(PARSE_ERROR
, ET_ERROR
, "illegal variable type %d\n", type
->type
);
562 get_dtype(enum ECPGdtype type
)
567 return ("ECPGd_countr");
570 return ("ECPGd_data");
573 return ("ECPGd_di_code");
575 case ECPGd_di_precision
:
576 return ("ECPGd_di_precision");
578 case ECPGd_indicator
:
579 return ("ECPGd_indicator");
581 case ECPGd_key_member
:
582 return ("ECPGd_key_member");
585 return ("ECPGd_length");
588 return ("ECPGd_name");
591 return ("ECPGd_nullable");
594 return ("ECPGd_octet");
596 case ECPGd_precision
:
597 return ("ECPGd_precision");
599 case ECPGd_ret_length
:
600 return ("ECPGd_ret_length");
601 case ECPGd_ret_octet
:
602 return ("ECPGd_ret_octet");
605 return ("ECPGd_scale");
608 return ("ECPGd_type");
610 case ECPGd_cardinality
:
611 return ("ECPGd_cardinality");
613 mmerror(PARSE_ERROR
, ET_ERROR
, "illegal descriptor item %d\n", type
);