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