1 /* 2 * functions needed for descriptor handling 3 * 4 * src/interfaces/ecpg/preproc/descriptor.c 5 * 6 * since descriptor might be either a string constant or a string var 7 * we need to check for a constant if we expect a constant 8 */ 9 10 #include "postgres_fe.h" 11 12 #include "preproc_extern.h" 13 14 /* 15 * assignment handling function (descriptor) 16 */ 17 18 static struct assignment *assignments; 19 20 void 21 push_assignment(char *var, enum ECPGdtype value) 22 { 23 struct assignment *new = (struct assignment *) mm_alloc(sizeof(struct assignment)); 24 25 new->next = assignments; 26 new->variable = mm_alloc(strlen(var) + 1); 27 strcpy(new->variable, var); 28 new->value = value; 29 assignments = new; 30 } 31 32 static void 33 drop_assignments(void) 34 { 35 while (assignments) 36 { 37 struct assignment *old_head = assignments; 38 39 assignments = old_head->next; 40 free(old_head->variable); 41 free(old_head); 42 } 43 } 44 45 static void 46 ECPGnumeric_lvalue(char *name) 47 { 48 const struct variable *v = find_variable(name); 49 50 switch (v->type->type) 51 { 52 case ECPGt_short: 53 case ECPGt_int: 54 case ECPGt_long: 55 case ECPGt_long_long: 56 case ECPGt_unsigned_short: 57 case ECPGt_unsigned_int: 58 case ECPGt_unsigned_long: 59 case ECPGt_unsigned_long_long: 60 case ECPGt_const: 61 fputs(name, base_yyout); 62 break; 63 default: 64 mmerror(PARSE_ERROR, ET_ERROR, "variable \"%s\" must have a numeric type", name); 65 break; 66 } 67 } 68 69 /* 70 * descriptor name lookup 71 */ 72 73 static struct descriptor *descriptors; 74 75 void 76 add_descriptor(char *name, char *connection) 77 { 78 struct descriptor *new; 79 80 if (name[0] != '"') 81 return; 82 83 new = (struct descriptor *) mm_alloc(sizeof(struct descriptor)); 84 85 new->next = descriptors; 86 new->name = mm_alloc(strlen(name) + 1); 87 strcpy(new->name, name); 88 if (connection) 89 { 90 new->connection = mm_alloc(strlen(connection) + 1); 91 strcpy(new->connection, connection); 92 } 93 else 94 new->connection = connection; 95 descriptors = new; 96 } 97 98 void 99 drop_descriptor(char *name, char *connection) 100 { 101 struct descriptor *i; 102 struct descriptor **lastptr = &descriptors; 103 104 if (name[0] != '"') 105 return; 106 107 for (i = descriptors; i; lastptr = &i->next, i = i->next) 108 { 109 if (strcmp(name, i->name) == 0) 110 { 111 if ((!connection && !i->connection) 112 || (connection && i->connection 113 && strcmp(connection, i->connection) == 0)) 114 { 115 *lastptr = i->next; 116 if (i->connection) 117 free(i->connection); 118 free(i->name); 119 free(i); 120 return; 121 } 122 } 123 } 124 mmerror(PARSE_ERROR, ET_WARNING, "descriptor \"%s\" does not exist", name); 125 } 126 127 struct descriptor 128 * 129 lookup_descriptor(char *name, char *connection) 130 { 131 struct descriptor *i; 132 133 if (name[0] != '"') 134 return NULL; 135 136 for (i = descriptors; i; i = i->next) 137 { 138 if (strcmp(name, i->name) == 0) 139 { 140 if ((!connection && !i->connection) 141 || (connection && i->connection 142 && strcmp(connection, i->connection) == 0)) 143 return i; 144 } 145 } 146 mmerror(PARSE_ERROR, ET_WARNING, "descriptor \"%s\" does not exist", name); 147 return NULL; 148 } 149 150 void 151 output_get_descr_header(char *desc_name) 152 { 153 struct assignment *results; 154 155 fprintf(base_yyout, "{ ECPGget_desc_header(__LINE__, %s, &(", desc_name); 156 for (results = assignments; results != NULL; results = results->next) 157 { 158 if (results->value == ECPGd_count) 159 ECPGnumeric_lvalue(results->variable); 160 else 161 mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value); 162 } 163 164 drop_assignments(); 165 fprintf(base_yyout, "));\n"); 166 whenever_action(3); 167 } 168 169 void 170 output_get_descr(char *desc_name, char *index) 171 { 172 struct assignment *results; 173 174 fprintf(base_yyout, "{ ECPGget_desc(__LINE__, %s, %s,", desc_name, index); 175 for (results = assignments; results != NULL; results = results->next) 176 { 177 const struct variable *v = find_variable(results->variable); 178 char *str_zero = mm_strdup("0"); 179 180 switch (results->value) 181 { 182 case ECPGd_nullable: 183 mmerror(PARSE_ERROR, ET_WARNING, "nullable is always 1"); 184 break; 185 case ECPGd_key_member: 186 mmerror(PARSE_ERROR, ET_WARNING, "key_member is always 0"); 187 break; 188 default: 189 break; 190 } 191 fprintf(base_yyout, "%s,", get_dtype(results->value)); 192 ECPGdump_a_type(base_yyout, v->name, v->type, v->brace_level, 193 NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL); 194 free(str_zero); 195 } 196 drop_assignments(); 197 fputs("ECPGd_EODT);\n", base_yyout); 198 199 whenever_action(2 | 1); 200 } 201 202 void 203 output_set_descr_header(char *desc_name) 204 { 205 struct assignment *results; 206 207 fprintf(base_yyout, "{ ECPGset_desc_header(__LINE__, %s, (int)(", desc_name); 208 for (results = assignments; results != NULL; results = results->next) 209 { 210 if (results->value == ECPGd_count) 211 ECPGnumeric_lvalue(results->variable); 212 else 213 mmerror(PARSE_ERROR, ET_WARNING, "descriptor header item \"%d\" does not exist", results->value); 214 } 215 216 drop_assignments(); 217 fprintf(base_yyout, "));\n"); 218 whenever_action(3); 219 } 220 221 static const char * 222 descriptor_item_name(enum ECPGdtype itemcode) 223 { 224 switch (itemcode) 225 { 226 case ECPGd_cardinality: 227 return "CARDINALITY"; 228 case ECPGd_count: 229 return "COUNT"; 230 case ECPGd_data: 231 return "DATA"; 232 case ECPGd_di_code: 233 return "DATETIME_INTERVAL_CODE"; 234 case ECPGd_di_precision: 235 return "DATETIME_INTERVAL_PRECISION"; 236 case ECPGd_indicator: 237 return "INDICATOR"; 238 case ECPGd_key_member: 239 return "KEY_MEMBER"; 240 case ECPGd_length: 241 return "LENGTH"; 242 case ECPGd_name: 243 return "NAME"; 244 case ECPGd_nullable: 245 return "NULLABLE"; 246 case ECPGd_octet: 247 return "OCTET_LENGTH"; 248 case ECPGd_precision: 249 return "PRECISION"; 250 case ECPGd_ret_length: 251 return "RETURNED_LENGTH"; 252 case ECPGd_ret_octet: 253 return "RETURNED_OCTET_LENGTH"; 254 case ECPGd_scale: 255 return "SCALE"; 256 case ECPGd_type: 257 return "TYPE"; 258 default: 259 return NULL; 260 } 261 } 262 263 void 264 output_set_descr(char *desc_name, char *index) 265 { 266 struct assignment *results; 267 268 fprintf(base_yyout, "{ ECPGset_desc(__LINE__, %s, %s,", desc_name, index); 269 for (results = assignments; results != NULL; results = results->next) 270 { 271 const struct variable *v = find_variable(results->variable); 272 273 switch (results->value) 274 { 275 case ECPGd_cardinality: 276 case ECPGd_di_code: 277 case ECPGd_di_precision: 278 case ECPGd_precision: 279 case ECPGd_scale: 280 mmfatal(PARSE_ERROR, "descriptor item \"%s\" is not implemented", 281 descriptor_item_name(results->value)); 282 break; 283 284 case ECPGd_key_member: 285 case ECPGd_name: 286 case ECPGd_nullable: 287 case ECPGd_octet: 288 case ECPGd_ret_length: 289 case ECPGd_ret_octet: 290 mmfatal(PARSE_ERROR, "descriptor item \"%s\" cannot be set", 291 descriptor_item_name(results->value)); 292 break; 293 294 case ECPGd_data: 295 case ECPGd_indicator: 296 case ECPGd_length: 297 case ECPGd_type: 298 { 299 char *str_zero = mm_strdup("0"); 300 301 fprintf(base_yyout, "%s,", get_dtype(results->value)); 302 ECPGdump_a_type(base_yyout, v->name, v->type, v->brace_level, 303 NULL, NULL, -1, NULL, NULL, str_zero, NULL, NULL); 304 free(str_zero); 305 } 306 break; 307 308 default: 309 ; 310 } 311 } 312 drop_assignments(); 313 fputs("ECPGd_EODT);\n", base_yyout); 314 315 whenever_action(2 | 1); 316 } 317 318 /* I consider dynamic allocation overkill since at most two descriptor 319 variables are possible per statement. (input and output descriptor) 320 And descriptors are no normal variables, so they don't belong into 321 the variable list. 322 */ 323 324 #define MAX_DESCRIPTOR_NAMELEN 128 325 struct variable * 326 descriptor_variable(const char *name, int input) 327 { 328 static char descriptor_names[2][MAX_DESCRIPTOR_NAMELEN]; 329 static struct ECPGtype descriptor_type = {ECPGt_descriptor, NULL, NULL, NULL, {NULL}, 0}; 330 static struct variable varspace[2] = { 331 {descriptor_names[0], &descriptor_type, 0, NULL}, 332 {descriptor_names[1], &descriptor_type, 0, NULL} 333 }; 334 335 strlcpy(descriptor_names[input], name, sizeof(descriptor_names[input])); 336 return &varspace[input]; 337 } 338 339 struct variable * 340 sqlda_variable(const char *name) 341 { 342 struct variable *p = (struct variable *) mm_alloc(sizeof(struct variable)); 343 344 p->name = mm_strdup(name); 345 p->type = (struct ECPGtype *) mm_alloc(sizeof(struct ECPGtype)); 346 p->type->type = ECPGt_sqlda; 347 p->type->size = NULL; 348 p->type->struct_sizeof = NULL; 349 p->type->u.element = NULL; 350 p->type->counter = 0; 351 p->brace_level = 0; 352 p->next = NULL; 353 354 return p; 355 } 356