LCOV - differential code coverage report
Current view: top level - src/interfaces/ecpg/preproc - type.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 81.6 % 381 311 70 311
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 14 14 14
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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