00001
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
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
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
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
00055
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
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;
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:
00179 return ("ECPGt_NO_INDICATOR");
00180 break;
00181 case ECPGt_char_variable:
00182 return ("ECPGt_char_variable");
00183 break;
00184 case ECPGt_const:
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
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
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)");
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:
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
00358
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
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
00383
00384
00385
00386 case ECPGt_varchar:
00387
00388
00389
00390
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
00401
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
00415
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
00432
00433 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
00434 sprintf(offset, "sizeof(numeric)");
00435 break;
00436 case ECPGt_interval:
00437
00438
00439
00440
00441 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
00442 sprintf(offset, "sizeof(interval)");
00443 break;
00444 case ECPGt_date:
00445
00446
00447
00448
00449 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
00450 sprintf(offset, "sizeof(date)");
00451 break;
00452 case ECPGt_timestamp:
00453
00454
00455
00456
00457 sprintf(variable, "&(%s%s)", prefix ? prefix : "", name);
00458 sprintf(offset, "sizeof(timestamp)");
00459 break;
00460 case ECPGt_const:
00461
00462
00463
00464
00465 sprintf(variable, "\"%s\"", name);
00466 sprintf(offset, "strlen(\"%s\")", name);
00467 break;
00468 default:
00469
00470
00471
00472
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
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
00505
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
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 }