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