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