1/* src/interfaces/ecpg/preproc/ecpg.trailer */ 2 3statements: /*EMPTY*/ 4 | statements statement 5 ; 6 7statement: ecpgstart at stmt ';' { connection = NULL; } 8 | ecpgstart stmt ';' 9 | ecpgstart ECPGVarDeclaration 10 { 11 fprintf(base_yyout, "%s", $2); 12 free($2); 13 output_line_number(); 14 } 15 | ECPGDeclaration 16 | c_thing { fprintf(base_yyout, "%s", $1); free($1); } 17 | CPP_LINE { fprintf(base_yyout, "%s", $1); free($1); } 18 | '{' { braces_open++; fputs("{", base_yyout); } 19 | '}' 20 { 21 remove_typedefs(braces_open); 22 remove_variables(braces_open--); 23 if (braces_open == 0) 24 { 25 free(current_function); 26 current_function = NULL; 27 } 28 fputs("}", base_yyout); 29 } 30 ; 31 32CreateAsStmt: CREATE OptTemp TABLE create_as_target AS {FoundInto = 0;} SelectStmt opt_with_data 33 { 34 if (FoundInto == 1) 35 mmerror(PARSE_ERROR, ET_ERROR, "CREATE TABLE AS cannot specify INTO"); 36 37 $$ = cat_str(7, mm_strdup("create"), $2, mm_strdup("table"), $4, mm_strdup("as"), $7, $8); 38 } 39 | CREATE OptTemp TABLE IF_P NOT EXISTS create_as_target AS {FoundInto = 0;} SelectStmt opt_with_data 40 { 41 if (FoundInto == 1) 42 mmerror(PARSE_ERROR, ET_ERROR, "CREATE TABLE AS cannot specify INTO"); 43 44 $$ = cat_str(7, mm_strdup("create"), $2, mm_strdup("table if not exists"), $7, mm_strdup("as"), $10, $11); 45 } 46 ; 47 48at: AT connection_object 49 { 50 connection = $2; 51 /* 52 * Do we have a variable as connection target? Remove the variable 53 * from the variable list or else it will be used twice. 54 */ 55 if (argsinsert != NULL) 56 argsinsert = NULL; 57 } 58 ; 59 60/* 61 * the exec sql connect statement: connect to the given database 62 */ 63ECPGConnect: SQL_CONNECT TO connection_target opt_connection_name opt_user 64 { $$ = cat_str(5, $3, mm_strdup(","), $5, mm_strdup(","), $4); } 65 | SQL_CONNECT TO DEFAULT 66 { $$ = mm_strdup("NULL, NULL, NULL, \"DEFAULT\""); } 67 /* also allow ORACLE syntax */ 68 | SQL_CONNECT ora_user 69 { $$ = cat_str(3, mm_strdup("NULL,"), $2, mm_strdup(", NULL")); } 70 | DATABASE connection_target 71 { $$ = cat2_str($2, mm_strdup(", NULL, NULL, NULL")); } 72 ; 73 74connection_target: opt_database_name opt_server opt_port 75 { 76 /* old style: dbname[@server][:port] */ 77 if (strlen($2) > 0 && *($2) != '@') 78 mmerror(PARSE_ERROR, ET_ERROR, "expected \"@\", found \"%s\"", $2); 79 80 /* C strings need to be handled differently */ 81 if ($1[0] == '\"') 82 $$ = $1; 83 else 84 $$ = make3_str(mm_strdup("\""), make3_str($1, $2, $3), mm_strdup("\"")); 85 } 86 | db_prefix ':' server opt_port '/' opt_database_name opt_options 87 { 88 /* new style: <tcp|unix>:postgresql://server[:port][/dbname] */ 89 if (strncmp($1, "unix:postgresql", strlen("unix:postgresql")) != 0 && strncmp($1, "tcp:postgresql", strlen("tcp:postgresql")) != 0) 90 mmerror(PARSE_ERROR, ET_ERROR, "only protocols \"tcp\" and \"unix\" and database type \"postgresql\" are supported"); 91 92 if (strncmp($3, "//", strlen("//")) != 0) 93 mmerror(PARSE_ERROR, ET_ERROR, "expected \"://\", found \"%s\"", $3); 94 95 if (strncmp($1, "unix", strlen("unix")) == 0 && 96 strncmp($3 + strlen("//"), "localhost", strlen("localhost")) != 0 && 97 strncmp($3 + strlen("//"), "127.0.0.1", strlen("127.0.0.1")) != 0) 98 mmerror(PARSE_ERROR, ET_ERROR, "Unix-domain sockets only work on \"localhost\" but not on \"%s\"", $3 + strlen("//")); 99 100 $$ = make3_str(make3_str(mm_strdup("\""), $1, mm_strdup(":")), $3, make3_str(make3_str($4, mm_strdup("/"), $6), $7, mm_strdup("\""))); 101 } 102 | char_variable 103 { 104 $$ = $1; 105 } 106 | ecpg_sconst 107 { 108 /* We can only process double quoted strings not single quotes ones, 109 * so we change the quotes. 110 * Note, that the rule for ecpg_sconst adds these single quotes. */ 111 $1[0] = '\"'; 112 $1[strlen($1)-1] = '\"'; 113 $$ = $1; 114 } 115 ; 116 117opt_database_name: database_name { $$ = $1; } 118 | /*EMPTY*/ { $$ = EMPTY; } 119 ; 120 121db_prefix: ecpg_ident cvariable 122 { 123 if (strcmp($2, "postgresql") != 0 && strcmp($2, "postgres") != 0) 124 mmerror(PARSE_ERROR, ET_ERROR, "expected \"postgresql\", found \"%s\"", $2); 125 126 if (strcmp($1, "tcp") != 0 && strcmp($1, "unix") != 0) 127 mmerror(PARSE_ERROR, ET_ERROR, "invalid connection type: %s", $1); 128 129 $$ = make3_str($1, mm_strdup(":"), $2); 130 } 131 ; 132 133server: Op server_name 134 { 135 if (strcmp($1, "@") != 0 && strcmp($1, "//") != 0) 136 mmerror(PARSE_ERROR, ET_ERROR, "expected \"@\" or \"://\", found \"%s\"", $1); 137 138 $$ = make2_str($1, $2); 139 } 140 ; 141 142opt_server: server { $$ = $1; } 143 | /*EMPTY*/ { $$ = EMPTY; } 144 ; 145 146server_name: ColId { $$ = $1; } 147 | ColId '.' server_name { $$ = make3_str($1, mm_strdup("."), $3); } 148 | IP { $$ = make_name(); } 149 ; 150 151opt_port: ':' Iconst { $$ = make2_str(mm_strdup(":"), $2); } 152 | /*EMPTY*/ { $$ = EMPTY; } 153 ; 154 155opt_connection_name: AS connection_object { $$ = $2; } 156 | /*EMPTY*/ { $$ = mm_strdup("NULL"); } 157 ; 158 159opt_user: USER ora_user { $$ = $2; } 160 | /*EMPTY*/ { $$ = mm_strdup("NULL, NULL"); } 161 ; 162 163ora_user: user_name 164 { $$ = cat2_str($1, mm_strdup(", NULL")); } 165 | user_name '/' user_name 166 { $$ = cat_str(3, $1, mm_strdup(","), $3); } 167 | user_name SQL_IDENTIFIED BY user_name 168 { $$ = cat_str(3, $1, mm_strdup(","), $4); } 169 | user_name USING user_name 170 { $$ = cat_str(3, $1, mm_strdup(","), $3); } 171 ; 172 173user_name: RoleId 174 { 175 if ($1[0] == '\"') 176 $$ = $1; 177 else 178 $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\"")); 179 } 180 | ecpg_sconst 181 { 182 if ($1[0] == '\"') 183 $$ = $1; 184 else 185 $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\"")); 186 } 187 | civar 188 { 189 enum ECPGttype type = argsinsert->variable->type->type; 190 191 /* if array see what's inside */ 192 if (type == ECPGt_array) 193 type = argsinsert->variable->type->u.element->type; 194 195 /* handle varchars */ 196 if (type == ECPGt_varchar) 197 $$ = make2_str(mm_strdup(argsinsert->variable->name), mm_strdup(".arr")); 198 else 199 $$ = mm_strdup(argsinsert->variable->name); 200 } 201 ; 202 203char_variable: cvariable 204 { 205 /* check if we have a string variable */ 206 struct variable *p = find_variable($1); 207 enum ECPGttype type = p->type->type; 208 209 /* If we have just one character this is not a string */ 210 if (atol(p->type->size) == 1) 211 mmerror(PARSE_ERROR, ET_ERROR, "invalid data type"); 212 else 213 { 214 /* if array see what's inside */ 215 if (type == ECPGt_array) 216 type = p->type->u.element->type; 217 218 switch (type) 219 { 220 case ECPGt_char: 221 case ECPGt_unsigned_char: 222 case ECPGt_string: 223 $$ = $1; 224 break; 225 case ECPGt_varchar: 226 $$ = make2_str($1, mm_strdup(".arr")); 227 break; 228 default: 229 mmerror(PARSE_ERROR, ET_ERROR, "invalid data type"); 230 $$ = $1; 231 break; 232 } 233 } 234 } 235 ; 236 237opt_options: Op connect_options 238 { 239 if (strlen($1) == 0) 240 mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement"); 241 242 if (strcmp($1, "?") != 0) 243 mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", $1); 244 245 $$ = make2_str(mm_strdup("?"), $2); 246 } 247 | /*EMPTY*/ { $$ = EMPTY; } 248 ; 249 250connect_options: ColId opt_opt_value 251 { 252 $$ = make2_str($1, $2); 253 } 254 | ColId opt_opt_value Op connect_options 255 { 256 if (strlen($3) == 0) 257 mmerror(PARSE_ERROR, ET_ERROR, "incomplete statement"); 258 259 if (strcmp($3, "&") != 0) 260 mmerror(PARSE_ERROR, ET_ERROR, "unrecognized token \"%s\"", $3); 261 262 $$ = cat_str(3, make2_str($1, $2), $3, $4); 263 } 264 ; 265 266opt_opt_value: /*EMPTY*/ 267 { $$ = EMPTY; } 268 | '=' Iconst 269 { $$ = make2_str(mm_strdup("="), $2); } 270 | '=' ecpg_ident 271 { $$ = make2_str(mm_strdup("="), $2); } 272 | '=' civar 273 { $$ = make2_str(mm_strdup("="), $2); } 274 ; 275 276prepared_name: name 277 { 278 if ($1[0] == '\"' && $1[strlen($1)-1] == '\"') /* already quoted? */ 279 $$ = $1; 280 else /* not quoted => convert to lowercase */ 281 { 282 size_t i; 283 284 for (i = 0; i< strlen($1); i++) 285 $1[i] = tolower((unsigned char) $1[i]); 286 287 $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\"")); 288 } 289 } 290 | char_variable { $$ = $1; } 291 ; 292 293/* 294 * Declare a prepared cursor. The syntax is different from the standard 295 * declare statement, so we create a new rule. 296 */ 297ECPGCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared_name 298 { 299 struct cursor *ptr, *this; 300 char *cursor_marker = $2[0] == ':' ? mm_strdup("$0") : mm_strdup($2); 301 int (* strcmp_fn)(const char *, const char *) = (($2[0] == ':' || $2[0] == '"') ? strcmp : pg_strcasecmp); 302 struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable)); 303 const char *con = connection ? connection : "NULL"; 304 char *comment; 305 306 for (ptr = cur; ptr != NULL; ptr = ptr->next) 307 { 308 if (strcmp_fn($2, ptr->name) == 0) 309 { 310 /* re-definition is a bug */ 311 if ($2[0] == ':') 312 mmerror(PARSE_ERROR, ET_ERROR, "using variable \"%s\" in different declare statements is not supported", $2+1); 313 else 314 mmerror(PARSE_ERROR, ET_ERROR, "cursor \"%s\" is already defined", $2); 315 } 316 } 317 318 this = (struct cursor *) mm_alloc(sizeof(struct cursor)); 319 320 /* initial definition */ 321 this->next = cur; 322 this->name = $2; 323 this->function = (current_function ? mm_strdup(current_function) : NULL); 324 this->connection = connection; 325 this->command = cat_str(6, mm_strdup("declare"), cursor_marker, $3, mm_strdup("cursor"), $5, mm_strdup("for $1")); 326 this->argsresult = NULL; 327 this->argsresult_oos = NULL; 328 329 thisquery->type = &ecpg_query; 330 thisquery->brace_level = 0; 331 thisquery->next = NULL; 332 thisquery->name = (char *) mm_alloc(sizeof("ECPGprepared_statement(, , __LINE__)") + strlen(con) + strlen($7)); 333 sprintf(thisquery->name, "ECPGprepared_statement(%s, %s, __LINE__)", con, $7); 334 335 this->argsinsert = NULL; 336 this->argsinsert_oos = NULL; 337 if ($2[0] == ':') 338 { 339 struct variable *var = find_variable($2 + 1); 340 remove_variable_from_list(&argsinsert, var); 341 add_variable_to_head(&(this->argsinsert), var, &no_indicator); 342 } 343 add_variable_to_head(&(this->argsinsert), thisquery, &no_indicator); 344 345 cur = this; 346 347 comment = cat_str(3, mm_strdup("/*"), mm_strdup(this->command), mm_strdup("*/")); 348 349 if ((braces_open > 0) && INFORMIX_MODE) /* we're in a function */ 350 $$ = cat_str(3, adjust_outofscope_cursor_vars(this), 351 mm_strdup("ECPG_informix_reset_sqlca();"), 352 comment); 353 else 354 $$ = cat2_str(adjust_outofscope_cursor_vars(this), comment); 355 } 356 ; 357 358ECPGExecuteImmediateStmt: EXECUTE IMMEDIATE execstring 359 { 360 /* execute immediate means prepare the statement and 361 * immediately execute it */ 362 $$ = $3; 363 }; 364/* 365 * variable declaration outside exec sql declare block 366 */ 367ECPGVarDeclaration: single_vt_declaration; 368 369single_vt_declaration: type_declaration { $$ = $1; } 370 | var_declaration { $$ = $1; } 371 ; 372 373precision: NumericOnly { $$ = $1; }; 374 375opt_scale: ',' NumericOnly { $$ = $2; } 376 | /* EMPTY */ { $$ = EMPTY; } 377 ; 378 379ecpg_interval: opt_interval { $$ = $1; } 380 | YEAR_P TO MINUTE_P { $$ = mm_strdup("year to minute"); } 381 | YEAR_P TO SECOND_P { $$ = mm_strdup("year to second"); } 382 | DAY_P TO DAY_P { $$ = mm_strdup("day to day"); } 383 | MONTH_P TO MONTH_P { $$ = mm_strdup("month to month"); } 384 ; 385 386/* 387 * variable declaration inside exec sql declare block 388 */ 389ECPGDeclaration: sql_startdeclare 390 { fputs("/* exec sql begin declare section */", base_yyout); } 391 var_type_declarations sql_enddeclare 392 { 393 fprintf(base_yyout, "%s/* exec sql end declare section */", $3); 394 free($3); 395 output_line_number(); 396 } 397 ; 398 399sql_startdeclare: ecpgstart BEGIN_P DECLARE SQL_SECTION ';' {}; 400 401sql_enddeclare: ecpgstart END_P DECLARE SQL_SECTION ';' {}; 402 403var_type_declarations: /*EMPTY*/ { $$ = EMPTY; } 404 | vt_declarations { $$ = $1; } 405 ; 406 407vt_declarations: single_vt_declaration { $$ = $1; } 408 | CPP_LINE { $$ = $1; } 409 | vt_declarations single_vt_declaration { $$ = cat2_str($1, $2); } 410 | vt_declarations CPP_LINE { $$ = cat2_str($1, $2); } 411 ; 412 413variable_declarations: var_declaration { $$ = $1; } 414 | variable_declarations var_declaration { $$ = cat2_str($1, $2); } 415 ; 416 417type_declaration: S_TYPEDEF 418 { 419 /* reset this variable so we see if there was */ 420 /* an initializer specified */ 421 initializer = 0; 422 } 423 var_type opt_pointer ECPGColLabelCommon opt_array_bounds ';' 424 { 425 add_typedef($5, $6.index1, $6.index2, $3.type_enum, $3.type_dimension, $3.type_index, initializer, *$4 ? 1 : 0); 426 427 fprintf(base_yyout, "typedef %s %s %s %s;\n", $3.type_str, *$4 ? "*" : "", $5, $6.str); 428 output_line_number(); 429 $$ = mm_strdup(""); 430 }; 431 432var_declaration: storage_declaration 433 var_type 434 { 435 actual_type[struct_level].type_enum = $2.type_enum; 436 actual_type[struct_level].type_str = $2.type_str; 437 actual_type[struct_level].type_dimension = $2.type_dimension; 438 actual_type[struct_level].type_index = $2.type_index; 439 actual_type[struct_level].type_sizeof = $2.type_sizeof; 440 441 actual_startline[struct_level] = hashline_number(); 442 } 443 variable_list ';' 444 { 445 $$ = cat_str(5, actual_startline[struct_level], $1, $2.type_str, $4, mm_strdup(";\n")); 446 } 447 | var_type 448 { 449 actual_type[struct_level].type_enum = $1.type_enum; 450 actual_type[struct_level].type_str = $1.type_str; 451 actual_type[struct_level].type_dimension = $1.type_dimension; 452 actual_type[struct_level].type_index = $1.type_index; 453 actual_type[struct_level].type_sizeof = $1.type_sizeof; 454 455 actual_startline[struct_level] = hashline_number(); 456 } 457 variable_list ';' 458 { 459 $$ = cat_str(4, actual_startline[struct_level], $1.type_str, $3, mm_strdup(";\n")); 460 } 461 | struct_union_type_with_symbol ';' 462 { 463 $$ = cat2_str($1, mm_strdup(";")); 464 } 465 ; 466 467opt_bit_field: ':' Iconst { $$ =cat2_str(mm_strdup(":"), $2); } 468 | /* EMPTY */ { $$ = EMPTY; } 469 ; 470 471storage_declaration: storage_clause storage_modifier 472 {$$ = cat2_str ($1, $2); } 473 | storage_clause {$$ = $1; } 474 | storage_modifier {$$ = $1; } 475 ; 476 477storage_clause : S_EXTERN { $$ = mm_strdup("extern"); } 478 | S_STATIC { $$ = mm_strdup("static"); } 479 | S_REGISTER { $$ = mm_strdup("register"); } 480 | S_AUTO { $$ = mm_strdup("auto"); } 481 ; 482 483storage_modifier : S_CONST { $$ = mm_strdup("const"); } 484 | S_VOLATILE { $$ = mm_strdup("volatile"); } 485 ; 486 487var_type: simple_type 488 { 489 $$.type_enum = $1; 490 $$.type_str = mm_strdup(ecpg_type_name($1)); 491 $$.type_dimension = mm_strdup("-1"); 492 $$.type_index = mm_strdup("-1"); 493 $$.type_sizeof = NULL; 494 } 495 | struct_union_type 496 { 497 $$.type_str = $1; 498 $$.type_dimension = mm_strdup("-1"); 499 $$.type_index = mm_strdup("-1"); 500 501 if (strncmp($1, "struct", sizeof("struct")-1) == 0) 502 { 503 $$.type_enum = ECPGt_struct; 504 $$.type_sizeof = ECPGstruct_sizeof; 505 } 506 else 507 { 508 $$.type_enum = ECPGt_union; 509 $$.type_sizeof = NULL; 510 } 511 } 512 | enum_type 513 { 514 $$.type_str = $1; 515 $$.type_enum = ECPGt_int; 516 $$.type_dimension = mm_strdup("-1"); 517 $$.type_index = mm_strdup("-1"); 518 $$.type_sizeof = NULL; 519 } 520 | ECPGColLabelCommon '(' precision opt_scale ')' 521 { 522 if (strcmp($1, "numeric") == 0) 523 { 524 $$.type_enum = ECPGt_numeric; 525 $$.type_str = mm_strdup("numeric"); 526 } 527 else if (strcmp($1, "decimal") == 0) 528 { 529 $$.type_enum = ECPGt_decimal; 530 $$.type_str = mm_strdup("decimal"); 531 } 532 else 533 { 534 mmerror(PARSE_ERROR, ET_ERROR, "only data types numeric and decimal have precision/scale argument"); 535 $$.type_enum = ECPGt_numeric; 536 $$.type_str = mm_strdup("numeric"); 537 } 538 539 $$.type_dimension = mm_strdup("-1"); 540 $$.type_index = mm_strdup("-1"); 541 $$.type_sizeof = NULL; 542 } 543 | ECPGColLabelCommon ecpg_interval 544 { 545 if (strlen($2) != 0 && strcmp ($1, "datetime") != 0 && strcmp ($1, "interval") != 0) 546 mmerror (PARSE_ERROR, ET_ERROR, "interval specification not allowed here"); 547 548 /* 549 * Check for type names that the SQL grammar treats as 550 * unreserved keywords 551 */ 552 if (strcmp($1, "varchar") == 0) 553 { 554 $$.type_enum = ECPGt_varchar; 555 $$.type_str = EMPTY; /*mm_strdup("varchar");*/ 556 $$.type_dimension = mm_strdup("-1"); 557 $$.type_index = mm_strdup("-1"); 558 $$.type_sizeof = NULL; 559 } 560 else if (strcmp($1, "float") == 0) 561 { 562 $$.type_enum = ECPGt_float; 563 $$.type_str = mm_strdup("float"); 564 $$.type_dimension = mm_strdup("-1"); 565 $$.type_index = mm_strdup("-1"); 566 $$.type_sizeof = NULL; 567 } 568 else if (strcmp($1, "double") == 0) 569 { 570 $$.type_enum = ECPGt_double; 571 $$.type_str = mm_strdup("double"); 572 $$.type_dimension = mm_strdup("-1"); 573 $$.type_index = mm_strdup("-1"); 574 $$.type_sizeof = NULL; 575 } 576 else if (strcmp($1, "numeric") == 0) 577 { 578 $$.type_enum = ECPGt_numeric; 579 $$.type_str = mm_strdup("numeric"); 580 $$.type_dimension = mm_strdup("-1"); 581 $$.type_index = mm_strdup("-1"); 582 $$.type_sizeof = NULL; 583 } 584 else if (strcmp($1, "decimal") == 0) 585 { 586 $$.type_enum = ECPGt_decimal; 587 $$.type_str = mm_strdup("decimal"); 588 $$.type_dimension = mm_strdup("-1"); 589 $$.type_index = mm_strdup("-1"); 590 $$.type_sizeof = NULL; 591 } 592 else if (strcmp($1, "date") == 0) 593 { 594 $$.type_enum = ECPGt_date; 595 $$.type_str = mm_strdup("date"); 596 $$.type_dimension = mm_strdup("-1"); 597 $$.type_index = mm_strdup("-1"); 598 $$.type_sizeof = NULL; 599 } 600 else if (strcmp($1, "timestamp") == 0) 601 { 602 $$.type_enum = ECPGt_timestamp; 603 $$.type_str = mm_strdup("timestamp"); 604 $$.type_dimension = mm_strdup("-1"); 605 $$.type_index = mm_strdup("-1"); 606 $$.type_sizeof = NULL; 607 } 608 else if (strcmp($1, "interval") == 0) 609 { 610 $$.type_enum = ECPGt_interval; 611 $$.type_str = mm_strdup("interval"); 612 $$.type_dimension = mm_strdup("-1"); 613 $$.type_index = mm_strdup("-1"); 614 $$.type_sizeof = NULL; 615 } 616 else if (strcmp($1, "datetime") == 0) 617 { 618 $$.type_enum = ECPGt_timestamp; 619 $$.type_str = mm_strdup("timestamp"); 620 $$.type_dimension = mm_strdup("-1"); 621 $$.type_index = mm_strdup("-1"); 622 $$.type_sizeof = NULL; 623 } 624 else if ((strcmp($1, "string") == 0) && INFORMIX_MODE) 625 { 626 $$.type_enum = ECPGt_string; 627 $$.type_str = mm_strdup("char"); 628 $$.type_dimension = mm_strdup("-1"); 629 $$.type_index = mm_strdup("-1"); 630 $$.type_sizeof = NULL; 631 } 632 else 633 { 634 /* this is for typedef'ed types */ 635 struct typedefs *this = get_typedef($1); 636 637 $$.type_str = (this->type->type_enum == ECPGt_varchar) ? EMPTY : mm_strdup(this->name); 638 $$.type_enum = this->type->type_enum; 639 $$.type_dimension = this->type->type_dimension; 640 $$.type_index = this->type->type_index; 641 if (this->type->type_sizeof && strlen(this->type->type_sizeof) != 0) 642 $$.type_sizeof = this->type->type_sizeof; 643 else 644 $$.type_sizeof = cat_str(3, mm_strdup("sizeof("), mm_strdup(this->name), mm_strdup(")")); 645 646 struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list); 647 } 648 } 649 | s_struct_union_symbol 650 { 651 /* this is for named structs/unions */ 652 char *name; 653 struct typedefs *this; 654 bool forward = (forward_name != NULL && strcmp($1.symbol, forward_name) == 0 && strcmp($1.su, "struct") == 0); 655 656 name = cat2_str($1.su, $1.symbol); 657 /* Do we have a forward definition? */ 658 if (!forward) 659 { 660 /* No */ 661 662 this = get_typedef(name); 663 $$.type_str = mm_strdup(this->name); 664 $$.type_enum = this->type->type_enum; 665 $$.type_dimension = this->type->type_dimension; 666 $$.type_index = this->type->type_index; 667 $$.type_sizeof = this->type->type_sizeof; 668 struct_member_list[struct_level] = ECPGstruct_member_dup(this->struct_member_list); 669 free(name); 670 } 671 else 672 { 673 $$.type_str = name; 674 $$.type_enum = ECPGt_long; 675 $$.type_dimension = mm_strdup("-1"); 676 $$.type_index = mm_strdup("-1"); 677 $$.type_sizeof = mm_strdup(""); 678 struct_member_list[struct_level] = NULL; 679 } 680 } 681 ; 682 683enum_type: ENUM_P symbol enum_definition 684 { $$ = cat_str(3, mm_strdup("enum"), $2, $3); } 685 | ENUM_P enum_definition 686 { $$ = cat2_str(mm_strdup("enum"), $2); } 687 | ENUM_P symbol 688 { $$ = cat2_str(mm_strdup("enum"), $2); } 689 ; 690 691enum_definition: '{' c_list '}' 692 { $$ = cat_str(3, mm_strdup("{"), $2, mm_strdup("}")); }; 693 694struct_union_type_with_symbol: s_struct_union_symbol 695 { 696 struct_member_list[struct_level++] = NULL; 697 if (struct_level >= STRUCT_DEPTH) 698 mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition"); 699 forward_name = mm_strdup($1.symbol); 700 } 701 '{' variable_declarations '}' 702 { 703 struct typedefs *ptr, *this; 704 struct this_type su_type; 705 706 ECPGfree_struct_member(struct_member_list[struct_level]); 707 struct_member_list[struct_level] = NULL; 708 struct_level--; 709 if (strncmp($1.su, "struct", sizeof("struct")-1) == 0) 710 su_type.type_enum = ECPGt_struct; 711 else 712 su_type.type_enum = ECPGt_union; 713 su_type.type_str = cat2_str($1.su, $1.symbol); 714 free(forward_name); 715 forward_name = NULL; 716 717 /* This is essentially a typedef but needs the keyword struct/union as well. 718 * So we create the typedef for each struct definition with symbol */ 719 for (ptr = types; ptr != NULL; ptr = ptr->next) 720 { 721 if (strcmp(su_type.type_str, ptr->name) == 0) 722 /* re-definition is a bug */ 723 mmerror(PARSE_ERROR, ET_ERROR, "type \"%s\" is already defined", su_type.type_str); 724 } 725 726 this = (struct typedefs *) mm_alloc(sizeof(struct typedefs)); 727 728 /* initial definition */ 729 this->next = types; 730 this->name = mm_strdup(su_type.type_str); 731 this->brace_level = braces_open; 732 this->type = (struct this_type *) mm_alloc(sizeof(struct this_type)); 733 this->type->type_enum = su_type.type_enum; 734 this->type->type_str = mm_strdup(su_type.type_str); 735 this->type->type_dimension = mm_strdup("-1"); /* dimension of array */ 736 this->type->type_index = mm_strdup("-1"); /* length of string */ 737 this->type->type_sizeof = ECPGstruct_sizeof; 738 this->struct_member_list = struct_member_list[struct_level]; 739 740 types = this; 741 $$ = cat_str(4, su_type.type_str, mm_strdup("{"), $4, mm_strdup("}")); 742 } 743 ; 744 745struct_union_type: struct_union_type_with_symbol { $$ = $1; } 746 | s_struct_union 747 { 748 struct_member_list[struct_level++] = NULL; 749 if (struct_level >= STRUCT_DEPTH) 750 mmerror(PARSE_ERROR, ET_ERROR, "too many levels in nested structure/union definition"); 751 } 752 '{' variable_declarations '}' 753 { 754 ECPGfree_struct_member(struct_member_list[struct_level]); 755 struct_member_list[struct_level] = NULL; 756 struct_level--; 757 $$ = cat_str(4, $1, mm_strdup("{"), $4, mm_strdup("}")); 758 } 759 ; 760 761s_struct_union_symbol: SQL_STRUCT symbol 762 { 763 $$.su = mm_strdup("struct"); 764 $$.symbol = $2; 765 ECPGstruct_sizeof = cat_str(3, mm_strdup("sizeof("), cat2_str(mm_strdup($$.su), mm_strdup($$.symbol)), mm_strdup(")")); 766 } 767 | UNION symbol 768 { 769 $$.su = mm_strdup("union"); 770 $$.symbol = $2; 771 } 772 ; 773 774s_struct_union: SQL_STRUCT 775 { 776 ECPGstruct_sizeof = mm_strdup(""); /* This must not be NULL to distinguish from simple types. */ 777 $$ = mm_strdup("struct"); 778 } 779 | UNION 780 { 781 $$ = mm_strdup("union"); 782 } 783 ; 784 785simple_type: unsigned_type { $$=$1; } 786 | opt_signed signed_type { $$=$2; } 787 ; 788 789unsigned_type: SQL_UNSIGNED SQL_SHORT { $$ = ECPGt_unsigned_short; } 790 | SQL_UNSIGNED SQL_SHORT INT_P { $$ = ECPGt_unsigned_short; } 791 | SQL_UNSIGNED { $$ = ECPGt_unsigned_int; } 792 | SQL_UNSIGNED INT_P { $$ = ECPGt_unsigned_int; } 793 | SQL_UNSIGNED SQL_LONG { $$ = ECPGt_unsigned_long; } 794 | SQL_UNSIGNED SQL_LONG INT_P { $$ = ECPGt_unsigned_long; } 795 | SQL_UNSIGNED SQL_LONG SQL_LONG 796 { 797#ifdef HAVE_LONG_LONG_INT 798 $$ = ECPGt_unsigned_long_long; 799#else 800 $$ = ECPGt_unsigned_long; 801#endif 802 } 803 | SQL_UNSIGNED SQL_LONG SQL_LONG INT_P 804 { 805#ifdef HAVE_LONG_LONG_INT 806 $$ = ECPGt_unsigned_long_long; 807#else 808 $$ = ECPGt_unsigned_long; 809#endif 810 } 811 | SQL_UNSIGNED CHAR_P { $$ = ECPGt_unsigned_char; } 812 ; 813 814signed_type: SQL_SHORT { $$ = ECPGt_short; } 815 | SQL_SHORT INT_P { $$ = ECPGt_short; } 816 | INT_P { $$ = ECPGt_int; } 817 | SQL_LONG { $$ = ECPGt_long; } 818 | SQL_LONG INT_P { $$ = ECPGt_long; } 819 | SQL_LONG SQL_LONG 820 { 821#ifdef HAVE_LONG_LONG_INT 822 $$ = ECPGt_long_long; 823#else 824 $$ = ECPGt_long; 825#endif 826 } 827 | SQL_LONG SQL_LONG INT_P 828 { 829#ifdef HAVE_LONG_LONG_INT 830 $$ = ECPGt_long_long; 831#else 832 $$ = ECPGt_long; 833#endif 834 } 835 | SQL_BOOL { $$ = ECPGt_bool; } 836 | CHAR_P { $$ = ECPGt_char; } 837 | DOUBLE_P { $$ = ECPGt_double; } 838 ; 839 840opt_signed: SQL_SIGNED 841 | /* EMPTY */ 842 ; 843 844variable_list: variable 845 { $$ = $1; } 846 | variable_list ',' variable 847 { 848 if (actual_type[struct_level].type_enum == ECPGt_varchar) 849 $$ = cat_str(3, $1, mm_strdup(";"), $3); 850 else 851 $$ = cat_str(3, $1, mm_strdup(","), $3); 852 } 853 ; 854 855variable: opt_pointer ECPGColLabel opt_array_bounds opt_bit_field opt_initializer 856 { 857 struct ECPGtype * type; 858 char *dimension = $3.index1; /* dimension of array */ 859 char *length = $3.index2; /* length of string */ 860 char *dim_str; 861 char *vcn; 862 863 adjust_array(actual_type[struct_level].type_enum, &dimension, &length, actual_type[struct_level].type_dimension, actual_type[struct_level].type_index, strlen($1), false); 864 865 switch (actual_type[struct_level].type_enum) 866 { 867 case ECPGt_struct: 868 case ECPGt_union: 869 if (atoi(dimension) < 0) 870 type = ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_str, actual_type[struct_level].type_sizeof); 871 else 872 type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], actual_type[struct_level].type_enum, actual_type[struct_level].type_str, actual_type[struct_level].type_sizeof), dimension); 873 874 $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5); 875 break; 876 877 case ECPGt_varchar: 878 if (atoi(dimension) < 0) 879 type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, varchar_counter); 880 else 881 type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, varchar_counter), dimension); 882 883 if (strcmp(dimension, "0") == 0 || abs(atoi(dimension)) == 1) 884 dim_str=mm_strdup(""); 885 else 886 dim_str=cat_str(3, mm_strdup("["), mm_strdup(dimension), mm_strdup("]")); 887 /* cannot check for atoi <= 0 because a defined constant will yield 0 here as well */ 888 if (atoi(length) < 0 || strcmp(length, "0") == 0) 889 mmerror(PARSE_ERROR, ET_ERROR, "pointers to varchar are not implemented"); 890 891 /* make sure varchar struct name is unique by adding a unique counter to its definition */ 892 vcn = (char *) mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); 893 sprintf(vcn, "%d", varchar_counter); 894 if (strcmp(dimension, "0") == 0) 895 $$ = cat_str(7, make2_str(mm_strdup(" struct varchar_"), vcn), mm_strdup(" { int len; char arr["), mm_strdup(length), mm_strdup("]; } *"), mm_strdup($2), $4, $5); 896 else 897 $$ = cat_str(8, make2_str(mm_strdup(" struct varchar_"), vcn), mm_strdup(" { int len; char arr["), mm_strdup(length), mm_strdup("]; } "), mm_strdup($2), dim_str, $4, $5); 898 varchar_counter++; 899 break; 900 901 case ECPGt_char: 902 case ECPGt_unsigned_char: 903 case ECPGt_string: 904 if (atoi(dimension) == -1) 905 { 906 int i = strlen($5); 907 908 if (atoi(length) == -1 && i > 0) /* char <var>[] = "string" */ 909 { 910 /* if we have an initializer but no string size set, let's use the initializer's length */ 911 free(length); 912 length = mm_alloc(i+sizeof("sizeof()")); 913 sprintf(length, "sizeof(%s)", $5+2); 914 } 915 type = ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0); 916 } 917 else 918 type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, length, 0), dimension); 919 920 $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5); 921 break; 922 923 default: 924 if (atoi(dimension) < 0) 925 type = ECPGmake_simple_type(actual_type[struct_level].type_enum, mm_strdup("1"), 0); 926 else 927 type = ECPGmake_array_type(ECPGmake_simple_type(actual_type[struct_level].type_enum, mm_strdup("1"), 0), dimension); 928 929 $$ = cat_str(5, $1, mm_strdup($2), $3.str, $4, $5); 930 break; 931 } 932 933 if (struct_level == 0) 934 new_variable($2, type, braces_open); 935 else 936 ECPGmake_struct_member($2, type, &(struct_member_list[struct_level - 1])); 937 938 free($2); 939 } 940 ; 941 942opt_initializer: /*EMPTY*/ 943 { $$ = EMPTY; } 944 | '=' c_term 945 { 946 initializer = 1; 947 $$ = cat2_str(mm_strdup("="), $2); 948 } 949 ; 950 951opt_pointer: /*EMPTY*/ { $$ = EMPTY; } 952 | '*' { $$ = mm_strdup("*"); } 953 | '*' '*' { $$ = mm_strdup("**"); } 954 ; 955 956/* 957 * We try to simulate the correct DECLARE syntax here so we get dynamic SQL 958 */ 959ECPGDeclare: DECLARE STATEMENT ecpg_ident 960 { 961 /* this is only supported for compatibility */ 962 $$ = cat_str(3, mm_strdup("/* declare statement"), $3, mm_strdup("*/")); 963 } 964 ; 965/* 966 * the exec sql disconnect statement: disconnect from the given database 967 */ 968ECPGDisconnect: SQL_DISCONNECT dis_name { $$ = $2; } 969 ; 970 971dis_name: connection_object { $$ = $1; } 972 | CURRENT_P { $$ = mm_strdup("\"CURRENT\""); } 973 | ALL { $$ = mm_strdup("\"ALL\""); } 974 | /* EMPTY */ { $$ = mm_strdup("\"CURRENT\""); } 975 ; 976 977connection_object: database_name { $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\"")); } 978 | DEFAULT { $$ = mm_strdup("\"DEFAULT\""); } 979 | char_variable { $$ = $1; } 980 ; 981 982execstring: char_variable 983 { $$ = $1; } 984 | CSTRING 985 { $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\"")); } 986 ; 987 988/* 989 * the exec sql free command to deallocate a previously 990 * prepared statement 991 */ 992ECPGFree: SQL_FREE cursor_name { $$ = $2; } 993 | SQL_FREE ALL { $$ = mm_strdup("all"); } 994 ; 995 996/* 997 * open is an open cursor, at the moment this has to be removed 998 */ 999ECPGOpen: SQL_OPEN cursor_name opt_ecpg_using 1000 { 1001 if ($2[0] == ':') 1002 remove_variable_from_list(&argsinsert, find_variable($2 + 1)); 1003 $$ = $2; 1004 } 1005 ; 1006 1007opt_ecpg_using: /*EMPTY*/ { $$ = EMPTY; } 1008 | ecpg_using { $$ = $1; } 1009 ; 1010 1011ecpg_using: USING using_list { $$ = EMPTY; } 1012 | using_descriptor { $$ = $1; } 1013 ; 1014 1015using_descriptor: USING SQL_P SQL_DESCRIPTOR quoted_ident_stringvar 1016 { 1017 add_variable_to_head(&argsinsert, descriptor_variable($4,0), &no_indicator); 1018 $$ = EMPTY; 1019 } 1020 | USING SQL_DESCRIPTOR name 1021 { 1022 add_variable_to_head(&argsinsert, sqlda_variable($3), &no_indicator); 1023 $$ = EMPTY; 1024 } 1025 ; 1026 1027into_descriptor: INTO SQL_P SQL_DESCRIPTOR quoted_ident_stringvar 1028 { 1029 add_variable_to_head(&argsresult, descriptor_variable($4,1), &no_indicator); 1030 $$ = EMPTY; 1031 } 1032 | INTO SQL_DESCRIPTOR name 1033 { 1034 add_variable_to_head(&argsresult, sqlda_variable($3), &no_indicator); 1035 $$ = EMPTY; 1036 } 1037 ; 1038 1039into_sqlda: INTO name 1040 { 1041 add_variable_to_head(&argsresult, sqlda_variable($2), &no_indicator); 1042 $$ = EMPTY; 1043 } 1044 ; 1045 1046using_list: UsingValue | UsingValue ',' using_list; 1047 1048UsingValue: UsingConst 1049 { 1050 char *length = mm_alloc(32); 1051 1052 sprintf(length, "%d", (int) strlen($1)); 1053 add_variable_to_head(&argsinsert, new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0), &no_indicator); 1054 } 1055 | civar { $$ = EMPTY; } 1056 | civarind { $$ = EMPTY; } 1057 ; 1058 1059UsingConst: Iconst { $$ = $1; } 1060 | '+' Iconst { $$ = cat_str(2, mm_strdup("+"), $2); } 1061 | '-' Iconst { $$ = cat_str(2, mm_strdup("-"), $2); } 1062 | ecpg_fconst { $$ = $1; } 1063 | '+' ecpg_fconst { $$ = cat_str(2, mm_strdup("+"), $2); } 1064 | '-' ecpg_fconst { $$ = cat_str(2, mm_strdup("-"), $2); } 1065 | ecpg_sconst { $$ = $1; } 1066 | ecpg_bconst { $$ = $1; } 1067 | ecpg_xconst { $$ = $1; } 1068 ; 1069 1070/* 1071 * We accept DESCRIBE [OUTPUT] but do nothing with DESCRIBE INPUT so far. 1072 */ 1073ECPGDescribe: SQL_DESCRIBE INPUT_P prepared_name using_descriptor 1074 { 1075 const char *con = connection ? connection : "NULL"; 1076 mmerror(PARSE_ERROR, ET_WARNING, "using unsupported DESCRIBE statement"); 1077 $$ = (char *) mm_alloc(sizeof("1, , ") + strlen(con) + strlen($3)); 1078 sprintf($$, "1, %s, %s", con, $3); 1079 } 1080 | SQL_DESCRIBE opt_output prepared_name using_descriptor 1081 { 1082 const char *con = connection ? connection : "NULL"; 1083 struct variable *var; 1084 1085 var = argsinsert->variable; 1086 remove_variable_from_list(&argsinsert, var); 1087 add_variable_to_head(&argsresult, var, &no_indicator); 1088 1089 $$ = (char *) mm_alloc(sizeof("0, , ") + strlen(con) + strlen($3)); 1090 sprintf($$, "0, %s, %s", con, $3); 1091 } 1092 | SQL_DESCRIBE opt_output prepared_name into_descriptor 1093 { 1094 const char *con = connection ? connection : "NULL"; 1095 $$ = (char *) mm_alloc(sizeof("0, , ") + strlen(con) + strlen($3)); 1096 sprintf($$, "0, %s, %s", con, $3); 1097 } 1098 | SQL_DESCRIBE INPUT_P prepared_name into_sqlda 1099 { 1100 const char *con = connection ? connection : "NULL"; 1101 mmerror(PARSE_ERROR, ET_WARNING, "using unsupported DESCRIBE statement"); 1102 $$ = (char *) mm_alloc(sizeof("1, , ") + strlen(con) + strlen($3)); 1103 sprintf($$, "1, %s, %s", con, $3); 1104 } 1105 | SQL_DESCRIBE opt_output prepared_name into_sqlda 1106 { 1107 const char *con = connection ? connection : "NULL"; 1108 $$ = (char *) mm_alloc(sizeof("0, , ") + strlen(con) + strlen($3)); 1109 sprintf($$, "0, %s, %s", con, $3); 1110 } 1111 ; 1112 1113opt_output: SQL_OUTPUT { $$ = mm_strdup("output"); } 1114 | /* EMPTY */ { $$ = EMPTY; } 1115 ; 1116 1117/* 1118 * dynamic SQL: descriptor based access 1119 * originally written by Christof Petig <christof.petig@wtal.de> 1120 * and Peter Eisentraut <peter.eisentraut@credativ.de> 1121 */ 1122 1123/* 1124 * allocate a descriptor 1125 */ 1126ECPGAllocateDescr: SQL_ALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar 1127 { 1128 add_descriptor($3,connection); 1129 $$ = $3; 1130 } 1131 ; 1132 1133 1134/* 1135 * deallocate a descriptor 1136 */ 1137ECPGDeallocateDescr: DEALLOCATE SQL_DESCRIPTOR quoted_ident_stringvar 1138 { 1139 drop_descriptor($3,connection); 1140 $$ = $3; 1141 } 1142 ; 1143 1144/* 1145 * manipulate a descriptor header 1146 */ 1147 1148ECPGGetDescriptorHeader: SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar ECPGGetDescHeaderItems 1149 { $$ = $3; } 1150 ; 1151 1152ECPGGetDescHeaderItems: ECPGGetDescHeaderItem 1153 | ECPGGetDescHeaderItems ',' ECPGGetDescHeaderItem 1154 ; 1155 1156ECPGGetDescHeaderItem: cvariable '=' desc_header_item 1157 { push_assignment($1, $3); } 1158 ; 1159 1160 1161ECPGSetDescriptorHeader: SET SQL_DESCRIPTOR quoted_ident_stringvar ECPGSetDescHeaderItems 1162 { $$ = $3; } 1163 ; 1164 1165ECPGSetDescHeaderItems: ECPGSetDescHeaderItem 1166 | ECPGSetDescHeaderItems ',' ECPGSetDescHeaderItem 1167 ; 1168 1169ECPGSetDescHeaderItem: desc_header_item '=' IntConstVar 1170 { 1171 push_assignment($3, $1); 1172 } 1173 ; 1174 1175IntConstVar: Iconst 1176 { 1177 char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); 1178 1179 sprintf(length, "%d", (int) strlen($1)); 1180 new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0); 1181 $$ = $1; 1182 } 1183 | cvariable 1184 { 1185 $$ = $1; 1186 } 1187 ; 1188 1189desc_header_item: SQL_COUNT { $$ = ECPGd_count; } 1190 ; 1191 1192/* 1193 * manipulate a descriptor 1194 */ 1195 1196ECPGGetDescriptor: SQL_GET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGGetDescItems 1197 { $$.str = $5; $$.name = $3; } 1198 ; 1199 1200ECPGGetDescItems: ECPGGetDescItem 1201 | ECPGGetDescItems ',' ECPGGetDescItem 1202 ; 1203 1204ECPGGetDescItem: cvariable '=' descriptor_item { push_assignment($1, $3); }; 1205 1206 1207ECPGSetDescriptor: SET SQL_DESCRIPTOR quoted_ident_stringvar VALUE_P IntConstVar ECPGSetDescItems 1208 { $$.str = $5; $$.name = $3; } 1209 ; 1210 1211ECPGSetDescItems: ECPGSetDescItem 1212 | ECPGSetDescItems ',' ECPGSetDescItem 1213 ; 1214 1215ECPGSetDescItem: descriptor_item '=' AllConstVar 1216 { 1217 push_assignment($3, $1); 1218 } 1219 ; 1220 1221AllConstVar: ecpg_fconst 1222 { 1223 char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); 1224 1225 sprintf(length, "%d", (int) strlen($1)); 1226 new_variable($1, ECPGmake_simple_type(ECPGt_const, length, 0), 0); 1227 $$ = $1; 1228 } 1229 1230 | IntConstVar 1231 { 1232 $$ = $1; 1233 } 1234 1235 | '-' ecpg_fconst 1236 { 1237 char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); 1238 char *var = cat2_str(mm_strdup("-"), $2); 1239 1240 sprintf(length, "%d", (int) strlen(var)); 1241 new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0); 1242 $$ = var; 1243 } 1244 1245 | '-' Iconst 1246 { 1247 char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); 1248 char *var = cat2_str(mm_strdup("-"), $2); 1249 1250 sprintf(length, "%d", (int) strlen(var)); 1251 new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0); 1252 $$ = var; 1253 } 1254 1255 | ecpg_sconst 1256 { 1257 char *length = mm_alloc(sizeof(int) * CHAR_BIT * 10 / 3); 1258 char *var = $1 + 1; 1259 1260 var[strlen(var) - 1] = '\0'; 1261 sprintf(length, "%d", (int) strlen(var)); 1262 new_variable(var, ECPGmake_simple_type(ECPGt_const, length, 0), 0); 1263 $$ = var; 1264 } 1265 ; 1266 1267descriptor_item: SQL_CARDINALITY { $$ = ECPGd_cardinality; } 1268 | DATA_P { $$ = ECPGd_data; } 1269 | SQL_DATETIME_INTERVAL_CODE { $$ = ECPGd_di_code; } 1270 | SQL_DATETIME_INTERVAL_PRECISION { $$ = ECPGd_di_precision; } 1271 | SQL_INDICATOR { $$ = ECPGd_indicator; } 1272 | SQL_KEY_MEMBER { $$ = ECPGd_key_member; } 1273 | SQL_LENGTH { $$ = ECPGd_length; } 1274 | NAME_P { $$ = ECPGd_name; } 1275 | SQL_NULLABLE { $$ = ECPGd_nullable; } 1276 | SQL_OCTET_LENGTH { $$ = ECPGd_octet; } 1277 | PRECISION { $$ = ECPGd_precision; } 1278 | SQL_RETURNED_LENGTH { $$ = ECPGd_length; } 1279 | SQL_RETURNED_OCTET_LENGTH { $$ = ECPGd_ret_octet; } 1280 | SQL_SCALE { $$ = ECPGd_scale; } 1281 | TYPE_P { $$ = ECPGd_type; } 1282 ; 1283 1284/* 1285 * set/reset the automatic transaction mode, this needs a different handling 1286 * as the other set commands 1287 */ 1288ECPGSetAutocommit: SET SQL_AUTOCOMMIT '=' on_off { $$ = $4; } 1289 | SET SQL_AUTOCOMMIT TO on_off { $$ = $4; } 1290 ; 1291 1292on_off: ON { $$ = mm_strdup("on"); } 1293 | OFF { $$ = mm_strdup("off"); } 1294 ; 1295 1296/* 1297 * set the actual connection, this needs a different handling as the other 1298 * set commands 1299 */ 1300ECPGSetConnection: SET CONNECTION TO connection_object { $$ = $4; } 1301 | SET CONNECTION '=' connection_object { $$ = $4; } 1302 | SET CONNECTION connection_object { $$ = $3; } 1303 ; 1304 1305/* 1306 * define a new type for embedded SQL 1307 */ 1308ECPGTypedef: TYPE_P 1309 { 1310 /* reset this variable so we see if there was */ 1311 /* an initializer specified */ 1312 initializer = 0; 1313 } 1314 ECPGColLabelCommon IS var_type opt_array_bounds opt_reference 1315 { 1316 add_typedef($3, $6.index1, $6.index2, $5.type_enum, $5.type_dimension, $5.type_index, initializer, *$7 ? 1 : 0); 1317 1318 if (auto_create_c == false) 1319 $$ = cat_str(7, mm_strdup("/* exec sql type"), mm_strdup($3), mm_strdup("is"), mm_strdup($5.type_str), mm_strdup($6.str), $7, mm_strdup("*/")); 1320 else 1321 $$ = cat_str(6, mm_strdup("typedef "), mm_strdup($5.type_str), *$7?mm_strdup("*"):mm_strdup(""), mm_strdup($3), mm_strdup($6.str), mm_strdup(";")); 1322 } 1323 ; 1324 1325opt_reference: SQL_REFERENCE { $$ = mm_strdup("reference"); } 1326 | /*EMPTY*/ { $$ = EMPTY; } 1327 ; 1328 1329/* 1330 * define the type of one variable for embedded SQL 1331 */ 1332ECPGVar: SQL_VAR 1333 { 1334 /* reset this variable so we see if there was */ 1335 /* an initializer specified */ 1336 initializer = 0; 1337 } 1338 ColLabel IS var_type opt_array_bounds opt_reference 1339 { 1340 struct variable *p = find_variable($3); 1341 char *dimension = $6.index1; 1342 char *length = $6.index2; 1343 struct ECPGtype * type; 1344 1345 if (($5.type_enum == ECPGt_struct || 1346 $5.type_enum == ECPGt_union) && 1347 initializer == 1) 1348 mmerror(PARSE_ERROR, ET_ERROR, "initializer not allowed in EXEC SQL VAR command"); 1349 else 1350 { 1351 adjust_array($5.type_enum, &dimension, &length, $5.type_dimension, $5.type_index, *$7?1:0, false); 1352 1353 switch ($5.type_enum) 1354 { 1355 case ECPGt_struct: 1356 case ECPGt_union: 1357 if (atoi(dimension) < 0) 1358 type = ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, $5.type_str, $5.type_sizeof); 1359 else 1360 type = ECPGmake_array_type(ECPGmake_struct_type(struct_member_list[struct_level], $5.type_enum, $5.type_str, $5.type_sizeof), dimension); 1361 break; 1362 1363 case ECPGt_varchar: 1364 if (atoi(dimension) == -1) 1365 type = ECPGmake_simple_type($5.type_enum, length, 0); 1366 else 1367 type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length, 0), dimension); 1368 break; 1369 1370 case ECPGt_char: 1371 case ECPGt_unsigned_char: 1372 case ECPGt_string: 1373 if (atoi(dimension) == -1) 1374 type = ECPGmake_simple_type($5.type_enum, length, 0); 1375 else 1376 type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, length, 0), dimension); 1377 break; 1378 1379 default: 1380 if (atoi(length) >= 0) 1381 mmerror(PARSE_ERROR, ET_ERROR, "multidimensional arrays for simple data types are not supported"); 1382 1383 if (atoi(dimension) < 0) 1384 type = ECPGmake_simple_type($5.type_enum, mm_strdup("1"), 0); 1385 else 1386 type = ECPGmake_array_type(ECPGmake_simple_type($5.type_enum, mm_strdup("1"), 0), dimension); 1387 break; 1388 } 1389 1390 ECPGfree_type(p->type); 1391 p->type = type; 1392 } 1393 1394 $$ = cat_str(7, mm_strdup("/* exec sql var"), mm_strdup($3), mm_strdup("is"), mm_strdup($5.type_str), mm_strdup($6.str), $7, mm_strdup("*/")); 1395 } 1396 ; 1397 1398/* 1399 * whenever statement: decide what to do in case of error/no data found 1400 * according to SQL standards we lack: SQLSTATE, CONSTRAINT and SQLEXCEPTION 1401 */ 1402ECPGWhenever: SQL_WHENEVER SQL_SQLERROR action 1403 { 1404 when_error.code = $<action>3.code; 1405 when_error.command = $<action>3.command; 1406 $$ = cat_str(3, mm_strdup("/* exec sql whenever sqlerror "), $3.str, mm_strdup("; */")); 1407 } 1408 | SQL_WHENEVER NOT SQL_FOUND action 1409 { 1410 when_nf.code = $<action>4.code; 1411 when_nf.command = $<action>4.command; 1412 $$ = cat_str(3, mm_strdup("/* exec sql whenever not found "), $4.str, mm_strdup("; */")); 1413 } 1414 | SQL_WHENEVER SQL_SQLWARNING action 1415 { 1416 when_warn.code = $<action>3.code; 1417 when_warn.command = $<action>3.command; 1418 $$ = cat_str(3, mm_strdup("/* exec sql whenever sql_warning "), $3.str, mm_strdup("; */")); 1419 } 1420 ; 1421 1422action : CONTINUE_P 1423 { 1424 $<action>$.code = W_NOTHING; 1425 $<action>$.command = NULL; 1426 $<action>$.str = mm_strdup("continue"); 1427 } 1428 | SQL_SQLPRINT 1429 { 1430 $<action>$.code = W_SQLPRINT; 1431 $<action>$.command = NULL; 1432 $<action>$.str = mm_strdup("sqlprint"); 1433 } 1434 | SQL_STOP 1435 { 1436 $<action>$.code = W_STOP; 1437 $<action>$.command = NULL; 1438 $<action>$.str = mm_strdup("stop"); 1439 } 1440 | SQL_GOTO name 1441 { 1442 $<action>$.code = W_GOTO; 1443 $<action>$.command = mm_strdup($2); 1444 $<action>$.str = cat2_str(mm_strdup("goto "), $2); 1445 } 1446 | SQL_GO TO name 1447 { 1448 $<action>$.code = W_GOTO; 1449 $<action>$.command = mm_strdup($3); 1450 $<action>$.str = cat2_str(mm_strdup("goto "), $3); 1451 } 1452 | DO name '(' c_args ')' 1453 { 1454 $<action>$.code = W_DO; 1455 $<action>$.command = cat_str(4, $2, mm_strdup("("), $4, mm_strdup(")")); 1456 $<action>$.str = cat2_str(mm_strdup("do"), mm_strdup($<action>$.command)); 1457 } 1458 | DO SQL_BREAK 1459 { 1460 $<action>$.code = W_BREAK; 1461 $<action>$.command = NULL; 1462 $<action>$.str = mm_strdup("break"); 1463 } 1464 | DO CONTINUE_P 1465 { 1466 $<action>$.code = W_CONTINUE; 1467 $<action>$.command = NULL; 1468 $<action>$.str = mm_strdup("continue"); 1469 } 1470 | CALL name '(' c_args ')' 1471 { 1472 $<action>$.code = W_DO; 1473 $<action>$.command = cat_str(4, $2, mm_strdup("("), $4, mm_strdup(")")); 1474 $<action>$.str = cat2_str(mm_strdup("call"), mm_strdup($<action>$.command)); 1475 } 1476 | CALL name 1477 { 1478 $<action>$.code = W_DO; 1479 $<action>$.command = cat2_str($2, mm_strdup("()")); 1480 $<action>$.str = cat2_str(mm_strdup("call"), mm_strdup($<action>$.command)); 1481 } 1482 ; 1483 1484/* some other stuff for ecpg */ 1485 1486/* additional unreserved keywords */ 1487ECPGKeywords: ECPGKeywords_vanames { $$ = $1; } 1488 | ECPGKeywords_rest { $$ = $1; } 1489 ; 1490 1491ECPGKeywords_vanames: SQL_BREAK { $$ = mm_strdup("break"); } 1492 | SQL_CARDINALITY { $$ = mm_strdup("cardinality"); } 1493 | SQL_COUNT { $$ = mm_strdup("count"); } 1494 | SQL_DATETIME_INTERVAL_CODE { $$ = mm_strdup("datetime_interval_code"); } 1495 | SQL_DATETIME_INTERVAL_PRECISION { $$ = mm_strdup("datetime_interval_precision"); } 1496 | SQL_FOUND { $$ = mm_strdup("found"); } 1497 | SQL_GO { $$ = mm_strdup("go"); } 1498 | SQL_GOTO { $$ = mm_strdup("goto"); } 1499 | SQL_IDENTIFIED { $$ = mm_strdup("identified"); } 1500 | SQL_INDICATOR { $$ = mm_strdup("indicator"); } 1501 | SQL_KEY_MEMBER { $$ = mm_strdup("key_member"); } 1502 | SQL_LENGTH { $$ = mm_strdup("length"); } 1503 | SQL_NULLABLE { $$ = mm_strdup("nullable"); } 1504 | SQL_OCTET_LENGTH { $$ = mm_strdup("octet_length"); } 1505 | SQL_RETURNED_LENGTH { $$ = mm_strdup("returned_length"); } 1506 | SQL_RETURNED_OCTET_LENGTH { $$ = mm_strdup("returned_octet_length"); } 1507 | SQL_SCALE { $$ = mm_strdup("scale"); } 1508 | SQL_SECTION { $$ = mm_strdup("section"); } 1509 | SQL_SQLERROR { $$ = mm_strdup("sqlerror"); } 1510 | SQL_SQLPRINT { $$ = mm_strdup("sqlprint"); } 1511 | SQL_SQLWARNING { $$ = mm_strdup("sqlwarning"); } 1512 | SQL_STOP { $$ = mm_strdup("stop"); } 1513 ; 1514 1515ECPGKeywords_rest: SQL_CONNECT { $$ = mm_strdup("connect"); } 1516 | SQL_DESCRIBE { $$ = mm_strdup("describe"); } 1517 | SQL_DISCONNECT { $$ = mm_strdup("disconnect"); } 1518 | SQL_OPEN { $$ = mm_strdup("open"); } 1519 | SQL_VAR { $$ = mm_strdup("var"); } 1520 | SQL_WHENEVER { $$ = mm_strdup("whenever"); } 1521 ; 1522 1523/* additional keywords that can be SQL type names (but not ECPGColLabels) */ 1524ECPGTypeName: SQL_BOOL { $$ = mm_strdup("bool"); } 1525 | SQL_LONG { $$ = mm_strdup("long"); } 1526 | SQL_OUTPUT { $$ = mm_strdup("output"); } 1527 | SQL_SHORT { $$ = mm_strdup("short"); } 1528 | SQL_STRUCT { $$ = mm_strdup("struct"); } 1529 | SQL_SIGNED { $$ = mm_strdup("signed"); } 1530 | SQL_UNSIGNED { $$ = mm_strdup("unsigned"); } 1531 ; 1532 1533symbol: ColLabel { $$ = $1; } 1534 ; 1535 1536ECPGColId: ecpg_ident { $$ = $1; } 1537 | unreserved_keyword { $$ = $1; } 1538 | col_name_keyword { $$ = $1; } 1539 | ECPGunreserved_interval { $$ = $1; } 1540 | ECPGKeywords { $$ = $1; } 1541 | ECPGCKeywords { $$ = $1; } 1542 | CHAR_P { $$ = mm_strdup("char"); } 1543 | VALUES { $$ = mm_strdup("values"); } 1544 ; 1545 1546/* 1547 * Name classification hierarchy. 1548 * 1549 * These productions should match those in the core grammar, except that 1550 * we use all_unreserved_keyword instead of unreserved_keyword, and 1551 * where possible include ECPG keywords as well as core keywords. 1552 */ 1553 1554/* Column identifier --- names that can be column, table, etc names. 1555 */ 1556ColId: ecpg_ident { $$ = $1; } 1557 | all_unreserved_keyword { $$ = $1; } 1558 | col_name_keyword { $$ = $1; } 1559 | ECPGKeywords { $$ = $1; } 1560 | ECPGCKeywords { $$ = $1; } 1561 | CHAR_P { $$ = mm_strdup("char"); } 1562 | VALUES { $$ = mm_strdup("values"); } 1563 ; 1564 1565/* Type/function identifier --- names that can be type or function names. 1566 */ 1567type_function_name: ecpg_ident { $$ = $1; } 1568 | all_unreserved_keyword { $$ = $1; } 1569 | type_func_name_keyword { $$ = $1; } 1570 | ECPGKeywords { $$ = $1; } 1571 | ECPGCKeywords { $$ = $1; } 1572 | ECPGTypeName { $$ = $1; } 1573 ; 1574 1575/* Column label --- allowed labels in "AS" clauses. 1576 * This presently includes *all* Postgres keywords. 1577 */ 1578ColLabel: ECPGColLabel { $$ = $1; } 1579 | ECPGTypeName { $$ = $1; } 1580 | CHAR_P { $$ = mm_strdup("char"); } 1581 | CURRENT_P { $$ = mm_strdup("current"); } 1582 | INPUT_P { $$ = mm_strdup("input"); } 1583 | INT_P { $$ = mm_strdup("int"); } 1584 | TO { $$ = mm_strdup("to"); } 1585 | UNION { $$ = mm_strdup("union"); } 1586 | VALUES { $$ = mm_strdup("values"); } 1587 | ECPGCKeywords { $$ = $1; } 1588 | ECPGunreserved_interval { $$ = $1; } 1589 ; 1590 1591ECPGColLabel: ECPGColLabelCommon { $$ = $1; } 1592 | unreserved_keyword { $$ = $1; } 1593 | reserved_keyword { $$ = $1; } 1594 | ECPGKeywords_rest { $$ = $1; } 1595 | CONNECTION { $$ = mm_strdup("connection"); } 1596 ; 1597 1598ECPGColLabelCommon: ecpg_ident { $$ = $1; } 1599 | col_name_keyword { $$ = $1; } 1600 | type_func_name_keyword { $$ = $1; } 1601 | ECPGKeywords_vanames { $$ = $1; } 1602 ; 1603 1604ECPGCKeywords: S_AUTO { $$ = mm_strdup("auto"); } 1605 | S_CONST { $$ = mm_strdup("const"); } 1606 | S_EXTERN { $$ = mm_strdup("extern"); } 1607 | S_REGISTER { $$ = mm_strdup("register"); } 1608 | S_STATIC { $$ = mm_strdup("static"); } 1609 | S_TYPEDEF { $$ = mm_strdup("typedef"); } 1610 | S_VOLATILE { $$ = mm_strdup("volatile"); } 1611 ; 1612 1613/* "Unreserved" keywords --- available for use as any kind of name. 1614 */ 1615 1616/* 1617 * The following symbols must be excluded from ECPGColLabel and directly 1618 * included into ColLabel to enable C variables to get names from ECPGColLabel: 1619 * DAY_P, HOUR_P, MINUTE_P, MONTH_P, SECOND_P, YEAR_P. 1620 * 1621 * We also have to exclude CONNECTION, CURRENT, and INPUT for various reasons. 1622 * CONNECTION can be added back in all_unreserved_keyword, but CURRENT and 1623 * INPUT are reserved for ecpg purposes. 1624 * 1625 * The mentioned exclusions are done by $replace_line settings in parse.pl. 1626 */ 1627all_unreserved_keyword: unreserved_keyword { $$ = $1; } 1628 | ECPGunreserved_interval { $$ = $1; } 1629 | CONNECTION { $$ = mm_strdup("connection"); } 1630 ; 1631 1632ECPGunreserved_interval: DAY_P { $$ = mm_strdup("day"); } 1633 | HOUR_P { $$ = mm_strdup("hour"); } 1634 | MINUTE_P { $$ = mm_strdup("minute"); } 1635 | MONTH_P { $$ = mm_strdup("month"); } 1636 | SECOND_P { $$ = mm_strdup("second"); } 1637 | YEAR_P { $$ = mm_strdup("year"); } 1638 ; 1639 1640 1641into_list : coutputvariable | into_list ',' coutputvariable 1642 ; 1643 1644ecpgstart: SQL_START { 1645 reset_variables(); 1646 pacounter = 1; 1647 } 1648 ; 1649 1650c_args: /*EMPTY*/ { $$ = EMPTY; } 1651 | c_list { $$ = $1; } 1652 ; 1653 1654coutputvariable: cvariable indicator 1655 { add_variable_to_head(&argsresult, find_variable($1), find_variable($2)); } 1656 | cvariable 1657 { add_variable_to_head(&argsresult, find_variable($1), &no_indicator); } 1658 ; 1659 1660 1661civarind: cvariable indicator 1662 { 1663 if (find_variable($2)->type->type == ECPGt_array) 1664 mmerror(PARSE_ERROR, ET_ERROR, "arrays of indicators are not allowed on input"); 1665 1666 add_variable_to_head(&argsinsert, find_variable($1), find_variable($2)); 1667 $$ = create_questionmarks($1, false); 1668 } 1669 ; 1670 1671char_civar: char_variable 1672 { 1673 char *ptr = strstr($1, ".arr"); 1674 1675 if (ptr) /* varchar, we need the struct name here, not the struct element */ 1676 *ptr = '\0'; 1677 add_variable_to_head(&argsinsert, find_variable($1), &no_indicator); 1678 $$ = $1; 1679 } 1680 ; 1681 1682civar: cvariable 1683 { 1684 add_variable_to_head(&argsinsert, find_variable($1), &no_indicator); 1685 $$ = create_questionmarks($1, false); 1686 } 1687 ; 1688 1689indicator: cvariable { check_indicator((find_variable($1))->type); $$ = $1; } 1690 | SQL_INDICATOR cvariable { check_indicator((find_variable($2))->type); $$ = $2; } 1691 | SQL_INDICATOR name { check_indicator((find_variable($2))->type); $$ = $2; } 1692 ; 1693 1694cvariable: CVARIABLE 1695 { 1696 /* As long as multidimensional arrays are not implemented we have to check for those here */ 1697 char *ptr = $1; 1698 int brace_open=0, brace = false; 1699 1700 for (; *ptr; ptr++) 1701 { 1702 switch (*ptr) 1703 { 1704 case '[': 1705 if (brace) 1706 mmfatal(PARSE_ERROR, "multidimensional arrays for simple data types are not supported"); 1707 brace_open++; 1708 break; 1709 case ']': 1710 brace_open--; 1711 if (brace_open == 0) 1712 brace = true; 1713 break; 1714 case '\t': 1715 case ' ': 1716 break; 1717 default: 1718 if (brace_open == 0) 1719 brace = false; 1720 break; 1721 } 1722 } 1723 $$ = $1; 1724 } 1725 ; 1726 1727ecpg_param: PARAM { $$ = make_name(); } ; 1728 1729ecpg_bconst: BCONST { $$ = make_name(); } ; 1730 1731ecpg_fconst: FCONST { $$ = make_name(); } ; 1732 1733ecpg_sconst: 1734 SCONST 1735 { 1736 /* could have been input as '' or $$ */ 1737 $$ = (char *)mm_alloc(strlen($1) + 3); 1738 $$[0]='\''; 1739 strcpy($$+1, $1); 1740 $$[strlen($1)+1]='\''; 1741 $$[strlen($1)+2]='\0'; 1742 free($1); 1743 } 1744 | ECONST 1745 { 1746 $$ = (char *)mm_alloc(strlen($1) + 4); 1747 $$[0]='E'; 1748 $$[1]='\''; 1749 strcpy($$+2, $1); 1750 $$[strlen($1)+2]='\''; 1751 $$[strlen($1)+3]='\0'; 1752 free($1); 1753 } 1754 | NCONST 1755 { 1756 $$ = (char *)mm_alloc(strlen($1) + 4); 1757 $$[0]='N'; 1758 $$[1]='\''; 1759 strcpy($$+2, $1); 1760 $$[strlen($1)+2]='\''; 1761 $$[strlen($1)+3]='\0'; 1762 free($1); 1763 } 1764 | UCONST { $$ = $1; } 1765 | DOLCONST { $$ = $1; } 1766 ; 1767 1768ecpg_xconst: XCONST { $$ = make_name(); } ; 1769 1770ecpg_ident: IDENT { $$ = make_name(); } 1771 | CSTRING { $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\"")); } 1772 | UIDENT { $$ = $1; } 1773 ; 1774 1775quoted_ident_stringvar: name 1776 { $$ = make3_str(mm_strdup("\""), $1, mm_strdup("\"")); } 1777 | char_variable 1778 { $$ = make3_str(mm_strdup("("), $1, mm_strdup(")")); } 1779 ; 1780 1781/* 1782 * C stuff 1783 */ 1784 1785c_stuff_item: c_anything { $$ = $1; } 1786 | '(' ')' { $$ = mm_strdup("()"); } 1787 | '(' c_stuff ')' 1788 { $$ = cat_str(3, mm_strdup("("), $2, mm_strdup(")")); } 1789 ; 1790 1791c_stuff: c_stuff_item { $$ = $1; } 1792 | c_stuff c_stuff_item 1793 { $$ = cat2_str($1, $2); } 1794 ; 1795 1796c_list: c_term { $$ = $1; } 1797 | c_list ',' c_term { $$ = cat_str(3, $1, mm_strdup(","), $3); } 1798 ; 1799 1800c_term: c_stuff { $$ = $1; } 1801 | '{' c_list '}' { $$ = cat_str(3, mm_strdup("{"), $2, mm_strdup("}")); } 1802 ; 1803 1804c_thing: c_anything { $$ = $1; } 1805 | '(' { $$ = mm_strdup("("); } 1806 | ')' { $$ = mm_strdup(")"); } 1807 | ',' { $$ = mm_strdup(","); } 1808 | ';' { $$ = mm_strdup(";"); } 1809 ; 1810 1811c_anything: ecpg_ident { $$ = $1; } 1812 | Iconst { $$ = $1; } 1813 | ecpg_fconst { $$ = $1; } 1814 | ecpg_sconst { $$ = $1; } 1815 | '*' { $$ = mm_strdup("*"); } 1816 | '+' { $$ = mm_strdup("+"); } 1817 | '-' { $$ = mm_strdup("-"); } 1818 | '/' { $$ = mm_strdup("/"); } 1819 | '%' { $$ = mm_strdup("%"); } 1820 | NULL_P { $$ = mm_strdup("NULL"); } 1821 | S_ADD { $$ = mm_strdup("+="); } 1822 | S_AND { $$ = mm_strdup("&&"); } 1823 | S_ANYTHING { $$ = make_name(); } 1824 | S_AUTO { $$ = mm_strdup("auto"); } 1825 | S_CONST { $$ = mm_strdup("const"); } 1826 | S_DEC { $$ = mm_strdup("--"); } 1827 | S_DIV { $$ = mm_strdup("/="); } 1828 | S_DOTPOINT { $$ = mm_strdup(".*"); } 1829 | S_EQUAL { $$ = mm_strdup("=="); } 1830 | S_EXTERN { $$ = mm_strdup("extern"); } 1831 | S_INC { $$ = mm_strdup("++"); } 1832 | S_LSHIFT { $$ = mm_strdup("<<"); } 1833 | S_MEMBER { $$ = mm_strdup("->"); } 1834 | S_MEMPOINT { $$ = mm_strdup("->*"); } 1835 | S_MOD { $$ = mm_strdup("%="); } 1836 | S_MUL { $$ = mm_strdup("*="); } 1837 | S_NEQUAL { $$ = mm_strdup("!="); } 1838 | S_OR { $$ = mm_strdup("||"); } 1839 | S_REGISTER { $$ = mm_strdup("register"); } 1840 | S_RSHIFT { $$ = mm_strdup(">>"); } 1841 | S_STATIC { $$ = mm_strdup("static"); } 1842 | S_SUB { $$ = mm_strdup("-="); } 1843 | S_TYPEDEF { $$ = mm_strdup("typedef"); } 1844 | S_VOLATILE { $$ = mm_strdup("volatile"); } 1845 | SQL_BOOL { $$ = mm_strdup("bool"); } 1846 | ENUM_P { $$ = mm_strdup("enum"); } 1847 | HOUR_P { $$ = mm_strdup("hour"); } 1848 | INT_P { $$ = mm_strdup("int"); } 1849 | SQL_LONG { $$ = mm_strdup("long"); } 1850 | MINUTE_P { $$ = mm_strdup("minute"); } 1851 | MONTH_P { $$ = mm_strdup("month"); } 1852 | SECOND_P { $$ = mm_strdup("second"); } 1853 | SQL_SHORT { $$ = mm_strdup("short"); } 1854 | SQL_SIGNED { $$ = mm_strdup("signed"); } 1855 | SQL_STRUCT { $$ = mm_strdup("struct"); } 1856 | SQL_UNSIGNED { $$ = mm_strdup("unsigned"); } 1857 | YEAR_P { $$ = mm_strdup("year"); } 1858 | CHAR_P { $$ = mm_strdup("char"); } 1859 | FLOAT_P { $$ = mm_strdup("float"); } 1860 | TO { $$ = mm_strdup("to"); } 1861 | UNION { $$ = mm_strdup("union"); } 1862 | VARCHAR { $$ = mm_strdup("varchar"); } 1863 | '[' { $$ = mm_strdup("["); } 1864 | ']' { $$ = mm_strdup("]"); } 1865 | '=' { $$ = mm_strdup("="); } 1866 | ':' { $$ = mm_strdup(":"); } 1867 ; 1868 1869DeallocateStmt: DEALLOCATE prepared_name { $$ = $2; } 1870 | DEALLOCATE PREPARE prepared_name { $$ = $3; } 1871 | DEALLOCATE ALL { $$ = mm_strdup("all"); } 1872 | DEALLOCATE PREPARE ALL { $$ = mm_strdup("all"); } 1873 ; 1874 1875Iresult: Iconst { $$ = $1; } 1876 | '(' Iresult ')' { $$ = cat_str(3, mm_strdup("("), $2, mm_strdup(")")); } 1877 | Iresult '+' Iresult { $$ = cat_str(3, $1, mm_strdup("+"), $3); } 1878 | Iresult '-' Iresult { $$ = cat_str(3, $1, mm_strdup("-"), $3); } 1879 | Iresult '*' Iresult { $$ = cat_str(3, $1, mm_strdup("*"), $3); } 1880 | Iresult '/' Iresult { $$ = cat_str(3, $1, mm_strdup("/"), $3); } 1881 | Iresult '%' Iresult { $$ = cat_str(3, $1, mm_strdup("%"), $3); } 1882 | ecpg_sconst { $$ = $1; } 1883 | ColId { $$ = $1; } 1884 | ColId '(' var_type ')' { if (pg_strcasecmp($1, "sizeof") != 0) 1885 mmerror(PARSE_ERROR, ET_ERROR, "operator not allowed in variable definition"); 1886 else 1887 $$ = cat_str(4, $1, mm_strdup("("), $3.type_str, mm_strdup(")")); 1888 } 1889 ; 1890 1891execute_rest: /* EMPTY */ { $$ = EMPTY; } 1892 | ecpg_using opt_ecpg_into { $$ = EMPTY; } 1893 | ecpg_into ecpg_using { $$ = EMPTY; } 1894 | ecpg_into { $$ = EMPTY; } 1895 ; 1896 1897ecpg_into: INTO into_list { $$ = EMPTY; } 1898 | into_descriptor { $$ = $1; } 1899 ; 1900 1901opt_ecpg_into: /* EMPTY */ { $$ = EMPTY; } 1902 | ecpg_into { $$ = $1; } 1903 ; 1904 1905ecpg_fetch_into: ecpg_into { $$ = $1; } 1906 | using_descriptor 1907 { 1908 struct variable *var; 1909 1910 var = argsinsert->variable; 1911 remove_variable_from_list(&argsinsert, var); 1912 add_variable_to_head(&argsresult, var, &no_indicator); 1913 $$ = $1; 1914 } 1915 ; 1916 1917opt_ecpg_fetch_into: /* EMPTY */ { $$ = EMPTY; } 1918 | ecpg_fetch_into { $$ = $1; } 1919 ; 1920 1921%% 1922 1923void base_yyerror(const char *error) 1924{ 1925 /* translator: %s is typically the translation of "syntax error" */ 1926 mmerror(PARSE_ERROR, ET_ERROR, "%s at or near \"%s\"", 1927 _(error), token_start ? token_start : base_yytext); 1928} 1929 1930void parser_init(void) 1931{ 1932 /* This function is empty. It only exists for compatibility with the backend parser right now. */ 1933} 1934