Header And Logo

PostgreSQL
| The world's most advanced open source database.

type.c

Go to the documentation of this file.
00001 /* src/interfaces/ecpg/preproc/type.c */
00002 
00003 #include "postgres_fe.h"
00004 
00005 #include "extern.h"
00006 
00007 #define indicator_set ind_type != NULL && ind_type->type != ECPGt_NO_INDICATOR
00008 
00009 static struct ECPGstruct_member struct_no_indicator = {"no_indicator", &ecpg_no_indicator, NULL};
00010 
00011 /* malloc + error check */
00012 void *
00013 mm_alloc(size_t size)
00014 {
00015     void       *ptr = malloc(size);
00016 
00017     if (ptr == NULL)
00018         mmerror(OUT_OF_MEMORY, ET_FATAL, "out of memory");
00019 
00020     return ptr;
00021 }
00022 
00023 /* strdup + error check */
00024 char *
00025 mm_strdup(const char *string)
00026 {
00027     char       *new = strdup(string);
00028 
00029     if (new == NULL)
00030         mmerror(OUT_OF_MEMORY, ET_FATAL, "out of memory");
00031 
00032     return new;
00033 }
00034 
00035 /* duplicate memberlist */
00036 struct ECPGstruct_member *
00037 ECPGstruct_member_dup(struct ECPGstruct_member * rm)
00038 {
00039     struct ECPGstruct_member *new = NULL;
00040 
00041     while (rm)
00042     {
00043         struct ECPGtype *type;
00044 
00045         switch (rm->type->type)
00046         {
00047             case ECPGt_struct:
00048             case ECPGt_union:
00049                 type = ECPGmake_struct_type(rm->type->u.members, rm->type->type, rm->type->type_name, rm->type->struct_sizeof);
00050                 break;
00051             case ECPGt_array:
00052 
00053                 /*
00054                  * if this array does contain a struct again, we have to
00055                  * create the struct too
00056                  */
00057                 if (rm->type->u.element->type == ECPGt_struct || rm->type->u.element->type == ECPGt_union)
00058                     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);
00059                 else
00060                     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);
00061                 break;
00062             default:
00063                 type = ECPGmake_simple_type(rm->type->type, rm->type->size, rm->type->counter);
00064                 break;
00065         }
00066 
00067         ECPGmake_struct_member(rm->name, type, &new);
00068 
00069         rm = rm->next;
00070     }
00071 
00072     return (new);
00073 }
00074 
00075 /* The NAME argument is copied. The type argument is preserved as a pointer. */
00076 void
00077 ECPGmake_struct_member(char *name, struct ECPGtype * type, struct ECPGstruct_member ** start)
00078 {
00079     struct ECPGstruct_member *ptr,
00080                *ne =
00081     (struct ECPGstruct_member *) mm_alloc(sizeof(struct ECPGstruct_member));
00082 
00083     ne->name = mm_strdup(name);
00084     ne->type = type;
00085     ne->next = NULL;
00086 
00087     for (ptr = *start; ptr && ptr->next; ptr = ptr->next);
00088 
00089     if (ptr)
00090         ptr->next = ne;
00091     else
00092         *start = ne;
00093 }
00094 
00095 struct ECPGtype *
00096 ECPGmake_simple_type(enum ECPGttype type, char *size, int counter)
00097 {
00098     struct ECPGtype *ne = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype));
00099 
00100     ne->type = type;
00101     ne->type_name = NULL;
00102     ne->size = size;
00103     ne->u.element = NULL;
00104     ne->struct_sizeof = NULL;
00105     ne->counter = counter;      /* only needed for varchar */
00106 
00107     return ne;
00108 }
00109 
00110 struct ECPGtype *
00111 ECPGmake_array_type(struct ECPGtype * type, char *size)
00112 {
00113     struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_array, size, 0);
00114 
00115     ne->u.element = type;
00116 
00117     return ne;
00118 }
00119 
00120 struct ECPGtype *
00121 ECPGmake_struct_type(struct ECPGstruct_member * rm, enum ECPGttype type, char *type_name, char *struct_sizeof)
00122 {
00123     struct ECPGtype *ne = ECPGmake_simple_type(type, mm_strdup("1"), 0);
00124 
00125     ne->type_name = mm_strdup(type_name);
00126     ne->u.members = ECPGstruct_member_dup(rm);
00127     ne->struct_sizeof = struct_sizeof;
00128 
00129     return ne;
00130 }
00131 
00132 static const char *
00133 get_type(enum ECPGttype type)
00134 {
00135     switch (type)
00136     {
00137         case ECPGt_char:
00138             return ("ECPGt_char");
00139             break;
00140         case ECPGt_unsigned_char:
00141             return ("ECPGt_unsigned_char");
00142             break;
00143         case ECPGt_short:
00144             return ("ECPGt_short");
00145             break;
00146         case ECPGt_unsigned_short:
00147             return ("ECPGt_unsigned_short");
00148             break;
00149         case ECPGt_int:
00150             return ("ECPGt_int");
00151             break;
00152         case ECPGt_unsigned_int:
00153             return ("ECPGt_unsigned_int");
00154             break;
00155         case ECPGt_long:
00156             return ("ECPGt_long");
00157             break;
00158         case ECPGt_unsigned_long:
00159             return ("ECPGt_unsigned_long");
00160             break;
00161         case ECPGt_long_long:
00162             return ("ECPGt_long_long");
00163             break;
00164         case ECPGt_unsigned_long_long:
00165             return ("ECPGt_unsigned_long_long");
00166             break;
00167         case ECPGt_float:
00168             return ("ECPGt_float");
00169             break;
00170         case ECPGt_double:
00171             return ("ECPGt_double");
00172             break;
00173         case ECPGt_bool:
00174             return ("ECPGt_bool");
00175             break;
00176         case ECPGt_varchar:
00177             return ("ECPGt_varchar");
00178         case ECPGt_NO_INDICATOR:        /* no indicator */
00179             return ("ECPGt_NO_INDICATOR");
00180             break;
00181         case ECPGt_char_variable:       /* string that should not be quoted */
00182             return ("ECPGt_char_variable");
00183             break;
00184         case ECPGt_const:       /* constant string quoted */
00185             return ("ECPGt_const");
00186             break;
00187         case ECPGt_decimal:
00188             return ("ECPGt_decimal");
00189             break;
00190         case ECPGt_numeric:
00191             return ("ECPGt_numeric");
00192             break;
00193         case ECPGt_interval:
00194             return ("ECPGt_interval");
00195             break;
00196         case ECPGt_descriptor:
00197             return ("ECPGt_descriptor");
00198             break;
00199         case ECPGt_sqlda:
00200             return ("ECPGt_sqlda");
00201             break;
00202         case ECPGt_date:
00203             return ("ECPGt_date");
00204             break;
00205         case ECPGt_timestamp:
00206             return ("ECPGt_timestamp");
00207             break;
00208         case ECPGt_string:
00209             return ("ECPGt_string");
00210             break;
00211         default:
00212             mmerror(PARSE_ERROR, ET_ERROR, "unrecognized variable type code %d", type);
00213     }
00214 
00215     return NULL;
00216 }
00217 
00218 /* Dump a type.
00219    The type is dumped as:
00220    type-tag <comma>                - enum ECPGttype
00221    reference-to-variable <comma>           - char *
00222    size <comma>                    - long size of this field (if varchar)
00223    arrsize <comma>                 - long number of elements in the arr
00224    offset <comma>                  - offset to the next element
00225    Where:
00226    type-tag is one of the simple types or varchar.
00227    reference-to-variable can be a reference to a struct element.
00228    arrsize is the size of the array in case of array fetches. Otherwise 0.
00229    size is the maxsize in case it is a varchar. Otherwise it is the size of
00230    the variable (required to do array fetches of structs).
00231  */
00232 static void ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type,
00233                   char *varcharsize,
00234                   char *arrsiz, const char *siz, const char *prefix, int);
00235 static void ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, char *arrsiz,
00236                   struct ECPGtype * type, struct ECPGtype * ind_type, const char *prefix, const char *ind_prefix);
00237 
00238 void
00239 ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * type, const int brace_level,
00240  const char *ind_name, struct ECPGtype * ind_type, const int ind_brace_level,
00241                 const char *prefix, const char *ind_prefix,
00242                 char *arr_str_siz, const char *struct_sizeof,
00243                 const char *ind_struct_sizeof)
00244 {
00245     struct variable *var;
00246 
00247     if (type->type != ECPGt_descriptor && type->type != ECPGt_sqlda &&
00248         type->type != ECPGt_char_variable && type->type != ECPGt_const &&
00249         brace_level >= 0)
00250     {
00251         char       *str;
00252 
00253         str = mm_strdup(name);
00254         var = find_variable(str);
00255         free(str);
00256 
00257         if ((var->type->type != type->type) ||
00258             (var->type->type_name && !type->type_name) ||
00259             (!var->type->type_name && type->type_name) ||
00260             (var->type->type_name && type->type_name && strcmp(var->type->type_name, type->type_name) != 0))
00261             mmerror(PARSE_ERROR, ET_ERROR, "variable \"%s\" is hidden by a local variable of a different type", name);
00262         else if (var->brace_level != brace_level)
00263             mmerror(PARSE_ERROR, ET_WARNING, "variable \"%s\" is hidden by a local variable", name);
00264 
00265         if (ind_name && ind_type && ind_type->type != ECPGt_NO_INDICATOR && ind_brace_level >= 0)
00266         {
00267             str = mm_strdup(ind_name);
00268             var = find_variable(str);
00269             free(str);
00270 
00271             if ((var->type->type != ind_type->type) ||
00272                 (var->type->type_name && !ind_type->type_name) ||
00273                 (!var->type->type_name && ind_type->type_name) ||
00274                 (var->type->type_name && ind_type->type_name && strcmp(var->type->type_name, ind_type->type_name) != 0))
00275                 mmerror(PARSE_ERROR, ET_ERROR, "indicator variable \"%s\" is hidden by a local variable of a different type", ind_name);
00276             else if (var->brace_level != ind_brace_level)
00277                 mmerror(PARSE_ERROR, ET_WARNING, "indicator variable \"%s\" is hidden by a local variable", ind_name);
00278         }
00279     }
00280 
00281     switch (type->type)
00282     {
00283         case ECPGt_array:
00284             if (indicator_set && ind_type->type != ECPGt_array)
00285                 mmerror(INDICATOR_NOT_ARRAY, ET_FATAL, "indicator for array/pointer has to be array/pointer");
00286             switch (type->u.element->type)
00287             {
00288                 case ECPGt_array:
00289                     mmerror(PARSE_ERROR, ET_ERROR, "nested arrays are not supported (except strings)"); /* array of array */
00290                     break;
00291                 case ECPGt_struct:
00292                 case ECPGt_union:
00293                     ECPGdump_a_struct(o, name,
00294                                       ind_name,
00295                                       type->size,
00296                                       type->u.element,
00297                                       (ind_type == NULL) ? NULL : ((ind_type->type == ECPGt_NO_INDICATOR) ? ind_type : ind_type->u.element),
00298                                       prefix, ind_prefix);
00299                     break;
00300                 default:
00301                     if (!IS_SIMPLE_TYPE(type->u.element->type))
00302                         base_yyerror("internal error: unknown datatype, please report this to <[email protected]>");
00303 
00304                     ECPGdump_a_simple(o, name,
00305                                       type->u.element->type,
00306                                       type->u.element->size, type->size, NULL, prefix, type->u.element->counter);
00307 
00308                     if (ind_type != NULL)
00309                     {
00310                         if (ind_type->type == ECPGt_NO_INDICATOR)
00311                             ECPGdump_a_simple(o, ind_name, ind_type->type, ind_type->size, mm_strdup("-1"), NULL, ind_prefix, 0);
00312                         else
00313                         {
00314                             ECPGdump_a_simple(o, ind_name, ind_type->u.element->type,
00315                                               ind_type->u.element->size, ind_type->size, NULL, ind_prefix, 0);
00316                         }
00317                     }
00318             }
00319             break;
00320         case ECPGt_struct:
00321             if (indicator_set && ind_type->type != ECPGt_struct)
00322                 mmerror(INDICATOR_NOT_STRUCT, ET_FATAL, "indicator for struct has to be a struct");
00323 
00324             ECPGdump_a_struct(o, name, ind_name, mm_strdup("1"), type, ind_type, prefix, ind_prefix);
00325             break;
00326         case ECPGt_union:       /* cannot dump a complete union */
00327             base_yyerror("type of union has to be specified");
00328             break;
00329         case ECPGt_char_variable:
00330             if (indicator_set && (ind_type->type == ECPGt_struct || ind_type->type == ECPGt_array))
00331                 mmerror(INDICATOR_NOT_SIMPLE, ET_FATAL, "indicator for simple data type has to be simple");
00332 
00333             ECPGdump_a_simple(o, name, type->type, mm_strdup("1"), (arr_str_siz && strcmp(arr_str_siz, "0") != 0) ? arr_str_siz : mm_strdup("1"), struct_sizeof, prefix, 0);
00334             if (ind_type != NULL)
00335                 ECPGdump_a_simple(o, ind_name, ind_type->type, ind_type->size, (arr_str_siz && strcmp(arr_str_siz, "0") != 0) ? arr_str_siz : mm_strdup("-1"), ind_struct_sizeof, ind_prefix, 0);
00336             break;
00337         case ECPGt_descriptor:
00338             if (indicator_set && (ind_type->type == ECPGt_struct || ind_type->type == ECPGt_array))
00339                 mmerror(INDICATOR_NOT_SIMPLE, ET_FATAL, "indicator for simple data type has to be simple");
00340 
00341             ECPGdump_a_simple(o, name, type->type, NULL, mm_strdup("-1"), NULL, prefix, 0);
00342             if (ind_type != NULL)
00343                 ECPGdump_a_simple(o, ind_name, ind_type->type, ind_type->size, mm_strdup("-1"), NULL, ind_prefix, 0);
00344             break;
00345         default:
00346             if (indicator_set && (ind_type->type == ECPGt_struct || ind_type->type == ECPGt_array))
00347                 mmerror(INDICATOR_NOT_SIMPLE, ET_FATAL, "indicator for simple data type has to be simple");
00348 
00349             ECPGdump_a_simple(o, name, type->type, type->size, (arr_str_siz && strcmp(arr_str_siz, "0") != 0) ? arr_str_siz : mm_strdup("-1"), struct_sizeof, prefix, type->counter);
00350             if (ind_type != NULL)
00351                 ECPGdump_a_simple(o, ind_name, ind_type->type, ind_type->size, (arr_str_siz && strcmp(arr_str_siz, "0") != 0) ? arr_str_siz : mm_strdup("-1"), ind_struct_sizeof, ind_prefix, 0);
00352             break;
00353     }
00354 }
00355 
00356 
00357 /* If siz is NULL, then the offset is 0, if not use siz as a
00358    string, it represents the offset needed if we are in an array of structs. */
00359 static void
00360 ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype type,
00361                   char *varcharsize,
00362                   char *arrsize,
00363                   const char *siz,
00364                   const char *prefix,
00365                   int counter)
00366 {
00367     if (type == ECPGt_NO_INDICATOR)
00368         fprintf(o, "\n\tECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ");
00369     else if (type == ECPGt_descriptor)
00370         /* remember that name here already contains quotes (if needed) */
00371         fprintf(o, "\n\tECPGt_descriptor, %s, 0L, 0L, 0L, ", name);
00372     else if (type == ECPGt_sqlda)
00373         fprintf(o, "\n\tECPGt_sqlda, &%s, 0L, 0L, 0L, ", name);
00374     else
00375     {
00376         char       *variable = (char *) mm_alloc(strlen(name) + ((prefix == NULL) ? 0 : strlen(prefix)) + 4);
00377         char       *offset = (char *) mm_alloc(strlen(name) + strlen("sizeof(struct varchar_)") + 1 + strlen(varcharsize) + sizeof(int) * CHAR_BIT * 10 / 3);
00378 
00379         switch (type)
00380         {
00381                 /*
00382                  * we have to use the & operator except for arrays and
00383                  * pointers
00384                  */
00385 
00386             case ECPGt_varchar:
00387 
00388                 /*
00389                  * we have to use the pointer except for arrays with given
00390                  * bounds
00391                  */
00392                 if (((atoi(arrsize) > 0) ||
00393                      (atoi(arrsize) == 0 && strcmp(arrsize, "0") != 0)) &&
00394                     siz == NULL)
00395                     sprintf(variable, "(%s%s)", prefix ? prefix : "", name);
00396                 else
00397                     sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
00398 
00399                 /*
00400                  * If we created a varchar structure atomatically, counter is
00401                  * greater than 0.
00402                  */
00403                 if (counter)
00404                     sprintf(offset, "sizeof(struct varchar_%d)", counter);
00405                 else
00406                     sprintf(offset, "sizeof(struct varchar)");
00407                 break;
00408             case ECPGt_char:
00409             case ECPGt_unsigned_char:
00410             case ECPGt_char_variable:
00411             case ECPGt_string:
00412 
00413                 /*
00414                  * we have to use the pointer except for arrays with given
00415                  * bounds, ecpglib will distinguish between * and []
00416                  */
00417                 if ((atoi(varcharsize) > 1 ||
00418                      (atoi(arrsize) > 0) ||
00419                  (atoi(varcharsize) == 0 && strcmp(varcharsize, "0") != 0) ||
00420                      (atoi(arrsize) == 0 && strcmp(arrsize, "0") != 0))
00421                     && siz == NULL)
00422                     sprintf(variable, "(%s%s)", prefix ? prefix : "", name);
00423                 else
00424                     sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
00425 
00426                 sprintf(offset, "(%s)*sizeof(char)", strcmp(varcharsize, "0") == 0 ? "1" : varcharsize);
00427                 break;
00428             case ECPGt_numeric:
00429 
00430                 /*
00431                  * we have to use a pointer here
00432                  */
00433                 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
00434                 sprintf(offset, "sizeof(numeric)");
00435                 break;
00436             case ECPGt_interval:
00437 
00438                 /*
00439                  * we have to use a pointer here
00440                  */
00441                 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
00442                 sprintf(offset, "sizeof(interval)");
00443                 break;
00444             case ECPGt_date:
00445 
00446                 /*
00447                  * we have to use a pointer and translate the variable type
00448                  */
00449                 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
00450                 sprintf(offset, "sizeof(date)");
00451                 break;
00452             case ECPGt_timestamp:
00453 
00454                 /*
00455                  * we have to use a pointer and translate the variable type
00456                  */
00457                 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
00458                 sprintf(offset, "sizeof(timestamp)");
00459                 break;
00460             case ECPGt_const:
00461 
00462                 /*
00463                  * just dump the const as string
00464                  */
00465                 sprintf(variable, "\"%s\"", name);
00466                 sprintf(offset, "strlen(\"%s\")", name);
00467                 break;
00468             default:
00469 
00470                 /*
00471                  * we have to use the pointer except for arrays with given
00472                  * bounds
00473                  */
00474                 if (((atoi(arrsize) > 0) ||
00475                      (atoi(arrsize) == 0 && strcmp(arrsize, "0") != 0)) &&
00476                     siz == NULL)
00477                     sprintf(variable, "(%s%s)", prefix ? prefix : "", name);
00478                 else
00479                     sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
00480 
00481                 sprintf(offset, "sizeof(%s)", ecpg_type_name(type));
00482                 break;
00483         }
00484 
00485         if (atoi(arrsize) < 0)
00486             strcpy(arrsize, "1");
00487 
00488         if (siz == NULL || strlen(siz) == 0 || strcmp(arrsize, "0") == 0 || strcmp(arrsize, "1") == 0)
00489             fprintf(o, "\n\t%s,%s,(long)%s,(long)%s,%s, ", get_type(type), variable, varcharsize, arrsize, offset);
00490         else
00491             fprintf(o, "\n\t%s,%s,(long)%s,(long)%s,%s, ", get_type(type), variable, varcharsize, arrsize, siz);
00492 
00493         free(variable);
00494         free(offset);
00495     }
00496 }
00497 
00498 
00499 /* Penetrate a struct and dump the contents. */
00500 static void
00501 ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, char *arrsiz, struct ECPGtype * type, struct ECPGtype * ind_type, const char *prefix, const char *ind_prefix)
00502 {
00503     /*
00504      * If offset is NULL, then this is the first recursive level. If not then
00505      * we are in a struct in a struct and the offset is used as offset.
00506      */
00507     struct ECPGstruct_member *p,
00508                *ind_p = NULL;
00509     char        *pbuf = (char *) mm_alloc(strlen(name) + ((prefix == NULL) ? 0 : strlen(prefix)) + 3);
00510     char        *ind_pbuf = (char *) mm_alloc(strlen(ind_name) + ((ind_prefix == NULL) ? 0 : strlen(ind_prefix)) + 3);
00511 
00512     if (atoi(arrsiz) == 1)
00513         sprintf(pbuf, "%s%s.", prefix ? prefix : "", name);
00514     else
00515         sprintf(pbuf, "%s%s->", prefix ? prefix : "", name);
00516 
00517     prefix = pbuf;
00518 
00519     if (ind_type == &ecpg_no_indicator)
00520         ind_p = &struct_no_indicator;
00521     else if (ind_type != NULL)
00522     {
00523         if (atoi(arrsiz) == 1)
00524             sprintf(ind_pbuf, "%s%s.", ind_prefix ? ind_prefix : "", ind_name);
00525         else
00526             sprintf(ind_pbuf, "%s%s->", ind_prefix ? ind_prefix : "", ind_name);
00527 
00528         ind_prefix = ind_pbuf;
00529         ind_p = ind_type->u.members;
00530     }
00531 
00532     for (p = type->u.members; p; p = p->next)
00533     {
00534         ECPGdump_a_type(o, p->name, p->type, -1,
00535                         (ind_p != NULL) ? ind_p->name : NULL,
00536                         (ind_p != NULL) ? ind_p->type : NULL,
00537                         -1,
00538                         prefix, ind_prefix, arrsiz, type->struct_sizeof,
00539                         (ind_p != NULL) ? ind_type->struct_sizeof : NULL);
00540         if (ind_p != NULL && ind_p != &struct_no_indicator)
00541             ind_p = ind_p->next;
00542     }
00543 
00544     free(pbuf);
00545     free(ind_pbuf);
00546 }
00547 
00548 void
00549 ECPGfree_struct_member(struct ECPGstruct_member * rm)
00550 {
00551     while (rm)
00552     {
00553         struct ECPGstruct_member *p = rm;
00554 
00555         rm = rm->next;
00556         free(p->name);
00557         free(p->type);
00558         free(p);
00559     }
00560 }
00561 
00562 void
00563 ECPGfree_type(struct ECPGtype * type)
00564 {
00565     if (!IS_SIMPLE_TYPE(type->type))
00566     {
00567         switch (type->type)
00568         {
00569             case ECPGt_array:
00570                 switch (type->u.element->type)
00571                 {
00572                     case ECPGt_array:
00573                         base_yyerror("internal error: found multidimensional array\n");
00574                         break;
00575                     case ECPGt_struct:
00576                     case ECPGt_union:
00577                         /* Array of structs. */
00578                         ECPGfree_struct_member(type->u.element->u.members);
00579                         free(type->u.element);
00580                         break;
00581                     default:
00582                         if (!IS_SIMPLE_TYPE(type->u.element->type))
00583                             base_yyerror("internal error: unknown datatype, please report this to <[email protected]>");
00584 
00585                         free(type->u.element);
00586                 }
00587                 break;
00588             case ECPGt_struct:
00589             case ECPGt_union:
00590                 ECPGfree_struct_member(type->u.members);
00591                 break;
00592             default:
00593                 mmerror(PARSE_ERROR, ET_ERROR, "unrecognized variable type code %d", type->type);
00594                 break;
00595         }
00596     }
00597     free(type);
00598 }
00599 
00600 const char *
00601 get_dtype(enum ECPGdtype type)
00602 {
00603     switch (type)
00604     {
00605         case ECPGd_count:
00606             return ("ECPGd_countr");
00607             break;
00608         case ECPGd_data:
00609             return ("ECPGd_data");
00610             break;
00611         case ECPGd_di_code:
00612             return ("ECPGd_di_code");
00613             break;
00614         case ECPGd_di_precision:
00615             return ("ECPGd_di_precision");
00616             break;
00617         case ECPGd_indicator:
00618             return ("ECPGd_indicator");
00619             break;
00620         case ECPGd_key_member:
00621             return ("ECPGd_key_member");
00622             break;
00623         case ECPGd_length:
00624             return ("ECPGd_length");
00625             break;
00626         case ECPGd_name:
00627             return ("ECPGd_name");
00628             break;
00629         case ECPGd_nullable:
00630             return ("ECPGd_nullable");
00631             break;
00632         case ECPGd_octet:
00633             return ("ECPGd_octet");
00634             break;
00635         case ECPGd_precision:
00636             return ("ECPGd_precision");
00637             break;
00638         case ECPGd_ret_length:
00639             return ("ECPGd_ret_length");
00640         case ECPGd_ret_octet:
00641             return ("ECPGd_ret_octet");
00642             break;
00643         case ECPGd_scale:
00644             return ("ECPGd_scale");
00645             break;
00646         case ECPGd_type:
00647             return ("ECPGd_type");
00648             break;
00649         case ECPGd_cardinality:
00650             return ("ECPGd_cardinality");
00651         default:
00652             mmerror(PARSE_ERROR, ET_ERROR, "unrecognized descriptor item code %d", type);
00653     }
00654 
00655     return NULL;
00656 }