LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/preproc - type.c (source / functions) Hit Total Coverage
Test: PostgreSQL 12beta2 Lines: 263 311 84.6 %
Date: 2019-06-19 14:06:47 Functions: 14 14 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13