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