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