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