]> granicus.if.org Git - postgresql/blob - src/interfaces/ecpg/preproc/type.c
When creating a varchar struct name braces must be discarded.
[postgresql] / src / interfaces / ecpg / preproc / type.c
1 /* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/type.c,v 1.80 2008/11/26 13:18:22 meskes Exp $ */
2
3 #include "postgres_fe.h"
4
5 #include "extern.h"
6
7 #define indicator_set ind_type != NULL && ind_type->type != ECPGt_NO_INDICATOR
8
9 static struct ECPGstruct_member struct_no_indicator = {"no_indicator", &ecpg_no_indicator, NULL};
10
11 /* malloc + error check */
12 void *
13 mm_alloc(size_t size)
14 {
15         void       *ptr = malloc(size);
16
17         if (ptr == NULL)
18                 mmerror(OUT_OF_MEMORY, ET_FATAL, "out of memory\n");
19
20         return ptr;
21 }
22
23 /* strdup + error check */
24 char *
25 mm_strdup(const char *string)
26 {
27         char       *new = strdup(string);
28
29         if (new == NULL)
30                 mmerror(OUT_OF_MEMORY, ET_FATAL, "out of memory\n");
31
32         return new;
33 }
34
35 /* duplicate memberlist */
36 struct ECPGstruct_member *
37 ECPGstruct_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->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)
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;
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. */
76 void
77 ECPGmake_struct_member(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
95 struct ECPGtype *
96 ECPGmake_simple_type(enum ECPGttype type, char *size, int lineno)
97 {
98         struct ECPGtype *ne = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype));
99
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 */
105
106         return ne;
107 }
108
109 struct ECPGtype *
110 ECPGmake_array_type(struct ECPGtype * type, char *size)
111 {
112         struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_array, size, 0);
113
114         ne->u.element = type;
115
116         return ne;
117 }
118
119 struct ECPGtype *
120 ECPGmake_struct_type(struct ECPGstruct_member * rm, enum ECPGttype type, char *struct_sizeof)
121 {
122         struct ECPGtype *ne = ECPGmake_simple_type(type, make_str("1"), 0);
123
124         ne->u.members = ECPGstruct_member_dup(rm);
125         ne->struct_sizeof = struct_sizeof;
126
127         return ne;
128 }
129
130 static const char *
131 get_type(enum ECPGttype type)
132 {
133         switch (type)
134         {
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);
205         }
206
207         return NULL;
208 }
209
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).
223  */
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);
229
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)
236 {
237         switch (type->type)
238         {
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)
243                         {
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>");
259
260                                         ECPGdump_a_simple(o, name,
261                                                                           type->u.element->type,
262                                                                           type->u.element->size, type->size, NULL, prefix, type->u.element->lineno);
263
264                                         if (ind_type != NULL)
265                                         {
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
269                                                 {
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);
272                                                 }
273                                         }
274                         }
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");
279
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");
288
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");
296
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");
304
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;
309         }
310 }
311
312
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)
322 {
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
329         {
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; 
333
334                 switch (type)
335                 {
336                                 /*
337                                  * we have to use the & operator except for arrays and
338                                  * pointers
339                                  */
340
341                         case ECPGt_varchar:
342
343                                 /*
344                                  * we have to use the pointer except for arrays with given
345                                  * bounds
346                                  */
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);
353
354                                 /* remove trailing [] is name is array element */
355                                 var_name = strdup(name);
356                                 *(strchrnul(var_name, '[')) = '\0';
357                                 if (lineno)
358                                         sprintf(offset, "sizeof(struct varchar_%s_%d)", var_name, lineno);
359                                 else
360                                         sprintf(offset, "sizeof(struct varchar_%s)", var_name);
361                                 free(var_name);
362                                 break;
363                         case ECPGt_char:
364                         case ECPGt_unsigned_char:
365                         case ECPGt_char_variable:
366
367                                 /*
368                                  * we have to use the pointer except for arrays with given
369                                  * bounds, ecpglib will distinguish between * and []
370                                  */
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))
375                                         && siz == NULL)
376                                         sprintf(variable, "(%s%s)", prefix ? prefix : "", name);
377                                 else
378                                         sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
379
380                                 sprintf(offset, "(%s)*sizeof(char)", strcmp(varcharsize, "0") == 0 ? "1" : varcharsize);
381                                 break;
382                         case ECPGt_numeric:
383
384                                 /*
385                                  * we have to use a pointer here
386                                  */
387                                 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
388                                 sprintf(offset, "sizeof(numeric)");
389                                 break;
390                         case ECPGt_interval:
391
392                                 /*
393                                  * we have to use a pointer here
394                                  */
395                                 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
396                                 sprintf(offset, "sizeof(interval)");
397                                 break;
398                         case ECPGt_date:
399
400                                 /*
401                                  * we have to use a pointer and translate the variable type
402                                  */
403                                 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
404                                 sprintf(offset, "sizeof(date)");
405                                 break;
406                         case ECPGt_timestamp:
407
408                                 /*
409                                  * we have to use a pointer and translate the variable type
410                                  */
411                                 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
412                                 sprintf(offset, "sizeof(timestamp)");
413                                 break;
414                         case ECPGt_const:
415
416                                 /*
417                                  * just dump the const as string
418                                  */
419                                 sprintf(variable, "\"%s\"", name);
420                                 sprintf(offset, "strlen(\"%s\")", name);
421                                 break;
422                         default:
423
424                                 /*
425                                  * we have to use the pointer except for arrays with given
426                                  * bounds
427                                  */
428                                 if (((atoi(arrsize) > 0) ||
429                                          (atoi(arrsize) == 0 && strcmp(arrsize, "0") != 0)) &&
430                                         siz == NULL)
431                                         sprintf(variable, "(%s%s)", prefix ? prefix : "", name);
432                                 else
433                                         sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
434
435                                 sprintf(offset, "sizeof(%s)", ecpg_type_name(type));
436                                 break;
437                 }
438
439                 if (atoi(arrsize) < 0)
440                         strcpy(arrsize, "1");
441
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);
444                 else
445                         fprintf(o, "\n\t%s,%s,(long)%s,(long)%s,%s, ", get_type(type), variable, varcharsize, arrsize, siz);
446
447                 free(variable);
448                 free(offset);
449         }
450 }
451
452
453 /* Penetrate a struct and dump the contents. */
454 static void
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)
456 {
457         /*
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.
460          */
461         struct ECPGstruct_member *p,
462                            *ind_p = NULL;
463         char            obuf[BUFSIZ];
464         char            pbuf[BUFSIZ],
465                                 ind_pbuf[BUFSIZ];
466         const char *offset;
467
468         if (offsetarg == NULL)
469         {
470                 sprintf(obuf, "sizeof(%s)", name);
471                 offset = obuf;
472         }
473         else
474                 offset = offsetarg;
475
476         if (atoi(arrsiz) == 1)
477                 sprintf(pbuf, "%s%s.", prefix ? prefix : "", name);
478         else
479                 sprintf(pbuf, "%s%s->", prefix ? prefix : "", name);
480
481         prefix = pbuf;
482
483         if (ind_type == &ecpg_no_indicator)
484                 ind_p = &struct_no_indicator;
485         else if (ind_type != NULL)
486         {
487                 if (atoi(arrsiz) == 1)
488                         sprintf(ind_pbuf, "%s%s.", ind_prefix ? ind_prefix : "", ind_name);
489                 else
490                         sprintf(ind_pbuf, "%s%s->", ind_prefix ? ind_prefix : "", ind_name);
491
492                 ind_prefix = ind_pbuf;
493                 ind_p = ind_type->u.members;
494         }
495
496         for (p = type->u.members; p; p = p->next)
497         {
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)
504                         ind_p = ind_p->next;
505         }
506 }
507
508 void
509 ECPGfree_struct_member(struct ECPGstruct_member * rm)
510 {
511         while (rm)
512         {
513                 struct ECPGstruct_member *p = rm;
514
515                 rm = rm->next;
516                 free(p->name);
517                 free(p->type);
518                 free(p);
519         }
520 }
521
522 void
523 ECPGfree_type(struct ECPGtype * type)
524 {
525         if (!IS_SIMPLE_TYPE(type->type))
526         {
527                 switch (type->type)
528                 {
529                         case ECPGt_array:
530                                 switch (type->u.element->type)
531                                 {
532                                         case ECPGt_array:
533                                                 base_yyerror("internal error: found multidimensional array\n");
534                                                 break;
535                                         case ECPGt_struct:
536                                         case ECPGt_union:
537                                                 /* Array of structs. */
538                                                 ECPGfree_struct_member(type->u.element->u.members);
539                                                 free(type->u.element);
540                                                 break;
541                                         default:
542                                                 if (!IS_SIMPLE_TYPE(type->u.element->type))
543                                                         base_yyerror("internal error: unknown datatype, please report this to <pgsql-bugs@postgresql.org>");
544
545                                                 free(type->u.element);
546                                 }
547                                 break;
548                         case ECPGt_struct:
549                         case ECPGt_union:
550                                 ECPGfree_struct_member(type->u.members);
551                                 break;
552                         default:
553                                 mmerror(PARSE_ERROR, ET_ERROR, "illegal variable type %d\n", type->type);
554                                 break;
555                 }
556         }
557         free(type);
558 }
559
560 const char *
561 get_dtype(enum ECPGdtype type)
562 {
563         switch (type)
564         {
565                 case ECPGd_count:
566                         return ("ECPGd_countr");
567                         break;
568                 case ECPGd_data:
569                         return ("ECPGd_data");
570                         break;
571                 case ECPGd_di_code:
572                         return ("ECPGd_di_code");
573                         break;
574                 case ECPGd_di_precision:
575                         return ("ECPGd_di_precision");
576                         break;
577                 case ECPGd_indicator:
578                         return ("ECPGd_indicator");
579                         break;
580                 case ECPGd_key_member:
581                         return ("ECPGd_key_member");
582                         break;
583                 case ECPGd_length:
584                         return ("ECPGd_length");
585                         break;
586                 case ECPGd_name:
587                         return ("ECPGd_name");
588                         break;
589                 case ECPGd_nullable:
590                         return ("ECPGd_nullable");
591                         break;
592                 case ECPGd_octet:
593                         return ("ECPGd_octet");
594                         break;
595                 case ECPGd_precision:
596                         return ("ECPGd_precision");
597                         break;
598                 case ECPGd_ret_length:
599                         return ("ECPGd_ret_length");
600                 case ECPGd_ret_octet:
601                         return ("ECPGd_ret_octet");
602                         break;
603                 case ECPGd_scale:
604                         return ("ECPGd_scale");
605                         break;
606                 case ECPGd_type:
607                         return ("ECPGd_type");
608                         break;
609                 case ECPGd_cardinality:
610                         return ("ECPGd_cardinality");
611                 default:
612                         mmerror(PARSE_ERROR, ET_ERROR, "illegal descriptor item %d\n", type);
613         }
614
615         return NULL;
616 }