1 %{ /* rcparse.y -- parser for Windows rc files 2 Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. 3 Written by Ian Lance Taylor, Cygnus Support. 4 5 This file is part of GNU Binutils. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program; if not, write to the Free Software 19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 20 02111-1307, USA. */ 21 22 /* This is a parser for Windows rc files. It is based on the parser 23 by Gunther Ebert <gunther.ebert@ixos-leipzig.de>. */ 24 25 #include "bfd.h" 26 #include "bucomm.h" 27 #include "libiberty.h" 28 #include "windres.h" 29 #include "safe-ctype.h" 30 31 /* The current language. */ 32 33 static unsigned short language; 34 35 /* The resource information during a sub statement. */ 36 37 static struct res_res_info sub_res_info; 38 39 /* Dialog information. This is built by the nonterminals styles and 40 controls. */ 41 42 static struct dialog dialog; 43 44 /* This is used when building a style. It is modified by the 45 nonterminal styleexpr. */ 46 47 static unsigned long style; 48 49 /* These are used when building a control. They are set before using 50 control_params. */ 51 52 static unsigned long base_style; 53 static unsigned long default_style; 54 static unsigned long class; 55 static struct res_id res_text_field; 56 57 /* This is used for COMBOBOX, LISTBOX and EDITTEXT which 58 do not allow resource 'text' field in control definition. */ 59 static const struct res_id res_null_text = { 1, {{0, L""}}}; 60 61 %} 62 63 %union 64 { 65 struct accelerator acc; 66 struct accelerator *pacc; 67 struct dialog_control *dialog_control; 68 struct menuitem *menuitem; 69 struct 70 { 71 struct rcdata_item *first; 72 struct rcdata_item *last; 73 } rcdata; 74 struct rcdata_item *rcdata_item; 75 struct stringtable_data *stringtable; 76 struct fixed_versioninfo *fixver; 77 struct ver_info *verinfo; 78 struct ver_stringinfo *verstring; 79 struct ver_varinfo *vervar; 80 struct res_id id; 81 struct res_res_info res_info; 82 struct 83 { 84 unsigned short on; 85 unsigned short off; 86 } memflags; 87 struct 88 { 89 unsigned long val; 90 /* Nonzero if this number was explicitly specified as long. */ 91 int dword; 92 } i; 93 unsigned long il; 94 unsigned short is; 95 const char *s; 96 struct 97 { 98 unsigned long length; 99 const char *s; 100 } ss; 101 }; 102 103 %token BEG END 104 %token ACCELERATORS VIRTKEY ASCII NOINVERT SHIFT CONTROL ALT 105 %token BITMAP 106 %token CURSOR 107 %token DIALOG DIALOGEX EXSTYLE CAPTION CLASS STYLE 108 %token AUTO3STATE AUTOCHECKBOX AUTORADIOBUTTON CHECKBOX COMBOBOX CTEXT 109 %token DEFPUSHBUTTON EDITTEXT GROUPBOX LISTBOX LTEXT PUSHBOX PUSHBUTTON 110 %token RADIOBUTTON RTEXT SCROLLBAR STATE3 USERBUTTON 111 %token BEDIT HEDIT IEDIT 112 %token FONT 113 %token ICON 114 %token LANGUAGE CHARACTERISTICS VERSIONK 115 %token MENU MENUEX MENUITEM SEPARATOR POPUP CHECKED GRAYED HELP INACTIVE 116 %token MENUBARBREAK MENUBREAK 117 %token MESSAGETABLE 118 %token RCDATA 119 %token STRINGTABLE 120 %token VERSIONINFO FILEVERSION PRODUCTVERSION FILEFLAGSMASK FILEFLAGS 121 %token FILEOS FILETYPE FILESUBTYPE BLOCKSTRINGFILEINFO BLOCKVARFILEINFO 122 %token VALUE 123 %token <s> BLOCK 124 %token MOVEABLE FIXED PURE IMPURE PRELOAD LOADONCALL DISCARDABLE 125 %token NOT 126 %token <s> QUOTEDSTRING STRING 127 %token <i> NUMBER 128 %token <ss> SIZEDSTRING 129 %token IGNORED_TOKEN 130 131 %type <pacc> acc_entries 132 %type <acc> acc_entry acc_event 133 %type <dialog_control> control control_params 134 %type <menuitem> menuitems menuitem menuexitems menuexitem 135 %type <rcdata> optrcdata_data optrcdata_data_int rcdata_data 136 %type <rcdata_item> opt_control_data 137 %type <fixver> fixedverinfo 138 %type <verinfo> verblocks 139 %type <verstring> vervals 140 %type <vervar> vertrans 141 %type <res_info> suboptions memflags_move_discard memflags_move 142 %type <memflags> memflag 143 %type <id> id optresidc resref 144 %type <il> exstyle parennumber 145 %type <il> numexpr posnumexpr cnumexpr optcnumexpr cposnumexpr 146 %type <is> acc_options acc_option menuitem_flags menuitem_flag 147 %type <s> file_name resname 148 %type <i> sizednumexpr sizedposnumexpr 149 150 %left '|' 151 %left '^' 152 %left '&' 153 %left '+' '-' 154 %left '*' '/' '%' 155 %right '~' NEG 156 157 %% 158 159 input: 160 /* empty */ 161 | input accelerator 162 | input bitmap 163 | input cursor 164 | input dialog 165 | input font 166 | input icon 167 | input language 168 | input menu 169 | input menuex 170 | input messagetable 171 | input rcdata 172 | input stringtable 173 | input user 174 | input versioninfo 175 | input IGNORED_TOKEN 176 ; 177 178 /* Accelerator resources. */ 179 180 accelerator: 181 id ACCELERATORS suboptions BEG acc_entries END 182 { 183 define_accelerator ($1, &$3, $5); 184 if (yychar != YYEMPTY) 185 YYERROR; 186 rcparse_discard_strings (); 187 } 188 ; 189 190 acc_entries: 191 /* empty */ 192 { 193 $$ = NULL; 194 } 195 | acc_entries acc_entry 196 { 197 struct accelerator *a; 198 199 a = (struct accelerator *) res_alloc (sizeof *a); 200 *a = $2; 201 if ($1 == NULL) 202 $$ = a; 203 else 204 { 205 struct accelerator **pp; 206 207 for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next) 208 ; 209 *pp = a; 210 $$ = $1; 211 } 212 } 213 ; 214 215 acc_entry: 216 acc_event cposnumexpr 217 { 218 $$ = $1; 219 $$.id = $2; 220 } 221 | acc_event cposnumexpr ',' acc_options 222 { 223 $$ = $1; 224 $$.id = $2; 225 $$.flags |= $4; 226 if (($$.flags & ACC_VIRTKEY) == 0 227 && ($$.flags & (ACC_SHIFT | ACC_CONTROL)) != 0) 228 rcparse_warning (_("inappropriate modifiers for non-VIRTKEY")); 229 } 230 ; 231 232 acc_event: 233 QUOTEDSTRING 234 { 235 const char *s = $1; 236 char ch; 237 238 $$.next = NULL; 239 $$.id = 0; 240 ch = *s; 241 if (ch != '^') 242 $$.flags = 0; 243 else 244 { 245 $$.flags = ACC_CONTROL | ACC_VIRTKEY; 246 ++s; 247 ch = *s; 248 ch = TOUPPER (ch); 249 } 250 $$.key = ch; 251 if (s[1] != '\0') 252 rcparse_warning (_("accelerator should only be one character")); 253 } 254 | posnumexpr 255 { 256 $$.next = NULL; 257 $$.flags = 0; 258 $$.id = 0; 259 $$.key = $1; 260 } 261 ; 262 263 acc_options: 264 acc_option 265 { 266 $$ = $1; 267 } 268 | acc_options ',' acc_option 269 { 270 $$ = $1 | $3; 271 } 272 /* I've had one report that the comma is optional. */ 273 | acc_options acc_option 274 { 275 $$ = $1 | $2; 276 } 277 ; 278 279 acc_option: 280 VIRTKEY 281 { 282 $$ = ACC_VIRTKEY; 283 } 284 | ASCII 285 { 286 /* This is just the absence of VIRTKEY. */ 287 $$ = 0; 288 } 289 | NOINVERT 290 { 291 $$ = ACC_NOINVERT; 292 } 293 | SHIFT 294 { 295 $$ = ACC_SHIFT; 296 } 297 | CONTROL 298 { 299 $$ = ACC_CONTROL; 300 } 301 | ALT 302 { 303 $$ = ACC_ALT; 304 } 305 ; 306 307 /* Bitmap resources. */ 308 309 bitmap: 310 id BITMAP memflags_move file_name 311 { 312 define_bitmap ($1, &$3, $4); 313 if (yychar != YYEMPTY) 314 YYERROR; 315 rcparse_discard_strings (); 316 } 317 ; 318 319 /* Cursor resources. */ 320 321 cursor: 322 id CURSOR memflags_move_discard file_name 323 { 324 define_cursor ($1, &$3, $4); 325 if (yychar != YYEMPTY) 326 YYERROR; 327 rcparse_discard_strings (); 328 } 329 ; 330 331 /* Dialog resources. */ 332 333 dialog: 334 id DIALOG memflags_move exstyle posnumexpr cnumexpr cnumexpr 335 cnumexpr 336 { 337 memset (&dialog, 0, sizeof dialog); 338 dialog.x = $5; 339 dialog.y = $6; 340 dialog.width = $7; 341 dialog.height = $8; 342 dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU; 343 dialog.exstyle = $4; 344 dialog.menu.named = 1; 345 dialog.class.named = 1; 346 dialog.font = NULL; 347 dialog.ex = NULL; 348 dialog.controls = NULL; 349 sub_res_info = $3; 350 style = 0; 351 } 352 styles BEG controls END 353 { 354 define_dialog ($1, &sub_res_info, &dialog); 355 if (yychar != YYEMPTY) 356 YYERROR; 357 rcparse_discard_strings (); 358 } 359 | id DIALOGEX memflags_move exstyle posnumexpr cnumexpr cnumexpr 360 cnumexpr 361 { 362 memset (&dialog, 0, sizeof dialog); 363 dialog.x = $5; 364 dialog.y = $6; 365 dialog.width = $7; 366 dialog.height = $8; 367 dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU; 368 dialog.exstyle = $4; 369 dialog.menu.named = 1; 370 dialog.class.named = 1; 371 dialog.font = NULL; 372 dialog.ex = ((struct dialog_ex *) 373 res_alloc (sizeof (struct dialog_ex))); 374 memset (dialog.ex, 0, sizeof (struct dialog_ex)); 375 dialog.controls = NULL; 376 sub_res_info = $3; 377 style = 0; 378 } 379 styles BEG controls END 380 { 381 define_dialog ($1, &sub_res_info, &dialog); 382 if (yychar != YYEMPTY) 383 YYERROR; 384 rcparse_discard_strings (); 385 } 386 | id DIALOGEX memflags_move exstyle posnumexpr cnumexpr cnumexpr 387 cnumexpr cnumexpr 388 { 389 memset (&dialog, 0, sizeof dialog); 390 dialog.x = $5; 391 dialog.y = $6; 392 dialog.width = $7; 393 dialog.height = $8; 394 dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU; 395 dialog.exstyle = $4; 396 dialog.menu.named = 1; 397 dialog.class.named = 1; 398 dialog.font = NULL; 399 dialog.ex = ((struct dialog_ex *) 400 res_alloc (sizeof (struct dialog_ex))); 401 memset (dialog.ex, 0, sizeof (struct dialog_ex)); 402 dialog.ex->help = $9; 403 dialog.controls = NULL; 404 sub_res_info = $3; 405 style = 0; 406 } 407 styles BEG controls END 408 { 409 define_dialog ($1, &sub_res_info, &dialog); 410 if (yychar != YYEMPTY) 411 YYERROR; 412 rcparse_discard_strings (); 413 } 414 ; 415 416 exstyle: 417 /* empty */ 418 { 419 $$ = 0; 420 } 421 | EXSTYLE '=' numexpr 422 { 423 $$ = $3; 424 } 425 ; 426 427 styles: 428 /* empty */ 429 | styles CAPTION QUOTEDSTRING 430 { 431 dialog.style |= WS_CAPTION; 432 style |= WS_CAPTION; 433 unicode_from_ascii ((int *) NULL, &dialog.caption, $3); 434 } 435 | styles CLASS id 436 { 437 dialog.class = $3; 438 } 439 | styles STYLE 440 styleexpr 441 { 442 dialog.style = style; 443 } 444 | styles EXSTYLE numexpr 445 { 446 dialog.exstyle = $3; 447 } 448 | styles CLASS QUOTEDSTRING 449 { 450 res_string_to_id (& dialog.class, $3); 451 } 452 | styles FONT numexpr ',' QUOTEDSTRING 453 { 454 dialog.style |= DS_SETFONT; 455 style |= DS_SETFONT; 456 dialog.pointsize = $3; 457 unicode_from_ascii ((int *) NULL, &dialog.font, $5); 458 if (dialog.ex != NULL) 459 { 460 dialog.ex->weight = 0; 461 dialog.ex->italic = 0; 462 dialog.ex->charset = 1; 463 } 464 } 465 | styles FONT numexpr ',' QUOTEDSTRING cnumexpr 466 { 467 dialog.style |= DS_SETFONT; 468 style |= DS_SETFONT; 469 dialog.pointsize = $3; 470 unicode_from_ascii ((int *) NULL, &dialog.font, $5); 471 if (dialog.ex == NULL) 472 rcparse_warning (_("extended FONT requires DIALOGEX")); 473 else 474 { 475 dialog.ex->weight = $6; 476 dialog.ex->italic = 0; 477 dialog.ex->charset = 1; 478 } 479 } 480 | styles FONT numexpr ',' QUOTEDSTRING cnumexpr cnumexpr 481 { 482 dialog.style |= DS_SETFONT; 483 style |= DS_SETFONT; 484 dialog.pointsize = $3; 485 unicode_from_ascii ((int *) NULL, &dialog.font, $5); 486 if (dialog.ex == NULL) 487 rcparse_warning (_("extended FONT requires DIALOGEX")); 488 else 489 { 490 dialog.ex->weight = $6; 491 dialog.ex->italic = $7; 492 dialog.ex->charset = 1; 493 } 494 } 495 | styles FONT numexpr ',' QUOTEDSTRING cnumexpr cnumexpr cnumexpr 496 { 497 dialog.style |= DS_SETFONT; 498 style |= DS_SETFONT; 499 dialog.pointsize = $3; 500 unicode_from_ascii ((int *) NULL, &dialog.font, $5); 501 if (dialog.ex == NULL) 502 rcparse_warning (_("extended FONT requires DIALOGEX")); 503 else 504 { 505 dialog.ex->weight = $6; 506 dialog.ex->italic = $7; 507 dialog.ex->charset = $8; 508 } 509 } 510 | styles MENU id 511 { 512 dialog.menu = $3; 513 } 514 | styles CHARACTERISTICS numexpr 515 { 516 sub_res_info.characteristics = $3; 517 } 518 | styles LANGUAGE numexpr cnumexpr 519 { 520 sub_res_info.language = $3 | ($4 << SUBLANG_SHIFT); 521 } 522 | styles VERSIONK numexpr 523 { 524 sub_res_info.version = $3; 525 } 526 ; 527 528 controls: 529 /* empty */ 530 | controls control 531 { 532 struct dialog_control **pp; 533 534 for (pp = &dialog.controls; *pp != NULL; pp = &(*pp)->next) 535 ; 536 *pp = $2; 537 } 538 ; 539 540 control: 541 AUTO3STATE optresidc 542 { 543 default_style = BS_AUTO3STATE | WS_TABSTOP; 544 base_style = BS_AUTO3STATE; 545 class = CTL_BUTTON; 546 res_text_field = $2; 547 } 548 control_params 549 { 550 $$ = $4; 551 } 552 | AUTOCHECKBOX optresidc 553 { 554 default_style = BS_AUTOCHECKBOX | WS_TABSTOP; 555 base_style = BS_AUTOCHECKBOX; 556 class = CTL_BUTTON; 557 res_text_field = $2; 558 } 559 control_params 560 { 561 $$ = $4; 562 } 563 | AUTORADIOBUTTON optresidc 564 { 565 default_style = BS_AUTORADIOBUTTON | WS_TABSTOP; 566 base_style = BS_AUTORADIOBUTTON; 567 class = CTL_BUTTON; 568 res_text_field = $2; 569 } 570 control_params 571 { 572 $$ = $4; 573 } 574 | BEDIT optresidc 575 { 576 default_style = ES_LEFT | WS_BORDER | WS_TABSTOP; 577 base_style = ES_LEFT | WS_BORDER | WS_TABSTOP; 578 class = CTL_EDIT; 579 res_text_field = $2; 580 } 581 control_params 582 { 583 $$ = $4; 584 if (dialog.ex == NULL) 585 rcparse_warning (_("BEDIT requires DIALOGEX")); 586 res_string_to_id (&$$->class, "BEDIT"); 587 } 588 | CHECKBOX optresidc 589 { 590 default_style = BS_CHECKBOX | WS_TABSTOP; 591 base_style = BS_CHECKBOX | WS_TABSTOP; 592 class = CTL_BUTTON; 593 res_text_field = $2; 594 } 595 control_params 596 { 597 $$ = $4; 598 } 599 | COMBOBOX 600 { 601 /* This is as per MSDN documentation. With some (???) 602 versions of MS rc.exe their is no default style. */ 603 default_style = CBS_SIMPLE | WS_TABSTOP; 604 base_style = 0; 605 class = CTL_COMBOBOX; 606 res_text_field = res_null_text; 607 } 608 control_params 609 { 610 $$ = $3; 611 } 612 | CONTROL optresidc numexpr cnumexpr control_styleexpr cnumexpr 613 cnumexpr cnumexpr cnumexpr optcnumexpr opt_control_data 614 { 615 $$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10); 616 if ($11 != NULL) 617 { 618 if (dialog.ex == NULL) 619 rcparse_warning (_("control data requires DIALOGEX")); 620 $$->data = $11; 621 } 622 } 623 | CONTROL optresidc numexpr cnumexpr control_styleexpr cnumexpr 624 cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data 625 { 626 $$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10); 627 if (dialog.ex == NULL) 628 rcparse_warning (_("help ID requires DIALOGEX")); 629 $$->help = $11; 630 $$->data = $12; 631 } 632 | CONTROL optresidc numexpr ',' QUOTEDSTRING control_styleexpr 633 cnumexpr cnumexpr cnumexpr cnumexpr optcnumexpr opt_control_data 634 { 635 $$ = define_control ($2, $3, $7, $8, $9, $10, 0, style, $11); 636 if ($12 != NULL) 637 { 638 if (dialog.ex == NULL) 639 rcparse_warning ("control data requires DIALOGEX"); 640 $$->data = $12; 641 } 642 $$->class.named = 1; 643 unicode_from_ascii (&$$->class.u.n.length, &$$->class.u.n.name, $5); 644 } 645 | CONTROL optresidc numexpr ',' QUOTEDSTRING control_styleexpr 646 cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data 647 { 648 $$ = define_control ($2, $3, $7, $8, $9, $10, 0, style, $11); 649 if (dialog.ex == NULL) 650 rcparse_warning ("help ID requires DIALOGEX"); 651 $$->help = $12; 652 $$->data = $13; 653 $$->class.named = 1; 654 unicode_from_ascii (&$$->class.u.n.length, &$$->class.u.n.name, $5); 655 } 656 | CTEXT optresidc 657 { 658 default_style = SS_CENTER | WS_GROUP; 659 base_style = SS_CENTER; 660 class = CTL_STATIC; 661 res_text_field = $2; 662 } 663 control_params 664 { 665 $$ = $4; 666 } 667 | DEFPUSHBUTTON optresidc 668 { 669 default_style = BS_DEFPUSHBUTTON | WS_TABSTOP; 670 base_style = BS_DEFPUSHBUTTON | WS_TABSTOP; 671 class = CTL_BUTTON; 672 res_text_field = $2; 673 } 674 control_params 675 { 676 $$ = $4; 677 } 678 | EDITTEXT 679 { 680 default_style = ES_LEFT | WS_BORDER | WS_TABSTOP; 681 base_style = ES_LEFT | WS_BORDER | WS_TABSTOP; 682 class = CTL_EDIT; 683 res_text_field = res_null_text; 684 } 685 control_params 686 { 687 $$ = $3; 688 } 689 | GROUPBOX optresidc 690 { 691 default_style = BS_GROUPBOX; 692 base_style = BS_GROUPBOX; 693 class = CTL_BUTTON; 694 res_text_field = $2; 695 } 696 control_params 697 { 698 $$ = $4; 699 } 700 | HEDIT optresidc 701 { 702 default_style = ES_LEFT | WS_BORDER | WS_TABSTOP; 703 base_style = ES_LEFT | WS_BORDER | WS_TABSTOP; 704 class = CTL_EDIT; 705 res_text_field = $2; 706 } 707 control_params 708 { 709 $$ = $4; 710 if (dialog.ex == NULL) 711 rcparse_warning (_("IEDIT requires DIALOGEX")); 712 res_string_to_id (&$$->class, "HEDIT"); 713 } 714 | ICON resref numexpr cnumexpr cnumexpr opt_control_data 715 { 716 $$ = define_icon_control ($2, $3, $4, $5, 0, 0, 0, $6, 717 dialog.ex); 718 } 719 | ICON resref numexpr cnumexpr cnumexpr cnumexpr cnumexpr 720 opt_control_data 721 { 722 $$ = define_icon_control ($2, $3, $4, $5, 0, 0, 0, $8, 723 dialog.ex); 724 } 725 | ICON resref numexpr cnumexpr cnumexpr cnumexpr cnumexpr 726 icon_styleexpr optcnumexpr opt_control_data 727 { 728 $$ = define_icon_control ($2, $3, $4, $5, style, $9, 0, $10, 729 dialog.ex); 730 } 731 | ICON resref numexpr cnumexpr cnumexpr cnumexpr cnumexpr 732 icon_styleexpr cnumexpr cnumexpr opt_control_data 733 { 734 $$ = define_icon_control ($2, $3, $4, $5, style, $9, $10, $11, 735 dialog.ex); 736 } 737 | IEDIT optresidc 738 { 739 default_style = ES_LEFT | WS_BORDER | WS_TABSTOP; 740 base_style = ES_LEFT | WS_BORDER | WS_TABSTOP; 741 class = CTL_EDIT; 742 res_text_field = $2; 743 } 744 control_params 745 { 746 $$ = $4; 747 if (dialog.ex == NULL) 748 rcparse_warning (_("IEDIT requires DIALOGEX")); 749 res_string_to_id (&$$->class, "IEDIT"); 750 } 751 | LISTBOX 752 { 753 default_style = LBS_NOTIFY | WS_BORDER; 754 base_style = LBS_NOTIFY | WS_BORDER; 755 class = CTL_LISTBOX; 756 res_text_field = res_null_text; 757 } 758 control_params 759 { 760 $$ = $3; 761 } 762 | LTEXT optresidc 763 { 764 default_style = SS_LEFT | WS_GROUP; 765 base_style = SS_LEFT; 766 class = CTL_STATIC; 767 res_text_field = $2; 768 } 769 control_params 770 { 771 $$ = $4; 772 } 773 | PUSHBOX optresidc 774 { 775 default_style = BS_PUSHBOX | WS_TABSTOP; 776 base_style = BS_PUSHBOX; 777 class = CTL_BUTTON; 778 } 779 control_params 780 { 781 $$ = $4; 782 } 783 | PUSHBUTTON optresidc 784 { 785 default_style = BS_PUSHBUTTON | WS_TABSTOP; 786 base_style = BS_PUSHBUTTON | WS_TABSTOP; 787 class = CTL_BUTTON; 788 res_text_field = $2; 789 } 790 control_params 791 { 792 $$ = $4; 793 } 794 | RADIOBUTTON optresidc 795 { 796 default_style = BS_RADIOBUTTON | WS_TABSTOP; 797 base_style = BS_RADIOBUTTON; 798 class = CTL_BUTTON; 799 res_text_field = $2; 800 } 801 control_params 802 { 803 $$ = $4; 804 } 805 | RTEXT optresidc 806 { 807 default_style = SS_RIGHT | WS_GROUP; 808 base_style = SS_RIGHT; 809 class = CTL_STATIC; 810 res_text_field = $2; 811 } 812 control_params 813 { 814 $$ = $4; 815 } 816 | SCROLLBAR 817 { 818 default_style = SBS_HORZ; 819 base_style = 0; 820 class = CTL_SCROLLBAR; 821 res_text_field = res_null_text; 822 } 823 control_params 824 { 825 $$ = $3; 826 } 827 | STATE3 optresidc 828 { 829 default_style = BS_3STATE | WS_TABSTOP; 830 base_style = BS_3STATE; 831 class = CTL_BUTTON; 832 res_text_field = $2; 833 } 834 control_params 835 { 836 $$ = $4; 837 } 838 | USERBUTTON resref numexpr ',' numexpr ',' numexpr ',' 839 numexpr ',' numexpr ',' 840 { style = WS_CHILD | WS_VISIBLE; } 841 styleexpr optcnumexpr 842 { 843 $$ = define_control ($2, $3, $5, $7, $9, $11, CTL_BUTTON, 844 style, $15); 845 } 846 ; 847 848 /* Parameters for a control. The static variables DEFAULT_STYLE, 849 BASE_STYLE, and CLASS must be initialized before this nonterminal 850 is used. DEFAULT_STYLE is the style to use if no style expression 851 is specified. BASE_STYLE is the base style to use if a style 852 expression is specified; the style expression modifies the base 853 style. CLASS is the class of the control. */ 854 855 control_params: 856 numexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data 857 { 858 $$ = define_control (res_text_field, $1, $2, $3, $4, $5, class, 859 default_style | WS_CHILD | WS_VISIBLE, 0); 860 if ($6 != NULL) 861 { 862 if (dialog.ex == NULL) 863 rcparse_warning (_("control data requires DIALOGEX")); 864 $$->data = $6; 865 } 866 } 867 | numexpr cnumexpr cnumexpr cnumexpr cnumexpr 868 control_params_styleexpr optcnumexpr opt_control_data 869 { 870 $$ = define_control (res_text_field, $1, $2, $3, $4, $5, class, style, $7); 871 if ($8 != NULL) 872 { 873 if (dialog.ex == NULL) 874 rcparse_warning (_("control data requires DIALOGEX")); 875 $$->data = $8; 876 } 877 } 878 | numexpr cnumexpr cnumexpr cnumexpr cnumexpr 879 control_params_styleexpr cnumexpr cnumexpr opt_control_data 880 { 881 $$ = define_control (res_text_field, $1, $2, $3, $4, $5, class, style, $7); 882 if (dialog.ex == NULL) 883 rcparse_warning (_("help ID requires DIALOGEX")); 884 $$->help = $8; 885 $$->data = $9; 886 } 887 ; 888 889 optresidc: 890 /* empty */ 891 { 892 res_string_to_id (&$$, ""); 893 } 894 | posnumexpr ',' 895 { 896 $$.named = 0; 897 $$.u.id = $1; 898 } 899 | QUOTEDSTRING 900 { 901 res_string_to_id (&$$, $1); 902 } 903 | QUOTEDSTRING ',' 904 { 905 res_string_to_id (&$$, $1); 906 } 907 ; 908 909 opt_control_data: 910 /* empty */ 911 { 912 $$ = NULL; 913 } 914 | BEG optrcdata_data END 915 { 916 $$ = $2.first; 917 } 918 ; 919 920 /* These only exist to parse a reduction out of a common case. */ 921 922 control_styleexpr: 923 ',' 924 { style = WS_CHILD | WS_VISIBLE; } 925 styleexpr 926 ; 927 928 icon_styleexpr: 929 ',' 930 { style = SS_ICON | WS_CHILD | WS_VISIBLE; } 931 styleexpr 932 ; 933 934 control_params_styleexpr: 935 ',' 936 { style = base_style | WS_CHILD | WS_VISIBLE; } 937 styleexpr 938 ; 939 940 /* Font resources. */ 941 942 font: 943 id FONT memflags_move_discard file_name 944 { 945 define_font ($1, &$3, $4); 946 if (yychar != YYEMPTY) 947 YYERROR; 948 rcparse_discard_strings (); 949 } 950 ; 951 952 /* Icon resources. */ 953 954 icon: 955 id ICON memflags_move_discard file_name 956 { 957 define_icon ($1, &$3, $4); 958 if (yychar != YYEMPTY) 959 YYERROR; 960 rcparse_discard_strings (); 961 } 962 ; 963 964 /* Language command. This changes the static variable language, which 965 affects all subsequent resources. */ 966 967 language: 968 LANGUAGE numexpr cnumexpr 969 { 970 language = $2 | ($3 << SUBLANG_SHIFT); 971 } 972 ; 973 974 /* Menu resources. */ 975 976 menu: 977 id MENU suboptions BEG menuitems END 978 { 979 define_menu ($1, &$3, $5); 980 if (yychar != YYEMPTY) 981 YYERROR; 982 rcparse_discard_strings (); 983 } 984 ; 985 986 menuitems: 987 /* empty */ 988 { 989 $$ = NULL; 990 } 991 | menuitems menuitem 992 { 993 if ($1 == NULL) 994 $$ = $2; 995 else 996 { 997 struct menuitem **pp; 998 999 for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next) 1000 ; 1001 *pp = $2; 1002 $$ = $1; 1003 } 1004 } 1005 ; 1006 1007 menuitem: 1008 MENUITEM QUOTEDSTRING cnumexpr menuitem_flags 1009 { 1010 $$ = define_menuitem ($2, $3, $4, 0, 0, NULL); 1011 } 1012 | MENUITEM SEPARATOR 1013 { 1014 $$ = define_menuitem (NULL, 0, 0, 0, 0, NULL); 1015 } 1016 | POPUP QUOTEDSTRING menuitem_flags BEG menuitems END 1017 { 1018 $$ = define_menuitem ($2, 0, $3, 0, 0, $5); 1019 } 1020 ; 1021 1022 menuitem_flags: 1023 /* empty */ 1024 { 1025 $$ = 0; 1026 } 1027 | menuitem_flags ',' menuitem_flag 1028 { 1029 $$ = $1 | $3; 1030 } 1031 | menuitem_flags menuitem_flag 1032 { 1033 $$ = $1 | $2; 1034 } 1035 ; 1036 1037 menuitem_flag: 1038 CHECKED 1039 { 1040 $$ = MENUITEM_CHECKED; 1041 } 1042 | GRAYED 1043 { 1044 $$ = MENUITEM_GRAYED; 1045 } 1046 | HELP 1047 { 1048 $$ = MENUITEM_HELP; 1049 } 1050 | INACTIVE 1051 { 1052 $$ = MENUITEM_INACTIVE; 1053 } 1054 | MENUBARBREAK 1055 { 1056 $$ = MENUITEM_MENUBARBREAK; 1057 } 1058 | MENUBREAK 1059 { 1060 $$ = MENUITEM_MENUBREAK; 1061 } 1062 ; 1063 1064 /* Menuex resources. */ 1065 1066 menuex: 1067 id MENUEX suboptions BEG menuexitems END 1068 { 1069 define_menu ($1, &$3, $5); 1070 if (yychar != YYEMPTY) 1071 YYERROR; 1072 rcparse_discard_strings (); 1073 } 1074 ; 1075 1076 menuexitems: 1077 /* empty */ 1078 { 1079 $$ = NULL; 1080 } 1081 | menuexitems menuexitem 1082 { 1083 if ($1 == NULL) 1084 $$ = $2; 1085 else 1086 { 1087 struct menuitem **pp; 1088 1089 for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next) 1090 ; 1091 *pp = $2; 1092 $$ = $1; 1093 } 1094 } 1095 ; 1096 1097 menuexitem: 1098 MENUITEM QUOTEDSTRING 1099 { 1100 $$ = define_menuitem ($2, 0, 0, 0, 0, NULL); 1101 } 1102 | MENUITEM QUOTEDSTRING cnumexpr 1103 { 1104 $$ = define_menuitem ($2, $3, 0, 0, 0, NULL); 1105 } 1106 | MENUITEM QUOTEDSTRING cnumexpr cnumexpr optcnumexpr 1107 { 1108 $$ = define_menuitem ($2, $3, $4, $5, 0, NULL); 1109 } 1110 | MENUITEM SEPARATOR 1111 { 1112 $$ = define_menuitem (NULL, 0, 0, 0, 0, NULL); 1113 } 1114 | POPUP QUOTEDSTRING BEG menuexitems END 1115 { 1116 $$ = define_menuitem ($2, 0, 0, 0, 0, $4); 1117 } 1118 | POPUP QUOTEDSTRING cnumexpr BEG menuexitems END 1119 { 1120 $$ = define_menuitem ($2, $3, 0, 0, 0, $5); 1121 } 1122 | POPUP QUOTEDSTRING cnumexpr cnumexpr BEG menuexitems END 1123 { 1124 $$ = define_menuitem ($2, $3, $4, 0, 0, $6); 1125 } 1126 | POPUP QUOTEDSTRING cnumexpr cnumexpr cnumexpr optcnumexpr 1127 BEG menuexitems END 1128 { 1129 $$ = define_menuitem ($2, $3, $4, $5, $6, $8); 1130 } 1131 ; 1132 1133 /* Messagetable resources. */ 1134 1135 messagetable: 1136 id MESSAGETABLE memflags_move file_name 1137 { 1138 define_messagetable ($1, &$3, $4); 1139 if (yychar != YYEMPTY) 1140 YYERROR; 1141 rcparse_discard_strings (); 1142 } 1143 ; 1144 1145 /* Rcdata resources. */ 1146 1147 rcdata: 1148 id RCDATA suboptions BEG optrcdata_data END 1149 { 1150 define_rcdata ($1, &$3, $5.first); 1151 if (yychar != YYEMPTY) 1152 YYERROR; 1153 rcparse_discard_strings (); 1154 } 1155 ; 1156 1157 /* We use a different lexing algorithm, because rcdata strings may 1158 contain embedded null bytes, and we need to know the length to use. */ 1159 1160 optrcdata_data: 1161 { 1162 rcparse_rcdata (); 1163 } 1164 optrcdata_data_int 1165 { 1166 rcparse_normal (); 1167 $$ = $2; 1168 } 1169 ; 1170 1171 optrcdata_data_int: 1172 /* empty */ 1173 { 1174 $$.first = NULL; 1175 $$.last = NULL; 1176 } 1177 | rcdata_data 1178 { 1179 $$ = $1; 1180 } 1181 ; 1182 1183 rcdata_data: 1184 SIZEDSTRING 1185 { 1186 struct rcdata_item *ri; 1187 1188 ri = define_rcdata_string ($1.s, $1.length); 1189 $$.first = ri; 1190 $$.last = ri; 1191 } 1192 | sizednumexpr 1193 { 1194 struct rcdata_item *ri; 1195 1196 ri = define_rcdata_number ($1.val, $1.dword); 1197 $$.first = ri; 1198 $$.last = ri; 1199 } 1200 | rcdata_data ',' SIZEDSTRING 1201 { 1202 struct rcdata_item *ri; 1203 1204 ri = define_rcdata_string ($3.s, $3.length); 1205 $$.first = $1.first; 1206 $1.last->next = ri; 1207 $$.last = ri; 1208 } 1209 | rcdata_data ',' sizednumexpr 1210 { 1211 struct rcdata_item *ri; 1212 1213 ri = define_rcdata_number ($3.val, $3.dword); 1214 $$.first = $1.first; 1215 $1.last->next = ri; 1216 $$.last = ri; 1217 } 1218 ; 1219 1220 /* Stringtable resources. */ 1221 1222 stringtable: 1223 STRINGTABLE suboptions BEG 1224 { sub_res_info = $2; } 1225 string_data END 1226 ; 1227 1228 string_data: 1229 /* empty */ 1230 | string_data numexpr QUOTEDSTRING 1231 { 1232 define_stringtable (&sub_res_info, $2, $3); 1233 if (yychar != YYEMPTY) 1234 YYERROR; 1235 rcparse_discard_strings (); 1236 } 1237 | string_data numexpr ',' QUOTEDSTRING 1238 { 1239 define_stringtable (&sub_res_info, $2, $4); 1240 if (yychar != YYEMPTY) 1241 YYERROR; 1242 rcparse_discard_strings (); 1243 } 1244 ; 1245 1246 /* User defined resources. We accept general suboptions in the 1247 file_name case to keep the parser happy. */ 1248 1249 user: 1250 id id suboptions BEG optrcdata_data END 1251 { 1252 define_user_data ($1, $2, &$3, $5.first); 1253 if (yychar != YYEMPTY) 1254 YYERROR; 1255 rcparse_discard_strings (); 1256 } 1257 | id id suboptions file_name 1258 { 1259 define_user_file ($1, $2, &$3, $4); 1260 if (yychar != YYEMPTY) 1261 YYERROR; 1262 rcparse_discard_strings (); 1263 } 1264 ; 1265 1266 /* Versioninfo resources. */ 1267 1268 versioninfo: 1269 id VERSIONINFO fixedverinfo BEG verblocks END 1270 { 1271 define_versioninfo ($1, language, $3, $5); 1272 if (yychar != YYEMPTY) 1273 YYERROR; 1274 rcparse_discard_strings (); 1275 } 1276 ; 1277 1278 fixedverinfo: 1279 /* empty */ 1280 { 1281 $$ = ((struct fixed_versioninfo *) 1282 res_alloc (sizeof (struct fixed_versioninfo))); 1283 memset ($$, 0, sizeof (struct fixed_versioninfo)); 1284 } 1285 | fixedverinfo FILEVERSION numexpr cnumexpr cnumexpr cnumexpr 1286 { 1287 $1->file_version_ms = ($3 << 16) | $4; 1288 $1->file_version_ls = ($5 << 16) | $6; 1289 $$ = $1; 1290 } 1291 | fixedverinfo PRODUCTVERSION numexpr cnumexpr cnumexpr cnumexpr 1292 { 1293 $1->product_version_ms = ($3 << 16) | $4; 1294 $1->product_version_ls = ($5 << 16) | $6; 1295 $$ = $1; 1296 } 1297 | fixedverinfo FILEFLAGSMASK numexpr 1298 { 1299 $1->file_flags_mask = $3; 1300 $$ = $1; 1301 } 1302 | fixedverinfo FILEFLAGS numexpr 1303 { 1304 $1->file_flags = $3; 1305 $$ = $1; 1306 } 1307 | fixedverinfo FILEOS numexpr 1308 { 1309 $1->file_os = $3; 1310 $$ = $1; 1311 } 1312 | fixedverinfo FILETYPE numexpr 1313 { 1314 $1->file_type = $3; 1315 $$ = $1; 1316 } 1317 | fixedverinfo FILESUBTYPE numexpr 1318 { 1319 $1->file_subtype = $3; 1320 $$ = $1; 1321 } 1322 ; 1323 1324 /* To handle verblocks successfully, the lexer handles BLOCK 1325 specially. A BLOCK "StringFileInfo" is returned as 1326 BLOCKSTRINGFILEINFO. A BLOCK "VarFileInfo" is returned as 1327 BLOCKVARFILEINFO. A BLOCK with some other string returns BLOCK 1328 with the string as the value. */ 1329 1330 verblocks: 1331 /* empty */ 1332 { 1333 $$ = NULL; 1334 } 1335 | verblocks BLOCKSTRINGFILEINFO BEG BLOCK BEG vervals END END 1336 { 1337 $$ = append_ver_stringfileinfo ($1, $4, $6); 1338 } 1339 | verblocks BLOCKVARFILEINFO BEG VALUE QUOTEDSTRING vertrans END 1340 { 1341 $$ = append_ver_varfileinfo ($1, $5, $6); 1342 } 1343 ; 1344 1345 vervals: 1346 /* empty */ 1347 { 1348 $$ = NULL; 1349 } 1350 | vervals VALUE QUOTEDSTRING ',' QUOTEDSTRING 1351 { 1352 $$ = append_verval ($1, $3, $5); 1353 } 1354 ; 1355 1356 vertrans: 1357 /* empty */ 1358 { 1359 $$ = NULL; 1360 } 1361 | vertrans cnumexpr cnumexpr 1362 { 1363 $$ = append_vertrans ($1, $2, $3); 1364 } 1365 ; 1366 1367 /* A resource ID. */ 1368 1369 id: 1370 posnumexpr 1371 { 1372 $$.named = 0; 1373 $$.u.id = $1; 1374 } 1375 | STRING 1376 { 1377 char *copy, *s; 1378 1379 /* It seems that resource ID's are forced to upper case. */ 1380 copy = xstrdup ($1); 1381 for (s = copy; *s != '\0'; s++) 1382 *s = TOUPPER (*s); 1383 res_string_to_id (&$$, copy); 1384 free (copy); 1385 } 1386 ; 1387 1388 /* A resource reference. */ 1389 1390 resname: 1391 QUOTEDSTRING 1392 { 1393 $$ = $1; 1394 } 1395 | QUOTEDSTRING ',' 1396 { 1397 $$ = $1; 1398 } 1399 | STRING ',' 1400 { 1401 $$ = $1; 1402 } 1403 ; 1404 1405 1406 resref: 1407 posnumexpr ',' 1408 { 1409 $$.named = 0; 1410 $$.u.id = $1; 1411 } 1412 | resname 1413 { 1414 char *copy, *s; 1415 1416 /* It seems that resource ID's are forced to upper case. */ 1417 copy = xstrdup ($1); 1418 for (s = copy; *s != '\0'; s++) 1419 *s = TOUPPER (*s); 1420 res_string_to_id (&$$, copy); 1421 free (copy); 1422 } 1423 ; 1424 1425 /* Generic suboptions. These may appear before the BEGIN in any 1426 multiline statement. */ 1427 1428 suboptions: 1429 /* empty */ 1430 { 1431 memset (&$$, 0, sizeof (struct res_res_info)); 1432 $$.language = language; 1433 /* FIXME: Is this the right default? */ 1434 $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_PURE | MEMFLAG_DISCARDABLE; 1435 } 1436 | suboptions memflag 1437 { 1438 $$ = $1; 1439 $$.memflags |= $2.on; 1440 $$.memflags &=~ $2.off; 1441 } 1442 | suboptions CHARACTERISTICS numexpr 1443 { 1444 $$ = $1; 1445 $$.characteristics = $3; 1446 } 1447 | suboptions LANGUAGE numexpr cnumexpr 1448 { 1449 $$ = $1; 1450 $$.language = $3 | ($4 << SUBLANG_SHIFT); 1451 } 1452 | suboptions VERSIONK numexpr 1453 { 1454 $$ = $1; 1455 $$.version = $3; 1456 } 1457 ; 1458 1459 /* Memory flags which default to MOVEABLE and DISCARDABLE. */ 1460 1461 memflags_move_discard: 1462 /* empty */ 1463 { 1464 memset (&$$, 0, sizeof (struct res_res_info)); 1465 $$.language = language; 1466 $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_DISCARDABLE; 1467 } 1468 | memflags_move_discard memflag 1469 { 1470 $$ = $1; 1471 $$.memflags |= $2.on; 1472 $$.memflags &=~ $2.off; 1473 } 1474 ; 1475 1476 /* Memory flags which default to MOVEABLE. */ 1477 1478 memflags_move: 1479 /* empty */ 1480 { 1481 memset (&$$, 0, sizeof (struct res_res_info)); 1482 $$.language = language; 1483 $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_PURE | MEMFLAG_DISCARDABLE; 1484 } 1485 | memflags_move memflag 1486 { 1487 $$ = $1; 1488 $$.memflags |= $2.on; 1489 $$.memflags &=~ $2.off; 1490 } 1491 ; 1492 1493 /* Memory flags. This returns a struct with two integers, because we 1494 sometimes want to set bits and we sometimes want to clear them. */ 1495 1496 memflag: 1497 MOVEABLE 1498 { 1499 $$.on = MEMFLAG_MOVEABLE; 1500 $$.off = 0; 1501 } 1502 | FIXED 1503 { 1504 $$.on = 0; 1505 $$.off = MEMFLAG_MOVEABLE; 1506 } 1507 | PURE 1508 { 1509 $$.on = MEMFLAG_PURE; 1510 $$.off = 0; 1511 } 1512 | IMPURE 1513 { 1514 $$.on = 0; 1515 $$.off = MEMFLAG_PURE; 1516 } 1517 | PRELOAD 1518 { 1519 $$.on = MEMFLAG_PRELOAD; 1520 $$.off = 0; 1521 } 1522 | LOADONCALL 1523 { 1524 $$.on = 0; 1525 $$.off = MEMFLAG_PRELOAD; 1526 } 1527 | DISCARDABLE 1528 { 1529 $$.on = MEMFLAG_DISCARDABLE; 1530 $$.off = 0; 1531 } 1532 ; 1533 1534 /* A file name. */ 1535 1536 file_name: 1537 QUOTEDSTRING 1538 { 1539 $$ = $1; 1540 } 1541 | STRING 1542 { 1543 $$ = $1; 1544 } 1545 ; 1546 1547 /* A style expression. This changes the static variable STYLE. We do 1548 it this way because rc appears to permit a style to be set to 1549 something like 1550 WS_GROUP | NOT WS_TABSTOP 1551 to mean that a default of WS_TABSTOP should be removed. Anything 1552 which wants to accept a style must first set STYLE to the default 1553 value. The styleexpr nonterminal will change STYLE as specified by 1554 the user. Note that we do not accept arbitrary expressions here, 1555 just numbers separated by '|'. */ 1556 1557 styleexpr: 1558 parennumber 1559 { 1560 style |= $1; 1561 } 1562 | NOT parennumber 1563 { 1564 style &=~ $2; 1565 } 1566 | styleexpr '|' parennumber 1567 { 1568 style |= $3; 1569 } 1570 | styleexpr '|' NOT parennumber 1571 { 1572 style &=~ $4; 1573 } 1574 ; 1575 1576 parennumber: 1577 NUMBER 1578 { 1579 $$ = $1.val; 1580 } 1581 | '(' numexpr ')' 1582 { 1583 $$ = $2; 1584 } 1585 ; 1586 1587 /* An optional expression with a leading comma. */ 1588 1589 optcnumexpr: 1590 /* empty */ 1591 { 1592 $$ = 0; 1593 } 1594 | cnumexpr 1595 { 1596 $$ = $1; 1597 } 1598 ; 1599 1600 /* An expression with a leading comma. */ 1601 1602 cnumexpr: 1603 ',' numexpr 1604 { 1605 $$ = $2; 1606 } 1607 ; 1608 1609 /* A possibly negated numeric expression. */ 1610 1611 numexpr: 1612 sizednumexpr 1613 { 1614 $$ = $1.val; 1615 } 1616 ; 1617 1618 /* A possibly negated expression with a size. */ 1619 1620 sizednumexpr: 1621 NUMBER 1622 { 1623 $$ = $1; 1624 } 1625 | '(' sizednumexpr ')' 1626 { 1627 $$ = $2; 1628 } 1629 | '~' sizednumexpr %prec '~' 1630 { 1631 $$.val = ~ $2.val; 1632 $$.dword = $2.dword; 1633 } 1634 | '-' sizednumexpr %prec NEG 1635 { 1636 $$.val = - $2.val; 1637 $$.dword = $2.dword; 1638 } 1639 | sizednumexpr '*' sizednumexpr 1640 { 1641 $$.val = $1.val * $3.val; 1642 $$.dword = $1.dword || $3.dword; 1643 } 1644 | sizednumexpr '/' sizednumexpr 1645 { 1646 $$.val = $1.val / $3.val; 1647 $$.dword = $1.dword || $3.dword; 1648 } 1649 | sizednumexpr '%' sizednumexpr 1650 { 1651 $$.val = $1.val % $3.val; 1652 $$.dword = $1.dword || $3.dword; 1653 } 1654 | sizednumexpr '+' sizednumexpr 1655 { 1656 $$.val = $1.val + $3.val; 1657 $$.dword = $1.dword || $3.dword; 1658 } 1659 | sizednumexpr '-' sizednumexpr 1660 { 1661 $$.val = $1.val - $3.val; 1662 $$.dword = $1.dword || $3.dword; 1663 } 1664 | sizednumexpr '&' sizednumexpr 1665 { 1666 $$.val = $1.val & $3.val; 1667 $$.dword = $1.dword || $3.dword; 1668 } 1669 | sizednumexpr '^' sizednumexpr 1670 { 1671 $$.val = $1.val ^ $3.val; 1672 $$.dword = $1.dword || $3.dword; 1673 } 1674 | sizednumexpr '|' sizednumexpr 1675 { 1676 $$.val = $1.val | $3.val; 1677 $$.dword = $1.dword || $3.dword; 1678 } 1679 ; 1680 1681 /* An expression with a leading comma which does not use unary 1682 negation. */ 1683 1684 cposnumexpr: 1685 ',' posnumexpr 1686 { 1687 $$ = $2; 1688 } 1689 ; 1690 1691 /* An expression which does not use unary negation. */ 1692 1693 posnumexpr: 1694 sizedposnumexpr 1695 { 1696 $$ = $1.val; 1697 } 1698 ; 1699 1700 /* An expression which does not use unary negation. We separate unary 1701 negation to avoid parsing conflicts when two numeric expressions 1702 appear consecutively. */ 1703 1704 sizedposnumexpr: 1705 NUMBER 1706 { 1707 $$ = $1; 1708 } 1709 | '(' sizednumexpr ')' 1710 { 1711 $$ = $2; 1712 } 1713 | '~' sizednumexpr %prec '~' 1714 { 1715 $$.val = ~ $2.val; 1716 $$.dword = $2.dword; 1717 } 1718 | sizedposnumexpr '*' sizednumexpr 1719 { 1720 $$.val = $1.val * $3.val; 1721 $$.dword = $1.dword || $3.dword; 1722 } 1723 | sizedposnumexpr '/' sizednumexpr 1724 { 1725 $$.val = $1.val / $3.val; 1726 $$.dword = $1.dword || $3.dword; 1727 } 1728 | sizedposnumexpr '%' sizednumexpr 1729 { 1730 $$.val = $1.val % $3.val; 1731 $$.dword = $1.dword || $3.dword; 1732 } 1733 | sizedposnumexpr '+' sizednumexpr 1734 { 1735 $$.val = $1.val + $3.val; 1736 $$.dword = $1.dword || $3.dword; 1737 } 1738 | sizedposnumexpr '-' sizednumexpr 1739 { 1740 $$.val = $1.val - $3.val; 1741 $$.dword = $1.dword || $3.dword; 1742 } 1743 | sizedposnumexpr '&' sizednumexpr 1744 { 1745 $$.val = $1.val & $3.val; 1746 $$.dword = $1.dword || $3.dword; 1747 } 1748 | sizedposnumexpr '^' sizednumexpr 1749 { 1750 $$.val = $1.val ^ $3.val; 1751 $$.dword = $1.dword || $3.dword; 1752 } 1753 | sizedposnumexpr '|' sizednumexpr 1754 { 1755 $$.val = $1.val | $3.val; 1756 $$.dword = $1.dword || $3.dword; 1757 } 1758 ; 1759 1760 %% 1761 1762 /* Set the language from the command line. */ 1763 1764 void 1765 rcparse_set_language (int lang) 1766 { 1767 language = lang; 1768 } 1769