2003-09-30 H.J. Lu <hongjiu.lu@intel.com>
[binutils.git] / binutils / rcparse.y
blob7aacaaa067326d2bd720527b8141922c8def2b54
1 %{ /* rcparse.y -- parser for Windows rc files
2 Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Cygnus Support.
5 This file is part of GNU Binutils.
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.
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.
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. */
22 /* This is a parser for Windows rc files. It is based on the parser
23 by Gunther Ebert <gunther.ebert@ixos-leipzig.de>. */
25 #include "bfd.h"
26 #include "bucomm.h"
27 #include "libiberty.h"
28 #include "windres.h"
29 #include "safe-ctype.h"
31 /* The current language. */
33 static unsigned short language;
35 /* The resource information during a sub statement. */
37 static struct res_res_info sub_res_info;
39 /* Dialog information. This is built by the nonterminals styles and
40 controls. */
42 static struct dialog dialog;
44 /* This is used when building a style. It is modified by the
45 nonterminal styleexpr. */
47 static unsigned long style;
49 /* These are used when building a control. They are set before using
50 control_params. */
52 static unsigned long base_style;
53 static unsigned long default_style;
54 static unsigned long class;
55 static struct res_id res_text_field;
57 /* This is used for COMBOBOX, LISTBOX and EDITTEXT which
58 do not allow resource 'text' field in control definition. */
59 static const struct res_id res_null_text = { 1, {{0, L""}}};
63 %union
65 struct accelerator acc;
66 struct accelerator *pacc;
67 struct dialog_control *dialog_control;
68 struct menuitem *menuitem;
69 struct
71 struct rcdata_item *first;
72 struct rcdata_item *last;
73 } rcdata;
74 struct rcdata_item *rcdata_item;
75 struct stringtable_data *stringtable;
76 struct fixed_versioninfo *fixver;
77 struct ver_info *verinfo;
78 struct ver_stringinfo *verstring;
79 struct ver_varinfo *vervar;
80 struct res_id id;
81 struct res_res_info res_info;
82 struct
84 unsigned short on;
85 unsigned short off;
86 } memflags;
87 struct
89 unsigned long val;
90 /* Nonzero if this number was explicitly specified as long. */
91 int dword;
92 } i;
93 unsigned long il;
94 unsigned short is;
95 const char *s;
96 struct
98 unsigned long length;
99 const char *s;
100 } ss;
103 %token BEG END
104 %token ACCELERATORS VIRTKEY ASCII NOINVERT SHIFT CONTROL ALT
105 %token BITMAP
106 %token CURSOR
107 %token DIALOG DIALOGEX EXSTYLE CAPTION CLASS STYLE
108 %token AUTO3STATE AUTOCHECKBOX AUTORADIOBUTTON CHECKBOX COMBOBOX CTEXT
109 %token DEFPUSHBUTTON EDITTEXT GROUPBOX LISTBOX LTEXT PUSHBOX PUSHBUTTON
110 %token RADIOBUTTON RTEXT SCROLLBAR STATE3 USERBUTTON
111 %token BEDIT HEDIT IEDIT
112 %token FONT
113 %token ICON
114 %token LANGUAGE CHARACTERISTICS VERSIONK
115 %token MENU MENUEX MENUITEM SEPARATOR POPUP CHECKED GRAYED HELP INACTIVE
116 %token MENUBARBREAK MENUBREAK
117 %token MESSAGETABLE
118 %token RCDATA
119 %token STRINGTABLE
120 %token VERSIONINFO FILEVERSION PRODUCTVERSION FILEFLAGSMASK FILEFLAGS
121 %token FILEOS FILETYPE FILESUBTYPE BLOCKSTRINGFILEINFO BLOCKVARFILEINFO
122 %token VALUE
123 %token <s> BLOCK
124 %token MOVEABLE FIXED PURE IMPURE PRELOAD LOADONCALL DISCARDABLE
125 %token NOT
126 %token <s> QUOTEDSTRING STRING
127 %token <i> NUMBER
128 %token <ss> SIZEDSTRING
129 %token IGNORED_TOKEN
131 %type <pacc> acc_entries
132 %type <acc> acc_entry acc_event
133 %type <dialog_control> control control_params
134 %type <menuitem> menuitems menuitem menuexitems menuexitem
135 %type <rcdata> optrcdata_data optrcdata_data_int rcdata_data
136 %type <rcdata_item> opt_control_data
137 %type <fixver> fixedverinfo
138 %type <verinfo> verblocks
139 %type <verstring> vervals
140 %type <vervar> vertrans
141 %type <res_info> suboptions memflags_move_discard memflags_move
142 %type <memflags> memflag
143 %type <id> id optresidc resref
144 %type <il> exstyle parennumber
145 %type <il> numexpr posnumexpr cnumexpr optcnumexpr cposnumexpr
146 %type <is> acc_options acc_option menuitem_flags menuitem_flag
147 %type <s> file_name resname
148 %type <i> sizednumexpr sizedposnumexpr
150 %left '|'
151 %left '^'
152 %left '&'
153 %left '+' '-'
154 %left '*' '/' '%'
155 %right '~' NEG
159 input:
160 /* empty */
161 | input accelerator
162 | input bitmap
163 | input cursor
164 | input dialog
165 | input font
166 | input icon
167 | input language
168 | input menu
169 | input menuex
170 | input messagetable
171 | input rcdata
172 | input stringtable
173 | input user
174 | input versioninfo
175 | input IGNORED_TOKEN
178 /* Accelerator resources. */
180 accelerator:
181 id ACCELERATORS suboptions BEG acc_entries END
183 define_accelerator ($1, &$3, $5);
184 if (yychar != YYEMPTY)
185 YYERROR;
186 rcparse_discard_strings ();
190 acc_entries:
191 /* empty */
193 $$ = NULL;
195 | acc_entries acc_entry
197 struct accelerator *a;
199 a = (struct accelerator *) res_alloc (sizeof *a);
200 *a = $2;
201 if ($1 == NULL)
202 $$ = a;
203 else
205 struct accelerator **pp;
207 for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
209 *pp = a;
210 $$ = $1;
215 acc_entry:
216 acc_event cposnumexpr
218 $$ = $1;
219 $$.id = $2;
221 | acc_event cposnumexpr ',' acc_options
223 $$ = $1;
224 $$.id = $2;
225 $$.flags |= $4;
226 if (($$.flags & ACC_VIRTKEY) == 0
227 && ($$.flags & (ACC_SHIFT | ACC_CONTROL)) != 0)
228 rcparse_warning (_("inappropriate modifiers for non-VIRTKEY"));
232 acc_event:
233 QUOTEDSTRING
235 const char *s = $1;
236 char ch;
238 $$.next = NULL;
239 $$.id = 0;
240 ch = *s;
241 if (ch != '^')
242 $$.flags = 0;
243 else
245 $$.flags = ACC_CONTROL | ACC_VIRTKEY;
246 ++s;
247 ch = *s;
248 ch = TOUPPER (ch);
250 $$.key = ch;
251 if (s[1] != '\0')
252 rcparse_warning (_("accelerator should only be one character"));
254 | posnumexpr
256 $$.next = NULL;
257 $$.flags = 0;
258 $$.id = 0;
259 $$.key = $1;
263 acc_options:
264 acc_option
266 $$ = $1;
268 | acc_options ',' acc_option
270 $$ = $1 | $3;
272 /* I've had one report that the comma is optional. */
273 | acc_options acc_option
275 $$ = $1 | $2;
279 acc_option:
280 VIRTKEY
282 $$ = ACC_VIRTKEY;
284 | ASCII
286 /* This is just the absence of VIRTKEY. */
287 $$ = 0;
289 | NOINVERT
291 $$ = ACC_NOINVERT;
293 | SHIFT
295 $$ = ACC_SHIFT;
297 | CONTROL
299 $$ = ACC_CONTROL;
301 | ALT
303 $$ = ACC_ALT;
307 /* Bitmap resources. */
309 bitmap:
310 id BITMAP memflags_move file_name
312 define_bitmap ($1, &$3, $4);
313 if (yychar != YYEMPTY)
314 YYERROR;
315 rcparse_discard_strings ();
319 /* Cursor resources. */
321 cursor:
322 id CURSOR memflags_move_discard file_name
324 define_cursor ($1, &$3, $4);
325 if (yychar != YYEMPTY)
326 YYERROR;
327 rcparse_discard_strings ();
331 /* Dialog resources. */
333 dialog:
334 id DIALOG memflags_move exstyle posnumexpr cnumexpr cnumexpr
335 cnumexpr
337 memset (&dialog, 0, sizeof dialog);
338 dialog.x = $5;
339 dialog.y = $6;
340 dialog.width = $7;
341 dialog.height = $8;
342 dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU;
343 dialog.exstyle = $4;
344 dialog.menu.named = 1;
345 dialog.class.named = 1;
346 dialog.font = NULL;
347 dialog.ex = NULL;
348 dialog.controls = NULL;
349 sub_res_info = $3;
350 style = 0;
352 styles BEG controls END
354 define_dialog ($1, &sub_res_info, &dialog);
355 if (yychar != YYEMPTY)
356 YYERROR;
357 rcparse_discard_strings ();
359 | id DIALOGEX memflags_move exstyle posnumexpr cnumexpr cnumexpr
360 cnumexpr
362 memset (&dialog, 0, sizeof dialog);
363 dialog.x = $5;
364 dialog.y = $6;
365 dialog.width = $7;
366 dialog.height = $8;
367 dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU;
368 dialog.exstyle = $4;
369 dialog.menu.named = 1;
370 dialog.class.named = 1;
371 dialog.font = NULL;
372 dialog.ex = ((struct dialog_ex *)
373 res_alloc (sizeof (struct dialog_ex)));
374 memset (dialog.ex, 0, sizeof (struct dialog_ex));
375 dialog.controls = NULL;
376 sub_res_info = $3;
377 style = 0;
379 styles BEG controls END
381 define_dialog ($1, &sub_res_info, &dialog);
382 if (yychar != YYEMPTY)
383 YYERROR;
384 rcparse_discard_strings ();
386 | id DIALOGEX memflags_move exstyle posnumexpr cnumexpr cnumexpr
387 cnumexpr cnumexpr
389 memset (&dialog, 0, sizeof dialog);
390 dialog.x = $5;
391 dialog.y = $6;
392 dialog.width = $7;
393 dialog.height = $8;
394 dialog.style = WS_POPUP | WS_BORDER | WS_SYSMENU;
395 dialog.exstyle = $4;
396 dialog.menu.named = 1;
397 dialog.class.named = 1;
398 dialog.font = NULL;
399 dialog.ex = ((struct dialog_ex *)
400 res_alloc (sizeof (struct dialog_ex)));
401 memset (dialog.ex, 0, sizeof (struct dialog_ex));
402 dialog.ex->help = $9;
403 dialog.controls = NULL;
404 sub_res_info = $3;
405 style = 0;
407 styles BEG controls END
409 define_dialog ($1, &sub_res_info, &dialog);
410 if (yychar != YYEMPTY)
411 YYERROR;
412 rcparse_discard_strings ();
416 exstyle:
417 /* empty */
419 $$ = 0;
421 | EXSTYLE '=' numexpr
423 $$ = $3;
427 styles:
428 /* empty */
429 | styles CAPTION QUOTEDSTRING
431 dialog.style |= WS_CAPTION;
432 style |= WS_CAPTION;
433 unicode_from_ascii ((int *) NULL, &dialog.caption, $3);
435 | styles CLASS id
437 dialog.class = $3;
439 | styles STYLE
440 styleexpr
442 dialog.style = style;
444 | styles EXSTYLE numexpr
446 dialog.exstyle = $3;
448 | styles CLASS QUOTEDSTRING
450 res_string_to_id (& dialog.class, $3);
452 | styles FONT numexpr ',' QUOTEDSTRING
454 dialog.style |= DS_SETFONT;
455 style |= DS_SETFONT;
456 dialog.pointsize = $3;
457 unicode_from_ascii ((int *) NULL, &dialog.font, $5);
458 if (dialog.ex != NULL)
460 dialog.ex->weight = 0;
461 dialog.ex->italic = 0;
462 dialog.ex->charset = 1;
465 | styles FONT numexpr ',' QUOTEDSTRING cnumexpr
467 dialog.style |= DS_SETFONT;
468 style |= DS_SETFONT;
469 dialog.pointsize = $3;
470 unicode_from_ascii ((int *) NULL, &dialog.font, $5);
471 if (dialog.ex == NULL)
472 rcparse_warning (_("extended FONT requires DIALOGEX"));
473 else
475 dialog.ex->weight = $6;
476 dialog.ex->italic = 0;
477 dialog.ex->charset = 1;
480 | styles FONT numexpr ',' QUOTEDSTRING cnumexpr cnumexpr
482 dialog.style |= DS_SETFONT;
483 style |= DS_SETFONT;
484 dialog.pointsize = $3;
485 unicode_from_ascii ((int *) NULL, &dialog.font, $5);
486 if (dialog.ex == NULL)
487 rcparse_warning (_("extended FONT requires DIALOGEX"));
488 else
490 dialog.ex->weight = $6;
491 dialog.ex->italic = $7;
492 dialog.ex->charset = 1;
495 | styles FONT numexpr ',' QUOTEDSTRING cnumexpr cnumexpr cnumexpr
497 dialog.style |= DS_SETFONT;
498 style |= DS_SETFONT;
499 dialog.pointsize = $3;
500 unicode_from_ascii ((int *) NULL, &dialog.font, $5);
501 if (dialog.ex == NULL)
502 rcparse_warning (_("extended FONT requires DIALOGEX"));
503 else
505 dialog.ex->weight = $6;
506 dialog.ex->italic = $7;
507 dialog.ex->charset = $8;
510 | styles MENU id
512 dialog.menu = $3;
514 | styles CHARACTERISTICS numexpr
516 sub_res_info.characteristics = $3;
518 | styles LANGUAGE numexpr cnumexpr
520 sub_res_info.language = $3 | ($4 << SUBLANG_SHIFT);
522 | styles VERSIONK numexpr
524 sub_res_info.version = $3;
528 controls:
529 /* empty */
530 | controls control
532 struct dialog_control **pp;
534 for (pp = &dialog.controls; *pp != NULL; pp = &(*pp)->next)
536 *pp = $2;
540 control:
541 AUTO3STATE optresidc
543 default_style = BS_AUTO3STATE | WS_TABSTOP;
544 base_style = BS_AUTO3STATE;
545 class = CTL_BUTTON;
546 res_text_field = $2;
548 control_params
550 $$ = $4;
552 | AUTOCHECKBOX optresidc
554 default_style = BS_AUTOCHECKBOX | WS_TABSTOP;
555 base_style = BS_AUTOCHECKBOX;
556 class = CTL_BUTTON;
557 res_text_field = $2;
559 control_params
561 $$ = $4;
563 | AUTORADIOBUTTON optresidc
565 default_style = BS_AUTORADIOBUTTON | WS_TABSTOP;
566 base_style = BS_AUTORADIOBUTTON;
567 class = CTL_BUTTON;
568 res_text_field = $2;
570 control_params
572 $$ = $4;
574 | BEDIT optresidc
576 default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
577 base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
578 class = CTL_EDIT;
579 res_text_field = $2;
581 control_params
583 $$ = $4;
584 if (dialog.ex == NULL)
585 rcparse_warning (_("BEDIT requires DIALOGEX"));
586 res_string_to_id (&$$->class, "BEDIT");
588 | CHECKBOX optresidc
590 default_style = BS_CHECKBOX | WS_TABSTOP;
591 base_style = BS_CHECKBOX | WS_TABSTOP;
592 class = CTL_BUTTON;
593 res_text_field = $2;
595 control_params
597 $$ = $4;
599 | COMBOBOX
601 /* This is as per MSDN documentation. With some (???)
602 versions of MS rc.exe their is no default style. */
603 default_style = CBS_SIMPLE | WS_TABSTOP;
604 base_style = 0;
605 class = CTL_COMBOBOX;
606 res_text_field = res_null_text;
608 control_params
610 $$ = $3;
612 | CONTROL optresidc numexpr cnumexpr control_styleexpr cnumexpr
613 cnumexpr cnumexpr cnumexpr optcnumexpr opt_control_data
615 $$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10);
616 if ($11 != NULL)
618 if (dialog.ex == NULL)
619 rcparse_warning (_("control data requires DIALOGEX"));
620 $$->data = $11;
623 | CONTROL optresidc numexpr cnumexpr control_styleexpr cnumexpr
624 cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data
626 $$ = define_control ($2, $3, $6, $7, $8, $9, $4, style, $10);
627 if (dialog.ex == NULL)
628 rcparse_warning (_("help ID requires DIALOGEX"));
629 $$->help = $11;
630 $$->data = $12;
632 | CONTROL optresidc numexpr ',' QUOTEDSTRING control_styleexpr
633 cnumexpr cnumexpr cnumexpr cnumexpr optcnumexpr opt_control_data
635 $$ = define_control ($2, $3, $7, $8, $9, $10, 0, style, $11);
636 if ($12 != NULL)
638 if (dialog.ex == NULL)
639 rcparse_warning ("control data requires DIALOGEX");
640 $$->data = $12;
642 $$->class.named = 1;
643 unicode_from_ascii (&$$->class.u.n.length, &$$->class.u.n.name, $5);
645 | CONTROL optresidc numexpr ',' QUOTEDSTRING control_styleexpr
646 cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data
648 $$ = define_control ($2, $3, $7, $8, $9, $10, 0, style, $11);
649 if (dialog.ex == NULL)
650 rcparse_warning ("help ID requires DIALOGEX");
651 $$->help = $12;
652 $$->data = $13;
653 $$->class.named = 1;
654 unicode_from_ascii (&$$->class.u.n.length, &$$->class.u.n.name, $5);
656 | CTEXT optresidc
658 default_style = SS_CENTER | WS_GROUP;
659 base_style = SS_CENTER;
660 class = CTL_STATIC;
661 res_text_field = $2;
663 control_params
665 $$ = $4;
667 | DEFPUSHBUTTON optresidc
669 default_style = BS_DEFPUSHBUTTON | WS_TABSTOP;
670 base_style = BS_DEFPUSHBUTTON | WS_TABSTOP;
671 class = CTL_BUTTON;
672 res_text_field = $2;
674 control_params
676 $$ = $4;
678 | EDITTEXT
680 default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
681 base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
682 class = CTL_EDIT;
683 res_text_field = res_null_text;
685 control_params
687 $$ = $3;
689 | GROUPBOX optresidc
691 default_style = BS_GROUPBOX;
692 base_style = BS_GROUPBOX;
693 class = CTL_BUTTON;
694 res_text_field = $2;
696 control_params
698 $$ = $4;
700 | HEDIT optresidc
702 default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
703 base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
704 class = CTL_EDIT;
705 res_text_field = $2;
707 control_params
709 $$ = $4;
710 if (dialog.ex == NULL)
711 rcparse_warning (_("IEDIT requires DIALOGEX"));
712 res_string_to_id (&$$->class, "HEDIT");
714 | ICON resref numexpr cnumexpr cnumexpr opt_control_data
716 $$ = define_icon_control ($2, $3, $4, $5, 0, 0, 0, $6,
717 dialog.ex);
719 | ICON resref numexpr cnumexpr cnumexpr cnumexpr cnumexpr
720 opt_control_data
722 $$ = define_icon_control ($2, $3, $4, $5, 0, 0, 0, $8,
723 dialog.ex);
725 | ICON resref numexpr cnumexpr cnumexpr cnumexpr cnumexpr
726 icon_styleexpr optcnumexpr opt_control_data
728 $$ = define_icon_control ($2, $3, $4, $5, style, $9, 0, $10,
729 dialog.ex);
731 | ICON resref numexpr cnumexpr cnumexpr cnumexpr cnumexpr
732 icon_styleexpr cnumexpr cnumexpr opt_control_data
734 $$ = define_icon_control ($2, $3, $4, $5, style, $9, $10, $11,
735 dialog.ex);
737 | IEDIT optresidc
739 default_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
740 base_style = ES_LEFT | WS_BORDER | WS_TABSTOP;
741 class = CTL_EDIT;
742 res_text_field = $2;
744 control_params
746 $$ = $4;
747 if (dialog.ex == NULL)
748 rcparse_warning (_("IEDIT requires DIALOGEX"));
749 res_string_to_id (&$$->class, "IEDIT");
751 | LISTBOX
753 default_style = LBS_NOTIFY | WS_BORDER;
754 base_style = LBS_NOTIFY | WS_BORDER;
755 class = CTL_LISTBOX;
756 res_text_field = res_null_text;
758 control_params
760 $$ = $3;
762 | LTEXT optresidc
764 default_style = SS_LEFT | WS_GROUP;
765 base_style = SS_LEFT;
766 class = CTL_STATIC;
767 res_text_field = $2;
769 control_params
771 $$ = $4;
773 | PUSHBOX optresidc
775 default_style = BS_PUSHBOX | WS_TABSTOP;
776 base_style = BS_PUSHBOX;
777 class = CTL_BUTTON;
779 control_params
781 $$ = $4;
783 | PUSHBUTTON optresidc
785 default_style = BS_PUSHBUTTON | WS_TABSTOP;
786 base_style = BS_PUSHBUTTON | WS_TABSTOP;
787 class = CTL_BUTTON;
788 res_text_field = $2;
790 control_params
792 $$ = $4;
794 | RADIOBUTTON optresidc
796 default_style = BS_RADIOBUTTON | WS_TABSTOP;
797 base_style = BS_RADIOBUTTON;
798 class = CTL_BUTTON;
799 res_text_field = $2;
801 control_params
803 $$ = $4;
805 | RTEXT optresidc
807 default_style = SS_RIGHT | WS_GROUP;
808 base_style = SS_RIGHT;
809 class = CTL_STATIC;
810 res_text_field = $2;
812 control_params
814 $$ = $4;
816 | SCROLLBAR
818 default_style = SBS_HORZ;
819 base_style = 0;
820 class = CTL_SCROLLBAR;
821 res_text_field = res_null_text;
823 control_params
825 $$ = $3;
827 | STATE3 optresidc
829 default_style = BS_3STATE | WS_TABSTOP;
830 base_style = BS_3STATE;
831 class = CTL_BUTTON;
832 res_text_field = $2;
834 control_params
836 $$ = $4;
838 | USERBUTTON resref numexpr ',' numexpr ',' numexpr ','
839 numexpr ',' numexpr ','
840 { style = WS_CHILD | WS_VISIBLE; }
841 styleexpr optcnumexpr
843 $$ = define_control ($2, $3, $5, $7, $9, $11, CTL_BUTTON,
844 style, $15);
848 /* Parameters for a control. The static variables DEFAULT_STYLE,
849 BASE_STYLE, and CLASS must be initialized before this nonterminal
850 is used. DEFAULT_STYLE is the style to use if no style expression
851 is specified. BASE_STYLE is the base style to use if a style
852 expression is specified; the style expression modifies the base
853 style. CLASS is the class of the control. */
855 control_params:
856 numexpr cnumexpr cnumexpr cnumexpr cnumexpr opt_control_data
858 $$ = define_control (res_text_field, $1, $2, $3, $4, $5, class,
859 default_style | WS_CHILD | WS_VISIBLE, 0);
860 if ($6 != NULL)
862 if (dialog.ex == NULL)
863 rcparse_warning (_("control data requires DIALOGEX"));
864 $$->data = $6;
867 | numexpr cnumexpr cnumexpr cnumexpr cnumexpr
868 control_params_styleexpr optcnumexpr opt_control_data
870 $$ = define_control (res_text_field, $1, $2, $3, $4, $5, class, style, $7);
871 if ($8 != NULL)
873 if (dialog.ex == NULL)
874 rcparse_warning (_("control data requires DIALOGEX"));
875 $$->data = $8;
878 | numexpr cnumexpr cnumexpr cnumexpr cnumexpr
879 control_params_styleexpr cnumexpr cnumexpr opt_control_data
881 $$ = define_control (res_text_field, $1, $2, $3, $4, $5, class, style, $7);
882 if (dialog.ex == NULL)
883 rcparse_warning (_("help ID requires DIALOGEX"));
884 $$->help = $8;
885 $$->data = $9;
889 optresidc:
890 /* empty */
892 res_string_to_id (&$$, "");
894 | posnumexpr ','
896 $$.named = 0;
897 $$.u.id = $1;
899 | QUOTEDSTRING
901 res_string_to_id (&$$, $1);
903 | QUOTEDSTRING ','
905 res_string_to_id (&$$, $1);
909 opt_control_data:
910 /* empty */
912 $$ = NULL;
914 | BEG optrcdata_data END
916 $$ = $2.first;
920 /* These only exist to parse a reduction out of a common case. */
922 control_styleexpr:
924 { style = WS_CHILD | WS_VISIBLE; }
925 styleexpr
928 icon_styleexpr:
930 { style = SS_ICON | WS_CHILD | WS_VISIBLE; }
931 styleexpr
934 control_params_styleexpr:
936 { style = base_style | WS_CHILD | WS_VISIBLE; }
937 styleexpr
940 /* Font resources. */
942 font:
943 id FONT memflags_move_discard file_name
945 define_font ($1, &$3, $4);
946 if (yychar != YYEMPTY)
947 YYERROR;
948 rcparse_discard_strings ();
952 /* Icon resources. */
954 icon:
955 id ICON memflags_move_discard file_name
957 define_icon ($1, &$3, $4);
958 if (yychar != YYEMPTY)
959 YYERROR;
960 rcparse_discard_strings ();
964 /* Language command. This changes the static variable language, which
965 affects all subsequent resources. */
967 language:
968 LANGUAGE numexpr cnumexpr
970 language = $2 | ($3 << SUBLANG_SHIFT);
974 /* Menu resources. */
976 menu:
977 id MENU suboptions BEG menuitems END
979 define_menu ($1, &$3, $5);
980 if (yychar != YYEMPTY)
981 YYERROR;
982 rcparse_discard_strings ();
986 menuitems:
987 /* empty */
989 $$ = NULL;
991 | menuitems menuitem
993 if ($1 == NULL)
994 $$ = $2;
995 else
997 struct menuitem **pp;
999 for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
1001 *pp = $2;
1002 $$ = $1;
1007 menuitem:
1008 MENUITEM QUOTEDSTRING cnumexpr menuitem_flags
1010 $$ = define_menuitem ($2, $3, $4, 0, 0, NULL);
1012 | MENUITEM SEPARATOR
1014 $$ = define_menuitem (NULL, 0, 0, 0, 0, NULL);
1016 | POPUP QUOTEDSTRING menuitem_flags BEG menuitems END
1018 $$ = define_menuitem ($2, 0, $3, 0, 0, $5);
1022 menuitem_flags:
1023 /* empty */
1025 $$ = 0;
1027 | menuitem_flags ',' menuitem_flag
1029 $$ = $1 | $3;
1031 | menuitem_flags menuitem_flag
1033 $$ = $1 | $2;
1037 menuitem_flag:
1038 CHECKED
1040 $$ = MENUITEM_CHECKED;
1042 | GRAYED
1044 $$ = MENUITEM_GRAYED;
1046 | HELP
1048 $$ = MENUITEM_HELP;
1050 | INACTIVE
1052 $$ = MENUITEM_INACTIVE;
1054 | MENUBARBREAK
1056 $$ = MENUITEM_MENUBARBREAK;
1058 | MENUBREAK
1060 $$ = MENUITEM_MENUBREAK;
1064 /* Menuex resources. */
1066 menuex:
1067 id MENUEX suboptions BEG menuexitems END
1069 define_menu ($1, &$3, $5);
1070 if (yychar != YYEMPTY)
1071 YYERROR;
1072 rcparse_discard_strings ();
1076 menuexitems:
1077 /* empty */
1079 $$ = NULL;
1081 | menuexitems menuexitem
1083 if ($1 == NULL)
1084 $$ = $2;
1085 else
1087 struct menuitem **pp;
1089 for (pp = &$1->next; *pp != NULL; pp = &(*pp)->next)
1091 *pp = $2;
1092 $$ = $1;
1097 menuexitem:
1098 MENUITEM QUOTEDSTRING
1100 $$ = define_menuitem ($2, 0, 0, 0, 0, NULL);
1102 | MENUITEM QUOTEDSTRING cnumexpr
1104 $$ = define_menuitem ($2, $3, 0, 0, 0, NULL);
1106 | MENUITEM QUOTEDSTRING cnumexpr cnumexpr optcnumexpr
1108 $$ = define_menuitem ($2, $3, $4, $5, 0, NULL);
1110 | MENUITEM SEPARATOR
1112 $$ = define_menuitem (NULL, 0, 0, 0, 0, NULL);
1114 | POPUP QUOTEDSTRING BEG menuexitems END
1116 $$ = define_menuitem ($2, 0, 0, 0, 0, $4);
1118 | POPUP QUOTEDSTRING cnumexpr BEG menuexitems END
1120 $$ = define_menuitem ($2, $3, 0, 0, 0, $5);
1122 | POPUP QUOTEDSTRING cnumexpr cnumexpr BEG menuexitems END
1124 $$ = define_menuitem ($2, $3, $4, 0, 0, $6);
1126 | POPUP QUOTEDSTRING cnumexpr cnumexpr cnumexpr optcnumexpr
1127 BEG menuexitems END
1129 $$ = define_menuitem ($2, $3, $4, $5, $6, $8);
1133 /* Messagetable resources. */
1135 messagetable:
1136 id MESSAGETABLE memflags_move file_name
1138 define_messagetable ($1, &$3, $4);
1139 if (yychar != YYEMPTY)
1140 YYERROR;
1141 rcparse_discard_strings ();
1145 /* Rcdata resources. */
1147 rcdata:
1148 id RCDATA suboptions BEG optrcdata_data END
1150 define_rcdata ($1, &$3, $5.first);
1151 if (yychar != YYEMPTY)
1152 YYERROR;
1153 rcparse_discard_strings ();
1157 /* We use a different lexing algorithm, because rcdata strings may
1158 contain embedded null bytes, and we need to know the length to use. */
1160 optrcdata_data:
1162 rcparse_rcdata ();
1164 optrcdata_data_int
1166 rcparse_normal ();
1167 $$ = $2;
1171 optrcdata_data_int:
1172 /* empty */
1174 $$.first = NULL;
1175 $$.last = NULL;
1177 | rcdata_data
1179 $$ = $1;
1183 rcdata_data:
1184 SIZEDSTRING
1186 struct rcdata_item *ri;
1188 ri = define_rcdata_string ($1.s, $1.length);
1189 $$.first = ri;
1190 $$.last = ri;
1192 | sizednumexpr
1194 struct rcdata_item *ri;
1196 ri = define_rcdata_number ($1.val, $1.dword);
1197 $$.first = ri;
1198 $$.last = ri;
1200 | rcdata_data ',' SIZEDSTRING
1202 struct rcdata_item *ri;
1204 ri = define_rcdata_string ($3.s, $3.length);
1205 $$.first = $1.first;
1206 $1.last->next = ri;
1207 $$.last = ri;
1209 | rcdata_data ',' sizednumexpr
1211 struct rcdata_item *ri;
1213 ri = define_rcdata_number ($3.val, $3.dword);
1214 $$.first = $1.first;
1215 $1.last->next = ri;
1216 $$.last = ri;
1220 /* Stringtable resources. */
1222 stringtable:
1223 STRINGTABLE suboptions BEG
1224 { sub_res_info = $2; }
1225 string_data END
1228 string_data:
1229 /* empty */
1230 | string_data numexpr QUOTEDSTRING
1232 define_stringtable (&sub_res_info, $2, $3);
1233 if (yychar != YYEMPTY)
1234 YYERROR;
1235 rcparse_discard_strings ();
1237 | string_data numexpr ',' QUOTEDSTRING
1239 define_stringtable (&sub_res_info, $2, $4);
1240 if (yychar != YYEMPTY)
1241 YYERROR;
1242 rcparse_discard_strings ();
1246 /* User defined resources. We accept general suboptions in the
1247 file_name case to keep the parser happy. */
1249 user:
1250 id id suboptions BEG optrcdata_data END
1252 define_user_data ($1, $2, &$3, $5.first);
1253 if (yychar != YYEMPTY)
1254 YYERROR;
1255 rcparse_discard_strings ();
1257 | id id suboptions file_name
1259 define_user_file ($1, $2, &$3, $4);
1260 if (yychar != YYEMPTY)
1261 YYERROR;
1262 rcparse_discard_strings ();
1266 /* Versioninfo resources. */
1268 versioninfo:
1269 id VERSIONINFO fixedverinfo BEG verblocks END
1271 define_versioninfo ($1, language, $3, $5);
1272 if (yychar != YYEMPTY)
1273 YYERROR;
1274 rcparse_discard_strings ();
1278 fixedverinfo:
1279 /* empty */
1281 $$ = ((struct fixed_versioninfo *)
1282 res_alloc (sizeof (struct fixed_versioninfo)));
1283 memset ($$, 0, sizeof (struct fixed_versioninfo));
1285 | fixedverinfo FILEVERSION numexpr cnumexpr cnumexpr cnumexpr
1287 $1->file_version_ms = ($3 << 16) | $4;
1288 $1->file_version_ls = ($5 << 16) | $6;
1289 $$ = $1;
1291 | fixedverinfo PRODUCTVERSION numexpr cnumexpr cnumexpr cnumexpr
1293 $1->product_version_ms = ($3 << 16) | $4;
1294 $1->product_version_ls = ($5 << 16) | $6;
1295 $$ = $1;
1297 | fixedverinfo FILEFLAGSMASK numexpr
1299 $1->file_flags_mask = $3;
1300 $$ = $1;
1302 | fixedverinfo FILEFLAGS numexpr
1304 $1->file_flags = $3;
1305 $$ = $1;
1307 | fixedverinfo FILEOS numexpr
1309 $1->file_os = $3;
1310 $$ = $1;
1312 | fixedverinfo FILETYPE numexpr
1314 $1->file_type = $3;
1315 $$ = $1;
1317 | fixedverinfo FILESUBTYPE numexpr
1319 $1->file_subtype = $3;
1320 $$ = $1;
1324 /* To handle verblocks successfully, the lexer handles BLOCK
1325 specially. A BLOCK "StringFileInfo" is returned as
1326 BLOCKSTRINGFILEINFO. A BLOCK "VarFileInfo" is returned as
1327 BLOCKVARFILEINFO. A BLOCK with some other string returns BLOCK
1328 with the string as the value. */
1330 verblocks:
1331 /* empty */
1333 $$ = NULL;
1335 | verblocks BLOCKSTRINGFILEINFO BEG BLOCK BEG vervals END END
1337 $$ = append_ver_stringfileinfo ($1, $4, $6);
1339 | verblocks BLOCKVARFILEINFO BEG VALUE QUOTEDSTRING vertrans END
1341 $$ = append_ver_varfileinfo ($1, $5, $6);
1345 vervals:
1346 /* empty */
1348 $$ = NULL;
1350 | vervals VALUE QUOTEDSTRING ',' QUOTEDSTRING
1352 $$ = append_verval ($1, $3, $5);
1356 vertrans:
1357 /* empty */
1359 $$ = NULL;
1361 | vertrans cnumexpr cnumexpr
1363 $$ = append_vertrans ($1, $2, $3);
1367 /* A resource ID. */
1370 posnumexpr
1372 $$.named = 0;
1373 $$.u.id = $1;
1375 | STRING
1377 char *copy, *s;
1379 /* It seems that resource ID's are forced to upper case. */
1380 copy = xstrdup ($1);
1381 for (s = copy; *s != '\0'; s++)
1382 *s = TOUPPER (*s);
1383 res_string_to_id (&$$, copy);
1384 free (copy);
1388 /* A resource reference. */
1390 resname:
1391 QUOTEDSTRING
1393 $$ = $1;
1395 | QUOTEDSTRING ','
1397 $$ = $1;
1399 | STRING ','
1401 $$ = $1;
1406 resref:
1407 posnumexpr ','
1409 $$.named = 0;
1410 $$.u.id = $1;
1412 | resname
1414 char *copy, *s;
1416 /* It seems that resource ID's are forced to upper case. */
1417 copy = xstrdup ($1);
1418 for (s = copy; *s != '\0'; s++)
1419 *s = TOUPPER (*s);
1420 res_string_to_id (&$$, copy);
1421 free (copy);
1425 /* Generic suboptions. These may appear before the BEGIN in any
1426 multiline statement. */
1428 suboptions:
1429 /* empty */
1431 memset (&$$, 0, sizeof (struct res_res_info));
1432 $$.language = language;
1433 /* FIXME: Is this the right default? */
1434 $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_PURE | MEMFLAG_DISCARDABLE;
1436 | suboptions memflag
1438 $$ = $1;
1439 $$.memflags |= $2.on;
1440 $$.memflags &=~ $2.off;
1442 | suboptions CHARACTERISTICS numexpr
1444 $$ = $1;
1445 $$.characteristics = $3;
1447 | suboptions LANGUAGE numexpr cnumexpr
1449 $$ = $1;
1450 $$.language = $3 | ($4 << SUBLANG_SHIFT);
1452 | suboptions VERSIONK numexpr
1454 $$ = $1;
1455 $$.version = $3;
1459 /* Memory flags which default to MOVEABLE and DISCARDABLE. */
1461 memflags_move_discard:
1462 /* empty */
1464 memset (&$$, 0, sizeof (struct res_res_info));
1465 $$.language = language;
1466 $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_DISCARDABLE;
1468 | memflags_move_discard memflag
1470 $$ = $1;
1471 $$.memflags |= $2.on;
1472 $$.memflags &=~ $2.off;
1476 /* Memory flags which default to MOVEABLE. */
1478 memflags_move:
1479 /* empty */
1481 memset (&$$, 0, sizeof (struct res_res_info));
1482 $$.language = language;
1483 $$.memflags = MEMFLAG_MOVEABLE | MEMFLAG_PURE | MEMFLAG_DISCARDABLE;
1485 | memflags_move memflag
1487 $$ = $1;
1488 $$.memflags |= $2.on;
1489 $$.memflags &=~ $2.off;
1493 /* Memory flags. This returns a struct with two integers, because we
1494 sometimes want to set bits and we sometimes want to clear them. */
1496 memflag:
1497 MOVEABLE
1499 $$.on = MEMFLAG_MOVEABLE;
1500 $$.off = 0;
1502 | FIXED
1504 $$.on = 0;
1505 $$.off = MEMFLAG_MOVEABLE;
1507 | PURE
1509 $$.on = MEMFLAG_PURE;
1510 $$.off = 0;
1512 | IMPURE
1514 $$.on = 0;
1515 $$.off = MEMFLAG_PURE;
1517 | PRELOAD
1519 $$.on = MEMFLAG_PRELOAD;
1520 $$.off = 0;
1522 | LOADONCALL
1524 $$.on = 0;
1525 $$.off = MEMFLAG_PRELOAD;
1527 | DISCARDABLE
1529 $$.on = MEMFLAG_DISCARDABLE;
1530 $$.off = 0;
1534 /* A file name. */
1536 file_name:
1537 QUOTEDSTRING
1539 $$ = $1;
1541 | STRING
1543 $$ = $1;
1547 /* A style expression. This changes the static variable STYLE. We do
1548 it this way because rc appears to permit a style to be set to
1549 something like
1550 WS_GROUP | NOT WS_TABSTOP
1551 to mean that a default of WS_TABSTOP should be removed. Anything
1552 which wants to accept a style must first set STYLE to the default
1553 value. The styleexpr nonterminal will change STYLE as specified by
1554 the user. Note that we do not accept arbitrary expressions here,
1555 just numbers separated by '|'. */
1557 styleexpr:
1558 parennumber
1560 style |= $1;
1562 | NOT parennumber
1564 style &=~ $2;
1566 | styleexpr '|' parennumber
1568 style |= $3;
1570 | styleexpr '|' NOT parennumber
1572 style &=~ $4;
1576 parennumber:
1577 NUMBER
1579 $$ = $1.val;
1581 | '(' numexpr ')'
1583 $$ = $2;
1587 /* An optional expression with a leading comma. */
1589 optcnumexpr:
1590 /* empty */
1592 $$ = 0;
1594 | cnumexpr
1596 $$ = $1;
1600 /* An expression with a leading comma. */
1602 cnumexpr:
1603 ',' numexpr
1605 $$ = $2;
1609 /* A possibly negated numeric expression. */
1611 numexpr:
1612 sizednumexpr
1614 $$ = $1.val;
1618 /* A possibly negated expression with a size. */
1620 sizednumexpr:
1621 NUMBER
1623 $$ = $1;
1625 | '(' sizednumexpr ')'
1627 $$ = $2;
1629 | '~' sizednumexpr %prec '~'
1631 $$.val = ~ $2.val;
1632 $$.dword = $2.dword;
1634 | '-' sizednumexpr %prec NEG
1636 $$.val = - $2.val;
1637 $$.dword = $2.dword;
1639 | sizednumexpr '*' sizednumexpr
1641 $$.val = $1.val * $3.val;
1642 $$.dword = $1.dword || $3.dword;
1644 | sizednumexpr '/' sizednumexpr
1646 $$.val = $1.val / $3.val;
1647 $$.dword = $1.dword || $3.dword;
1649 | sizednumexpr '%' sizednumexpr
1651 $$.val = $1.val % $3.val;
1652 $$.dword = $1.dword || $3.dword;
1654 | sizednumexpr '+' sizednumexpr
1656 $$.val = $1.val + $3.val;
1657 $$.dword = $1.dword || $3.dword;
1659 | sizednumexpr '-' sizednumexpr
1661 $$.val = $1.val - $3.val;
1662 $$.dword = $1.dword || $3.dword;
1664 | sizednumexpr '&' sizednumexpr
1666 $$.val = $1.val & $3.val;
1667 $$.dword = $1.dword || $3.dword;
1669 | sizednumexpr '^' sizednumexpr
1671 $$.val = $1.val ^ $3.val;
1672 $$.dword = $1.dword || $3.dword;
1674 | sizednumexpr '|' sizednumexpr
1676 $$.val = $1.val | $3.val;
1677 $$.dword = $1.dword || $3.dword;
1681 /* An expression with a leading comma which does not use unary
1682 negation. */
1684 cposnumexpr:
1685 ',' posnumexpr
1687 $$ = $2;
1691 /* An expression which does not use unary negation. */
1693 posnumexpr:
1694 sizedposnumexpr
1696 $$ = $1.val;
1700 /* An expression which does not use unary negation. We separate unary
1701 negation to avoid parsing conflicts when two numeric expressions
1702 appear consecutively. */
1704 sizedposnumexpr:
1705 NUMBER
1707 $$ = $1;
1709 | '(' sizednumexpr ')'
1711 $$ = $2;
1713 | '~' sizednumexpr %prec '~'
1715 $$.val = ~ $2.val;
1716 $$.dword = $2.dword;
1718 | sizedposnumexpr '*' sizednumexpr
1720 $$.val = $1.val * $3.val;
1721 $$.dword = $1.dword || $3.dword;
1723 | sizedposnumexpr '/' sizednumexpr
1725 $$.val = $1.val / $3.val;
1726 $$.dword = $1.dword || $3.dword;
1728 | sizedposnumexpr '%' sizednumexpr
1730 $$.val = $1.val % $3.val;
1731 $$.dword = $1.dword || $3.dword;
1733 | sizedposnumexpr '+' sizednumexpr
1735 $$.val = $1.val + $3.val;
1736 $$.dword = $1.dword || $3.dword;
1738 | sizedposnumexpr '-' sizednumexpr
1740 $$.val = $1.val - $3.val;
1741 $$.dword = $1.dword || $3.dword;
1743 | sizedposnumexpr '&' sizednumexpr
1745 $$.val = $1.val & $3.val;
1746 $$.dword = $1.dword || $3.dword;
1748 | sizedposnumexpr '^' sizednumexpr
1750 $$.val = $1.val ^ $3.val;
1751 $$.dword = $1.dword || $3.dword;
1753 | sizedposnumexpr '|' sizednumexpr
1755 $$.val = $1.val | $3.val;
1756 $$.dword = $1.dword || $3.dword;
1762 /* Set the language from the command line. */
1764 void
1765 rcparse_set_language (int lang)
1767 language = lang;