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