PageRenderTime 78ms CodeModel.GetById 40ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 1ms

/tools/wrc/parser.y

https://bitbucket.org/arty/arty-newcc-reactos
Happy | 2961 lines | 2744 code | 217 blank | 0 comment | 0 complexity | 1ad3d74dea63c63f35a0e2a7ce468089 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1%{
   2/*
   3 * Copyright 1994	Martin von Loewis
   4 * Copyright 1998-2000	Bertho A. Stultiens (BS)
   5 *           1999	Juergen Schmied (JS)
   6 *
   7 * This library is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU Lesser General Public
   9 * License as published by the Free Software Foundation; either
  10 * version 2.1 of the License, or (at your option) any later version.
  11 *
  12 * This library 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 GNU
  15 * Lesser General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU Lesser General Public
  18 * License along with this library; if not, write to the Free Software
  19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  20 *
  21 * History:
  22 * 24-Jul-2000 BS	- Made a fix for broken Berkeley yacc on
  23 *			  non-terminals (see cjunk rule).
  24 * 21-May-2000 BS	- Partial implementation of font resources.
  25 *			- Corrected language propagation for binary
  26 *			  resources such as bitmaps, icons, cursors,
  27 *			  userres and rcdata. The language is now
  28 *			  correct in .res files.
  29 *			- Fixed reading the resource name as ident,
  30 *			  so that it may overlap keywords.
  31 * 20-May-2000 BS	- Implemented animated cursors and icons
  32 *			  resource types.
  33 * 30-Apr-2000 BS	- Reintegration into the wine-tree
  34 * 14-Jan-2000 BS	- Redid the usertype resources so that they
  35 *			  are compatible.
  36 * 02-Jan-2000 BS	- Removed the preprocessor from the grammar
  37 *			  except for the # command (line numbers).
  38 *
  39 * 06-Nov-1999 JS	- see CHANGES
  40 *
  41 * 29-Dec-1998 AdH	- Grammar and function extensions.
  42 *			     grammar: TOOLBAR resources, Named ICONs in
  43 *				DIALOGS
  44 *			     functions: semantic actions for the grammar
  45 *				changes, resource files can now be anywhere
  46 *				on the include path instead of just in the
  47 *				current directory
  48 *
  49 * 20-Jun-1998 BS	- Fixed a bug in load_file() where the name was not
  50 *			  printed out correctly.
  51 *
  52 * 17-Jun-1998 BS	- Fixed a bug in CLASS statement parsing which should
  53 *			  also accept a tSTRING as argument.
  54 *
  55 * 25-May-1998 BS	- Found out that I need to support language, version
  56 *			  and characteristics in inline resources (bitmap,
  57 *			  cursor, etc) but they can also be specified with
  58 *			  a filename. This renders my filename-scanning scheme
  59 *			  worthless. Need to build newline parsing to solve
  60 *			  this one.
  61 *			  It will come with version 1.1.0 (sigh).
  62 *
  63 * 19-May-1998 BS	- Started to build a builtin preprocessor
  64 *
  65 * 30-Apr-1998 BS	- Redid the stringtable parsing/handling. My previous
  66 *			  ideas had some serious flaws.
  67 *
  68 * 27-Apr-1998 BS	- Removed a lot of dead comments and put it in a doc
  69 *			  file.
  70 *
  71 * 21-Apr-1998 BS	- Added correct behavior for cursors and icons.
  72 *			- This file is growing too big. It is time to strip
  73 *			  things and put it in a support file.
  74 *
  75 * 19-Apr-1998 BS	- Tagged the stringtable resource so that only one
  76 *			  resource will be created. This because the table
  77 *			  has a different layout than other resources. The
  78 *			  table has to be sorted, and divided into smaller
  79 *			  resource entries (see comment in source).
  80 *
  81 * 17-Apr-1998 BS	- Almost all strings, including identifiers, are parsed
  82 *			  as string_t which include unicode strings upon
  83 *			  input.
  84 *			- Parser now emits a warning when compiling win32
  85 *			  extensions in win16 mode.
  86 *
  87 * 16-Apr-1998 BS	- Raw data elements are now *optionally* separated
  88 *			  by commas. Read the comments in file sq2dq.l.
  89 *			- FIXME: there are instances in the source that rely
  90 *			  on the fact that int==32bit and pointers are int size.
  91 *			- Fixed the conflict in menuex by changing a rule
  92 *			  back into right recursion. See note in source.
  93 *			- UserType resources cannot have an expression as its
  94 *			  typeclass. See note in source.
  95 *
  96 * 15-Apr-1998 BS	- Changed all right recursion into left recursion to
  97 *			  get reduction of the parsestack.
  98 *			  This also helps communication between bison and flex.
  99 *			  Main advantage is that the Empty rule gets reduced
 100 *			  first, which is used to allocate/link things.
 101 *			  It also added a shift/reduce conflict in the menuex
 102 *			  handling, due to expression/option possibility,
 103 *			  although not serious.
 104 *
 105 * 14-Apr-1998 BS	- Redone almost the entire parser. We're not talking
 106 *			  about making it more efficient, but readable (for me)
 107 *			  and slightly easier to expand/change.
 108 *			  This is done primarily by using more reduce states
 109 *			  with many (intuitive) types for the various resource
 110 *			  statements.
 111 *			- Added expression handling for all resources where a
 112 *			  number is accepted (not only for win32). Also added
 113 *			  multiply and division (not MS compatible, but handy).
 114 *			  Unary minus introduced a shift/reduce conflict, but
 115 *			  it is not serious.
 116 *
 117 * 13-Apr-1998 BS	- Reordered a lot of things
 118 *			- Made the source more readable
 119 *			- Added Win32 resource definitions
 120 *			- Corrected syntax problems with an old yacc (;)
 121 *			- Added extra comment about grammar
 122 */
 123#include "config.h"
 124#include "wine/port.h"
 125
 126#include <stdio.h>
 127#include <stdlib.h>
 128#include <stdarg.h>
 129#include <assert.h>
 130#include <ctype.h>
 131#include <string.h>
 132
 133#include "wrc.h"
 134#include "utils.h"
 135#include "newstruc.h"
 136#include "dumpres.h"
 137#include "wine/wpp.h"
 138#include "wine/unicode.h"
 139#include "parser.h"
 140#include "windef.h"
 141#include "winbase.h"
 142#include "wingdi.h"
 143#include "winuser.h"
 144
 145#if defined(YYBYACC)
 146	/* Berkeley yacc (byacc) doesn't seem to know about these */
 147	/* Some *BSD supplied versions do define these though */
 148# ifndef YYEMPTY
 149#  define YYEMPTY	(-1)	/* Empty lookahead value of yychar */
 150# endif
 151# ifndef YYLEX
 152#  define YYLEX		yylex()
 153# endif
 154
 155#elif defined(YYBISON)
 156	/* Bison was used for original development */
 157	/* #define YYEMPTY -2 */
 158	/* #define YYLEX   yylex() */
 159
 160#else
 161	/* No yacc we know yet */
 162# if !defined(YYEMPTY) || !defined(YYLEX)
 163#  error Yacc version/type unknown. This version needs to be verified for settings of YYEMPTY and YYLEX.
 164# elif defined(__GNUC__)	/* gcc defines the #warning directive */
 165#  warning Yacc version/type unknown. It defines YYEMPTY and YYLEX, but is not tested
 166  /* #else we just take a chance that it works... */
 167# endif
 168#endif
 169
 170int want_nl = 0;	/* Signal flex that we need the next newline */
 171int want_id = 0;	/* Signal flex that we need the next identifier */
 172static stringtable_t *tagstt;	/* Stringtable tag.
 173			 * It is set while parsing a stringtable to one of
 174			 * the stringtables in the sttres list or a new one
 175			 * if the language was not parsed before.
 176			 */
 177static stringtable_t *sttres;	/* Stringtable resources. This holds the list of
 178			 * stringtables with different lanuages
 179			 */
 180static int dont_want_id = 0;	/* See language parsing for details */
 181
 182/* Set to the current options of the currently scanning stringtable */
 183static int *tagstt_memopt;
 184static characts_t *tagstt_characts;
 185static version_t *tagstt_version;
 186
 187static const char riff[4] = "RIFF";	/* RIFF file magic for animated cursor/icon */
 188
 189/* Prototypes of here defined functions */
 190static event_t *get_event_head(event_t *p);
 191static control_t *get_control_head(control_t *p);
 192static ver_value_t *get_ver_value_head(ver_value_t *p);
 193static ver_block_t *get_ver_block_head(ver_block_t *p);
 194static resource_t *get_resource_head(resource_t *p);
 195static menu_item_t *get_item_head(menu_item_t *p);
 196static raw_data_t *merge_raw_data_str(raw_data_t *r1, string_t *str);
 197static raw_data_t *merge_raw_data_int(raw_data_t *r1, int i);
 198static raw_data_t *merge_raw_data_long(raw_data_t *r1, int i);
 199static raw_data_t *merge_raw_data(raw_data_t *r1, raw_data_t *r2);
 200static raw_data_t *str2raw_data(string_t *str);
 201static raw_data_t *int2raw_data(int i);
 202static raw_data_t *long2raw_data(int i);
 203static raw_data_t *load_file(string_t *name, language_t *lang);
 204static itemex_opt_t *new_itemex_opt(int id, int type, int state, int helpid);
 205static event_t *add_string_event(string_t *key, int id, int flags, event_t *prev);
 206static event_t *add_event(int key, int id, int flags, event_t *prev);
 207static name_id_t *convert_ctlclass(name_id_t *cls);
 208static control_t *ins_ctrl(int type, int special_style, control_t *ctrl, control_t *prev);
 209static dialog_t *dialog_version(version_t *v, dialog_t *dlg);
 210static dialog_t *dialog_characteristics(characts_t *c, dialog_t *dlg);
 211static dialog_t *dialog_language(language_t *l, dialog_t *dlg);
 212static dialog_t *dialog_menu(name_id_t *m, dialog_t *dlg);
 213static dialog_t *dialog_class(name_id_t *n, dialog_t *dlg);
 214static dialog_t *dialog_font(font_id_t *f, dialog_t *dlg);
 215static dialog_t *dialog_caption(string_t *s, dialog_t *dlg);
 216static dialog_t *dialog_exstyle(style_t * st, dialog_t *dlg);
 217static dialog_t *dialog_style(style_t * st, dialog_t *dlg);
 218static resource_t *build_stt_resources(stringtable_t *stthead);
 219static stringtable_t *find_stringtable(lvc_t *lvc);
 220static toolbar_item_t *ins_tlbr_button(toolbar_item_t *prev, toolbar_item_t *idrec);
 221static toolbar_item_t *get_tlbr_buttons_head(toolbar_item_t *p, int *nitems);
 222static string_t *make_filename(string_t *s);
 223static resource_t *build_fontdirs(resource_t *tail);
 224static resource_t *build_fontdir(resource_t **fnt, int nfnt);
 225static int rsrcid_to_token(int lookahead);
 226
 227%}
 228%union{
 229	string_t	*str;
 230	int		num;
 231	int		*iptr;
 232	char		*cptr;
 233	resource_t	*res;
 234	accelerator_t	*acc;
 235	bitmap_t	*bmp;
 236	dialog_t	*dlg;
 237	font_t		*fnt;
 238	fontdir_t	*fnd;
 239	menu_t		*men;
 240	html_t		*html;
 241	rcdata_t	*rdt;
 242	stringtable_t	*stt;
 243	stt_entry_t	*stte;
 244	user_t		*usr;
 245	messagetable_t	*msg;
 246	versioninfo_t	*veri;
 247	control_t	*ctl;
 248	name_id_t	*nid;
 249	font_id_t	*fntid;
 250	language_t	*lan;
 251	version_t	*ver;
 252	characts_t	*chars;
 253	event_t		*event;
 254	menu_item_t	*menitm;
 255	itemex_opt_t	*exopt;
 256	raw_data_t	*raw;
 257	lvc_t		*lvc;
 258	ver_value_t	*val;
 259	ver_block_t	*blk;
 260	ver_words_t	*verw;
 261	toolbar_t	*tlbar;
 262	toolbar_item_t	*tlbarItems;
 263	dlginit_t       *dginit;
 264	style_pair_t	*styles;
 265	style_t		*style;
 266	ani_any_t	*ani;
 267}
 268
 269%token tNL
 270%token <num> tNUMBER tLNUMBER
 271%token <str> tSTRING tIDENT tFILENAME
 272%token <raw> tRAWDATA
 273%token tACCELERATORS tBITMAP tCURSOR tDIALOG tDIALOGEX tMENU tMENUEX tMESSAGETABLE
 274%token tRCDATA tVERSIONINFO tSTRINGTABLE tFONT tFONTDIR tICON tHTML
 275%token tAUTO3STATE tAUTOCHECKBOX tAUTORADIOBUTTON tCHECKBOX tDEFPUSHBUTTON
 276%token tPUSHBUTTON tRADIOBUTTON tSTATE3 /* PUSHBOX */
 277%token tGROUPBOX tCOMBOBOX tLISTBOX tSCROLLBAR
 278%token tCONTROL tEDITTEXT
 279%token tRTEXT tCTEXT tLTEXT
 280%token tBLOCK tVALUE
 281%token tSHIFT tALT tASCII tVIRTKEY tGRAYED tCHECKED tINACTIVE tNOINVERT
 282%token tPURE tIMPURE tDISCARDABLE tLOADONCALL tPRELOAD tFIXED tMOVEABLE
 283%token tCLASS tCAPTION tCHARACTERISTICS tEXSTYLE tSTYLE tVERSION tLANGUAGE
 284%token tFILEVERSION tPRODUCTVERSION tFILEFLAGSMASK tFILEOS tFILETYPE tFILEFLAGS tFILESUBTYPE
 285%token tMENUBARBREAK tMENUBREAK tMENUITEM tPOPUP tSEPARATOR
 286%token tHELP
 287%token tTOOLBAR tBUTTON
 288%token tBEGIN tEND
 289%token tDLGINIT
 290%left '|'
 291%left '^'
 292%left '&'
 293%left '+' '-'
 294%left '*' '/'
 295%right '~' tNOT
 296%left pUPM
 297
 298%type <res> 	resource_file resource resources resource_definition
 299%type <stt>	stringtable strings
 300%type <fnt>	font
 301%type <fnd>	fontdir
 302%type <acc> 	accelerators
 303%type <event> 	events
 304%type <bmp> 	bitmap
 305%type <ani> 	cursor icon
 306%type <dlg> 	dialog dlg_attributes dialogex dlgex_attribs
 307%type <ctl> 	ctrls gen_ctrl lab_ctrl ctrl_desc iconinfo
 308%type <iptr>	helpid
 309%type <ctl>	exctrls gen_exctrl lab_exctrl exctrl_desc
 310%type <html>	html
 311%type <rdt> 	rcdata
 312%type <raw>	raw_data raw_elements opt_data file_raw
 313%type <veri> 	versioninfo fix_version
 314%type <verw>	ver_words
 315%type <blk>	ver_blocks ver_block
 316%type <val>	ver_values ver_value
 317%type <men> 	menu menuex
 318%type <menitm>	item_definitions menu_body itemex_definitions menuex_body
 319%type <exopt>	itemex_p_options itemex_options
 320%type <msg> 	messagetable
 321%type <usr> 	userres
 322%type <num> 	item_options
 323%type <nid> 	nameid nameid_s ctlclass usertype
 324%type <num> 	acc_opt acc accs
 325%type <iptr>	loadmemopts lamo lama
 326%type <fntid>	opt_font opt_exfont opt_expr
 327%type <lvc>	opt_lvc
 328%type <lan>	opt_language
 329%type <chars>	opt_characts
 330%type <ver>	opt_version
 331%type <num>	expr xpr
 332%type <iptr>	e_expr
 333%type <tlbar>	toolbar
 334%type <tlbarItems>	toolbar_items
 335%type <dginit>  dlginit
 336%type <styles>  optional_style_pair
 337%type <num>	any_num
 338%type <style>   style
 339%type <str>	filename
 340
 341%%
 342
 343resource_file
 344	: resources {
 345		resource_t *rsc, *head;
 346		/* First add stringtables to the resource-list */
 347		rsc = build_stt_resources(sttres);
 348		/* 'build_stt_resources' returns a head and $1 is a tail */
 349		if($1)
 350		{
 351			$1->next = rsc;
 352			if(rsc)
 353				rsc->prev = $1;
 354		}
 355		else
 356			$1 = rsc;
 357		/* Find the tail again */
 358		while($1 && $1->next)
 359			$1 = $1->next;
 360		/* Now add any fontdirecory */
 361		rsc = build_fontdirs($1);
 362		/* 'build_fontdir' returns a head and $1 is a tail */
 363		if($1)
 364		{
 365			$1->next = rsc;
 366			if(rsc)
 367				rsc->prev = $1;
 368		}
 369		else
 370			$1 = rsc;
 371
 372		/* Final statements before we're done */
 373                if ((head = get_resource_head($1)) != NULL)
 374                {
 375                    if (resource_top)  /* append to existing resources */
 376                    {
 377                        resource_t *tail = resource_top;
 378                        while (tail->next) tail = tail->next;
 379                        tail->next = head;
 380                        head->prev = tail;
 381                    }
 382                    else resource_top = head;
 383                }
 384                sttres = NULL;
 385		}
 386	;
 387
 388/* Resources are put into a linked list */
 389resources
 390	: /* Empty */		{ $$ = NULL; want_id = 1; }
 391	| resources resource	{
 392		if($2)
 393		{
 394			resource_t *tail = $2;
 395			resource_t *head = $2;
 396			while(tail->next)
 397				tail = tail->next;
 398			while(head->prev)
 399				head = head->prev;
 400			head->prev = $1;
 401			if($1)
 402				$1->next = head;
 403			$$ = tail;
 404			/* Check for duplicate identifiers */
 405			while($1 && head)
 406			{
 407				resource_t *rsc = $1;
 408				while(rsc)
 409				{
 410					if(rsc->type == head->type
 411					&& rsc->lan->id == head->lan->id
 412					&& rsc->lan->sub == head->lan->sub
 413					&& !compare_name_id(rsc->name, head->name)
 414					&& (rsc->type != res_usr || !compare_name_id(rsc->res.usr->type,head->res.usr->type)))
 415					{
 416						yyerror("Duplicate resource name '%s'", get_nameid_str(rsc->name));
 417					}
 418					rsc = rsc->prev;
 419				}
 420				head = head->next;
 421			}
 422		}
 423		else if($1)
 424		{
 425			resource_t *tail = $1;
 426			while(tail->next)
 427				tail = tail->next;
 428			$$ = tail;
 429		}
 430		else
 431			$$ = NULL;
 432
 433		if(!dont_want_id)	/* See comments in language parsing below */
 434			want_id = 1;
 435		dont_want_id = 0;
 436		}
 437	/*
 438	 * The following newline rule will never get reduced because we never
 439	 * get the tNL token, unless we explicitly set the 'want_nl'
 440	 * flag, which we don't.
 441	 * The *ONLY* reason for this to be here is because Berkeley
 442	 * yacc (byacc), at least version 1.9, has a bug.
 443	 * (identified in the generated parser on the second
 444	 *  line with:
 445	 *  static char yysccsid[] = "@(#)yaccpar   1.9 (Berkeley) 02/21/93";
 446	 * )
 447	 * This extra rule fixes it.
 448	 * The problem is that the expression handling rule "expr: xpr"
 449	 * is not reduced on non-terminal tokens, defined above in the
 450	 * %token declarations. Token tNL is the only non-terminal that
 451	 * can occur. The error becomes visible in the language parsing
 452	 * rule below, which looks at the look-ahead token and tests it
 453	 * for tNL. However, byacc already generates an error upon reading
 454	 * the token instead of keeping it as a lookahead. The reason
 455	 * lies in the lack of a $default transition in the "expr : xpr . "
 456	 * state (currently state 25). It is probably omitted because tNL
 457	 * is a non-terminal and the state contains 2 s/r conflicts. The
 458	 * state enumerates all possible transitions instead of using a
 459	 * $default transition.
 460	 * All in all, it is a bug in byacc. (period)
 461	 */
 462	| resources tNL
 463	;
 464
 465
 466/* Parse top level resource definitions etc. */
 467resource
 468	: expr usrcvt resource_definition {
 469		$$ = $3;
 470		if($$)
 471		{
 472			if($1 > 65535 || $1 < -32768)
 473				yyerror("Resource's ID out of range (%d)", $1);
 474			$$->name = new_name_id();
 475			$$->name->type = name_ord;
 476			$$->name->name.i_name = $1;
 477			chat("Got %s (%d)\n", get_typename($3), $$->name->name.i_name);
 478			}
 479			}
 480	| tIDENT usrcvt resource_definition {
 481		$$ = $3;
 482		if($$)
 483		{
 484			$$->name = new_name_id();
 485			$$->name->type = name_str;
 486			$$->name->name.s_name = $1;
 487			chat("Got %s (%s)\n", get_typename($3), $$->name->name.s_name->str.cstr);
 488		}
 489		}
 490	| stringtable {
 491		/* Don't do anything, stringtables are converted to
 492		 * resource_t structures when we are finished parsing and
 493		 * the final rule of the parser is reduced (see above)
 494		 */
 495		$$ = NULL;
 496		chat("Got STRINGTABLE\n");
 497		}
 498	| tLANGUAGE {want_nl = 1; } expr ',' expr {
 499		/* We *NEED* the newline to delimit the expression.
 500		 * Otherwise, we would not be able to set the next
 501		 * want_id anymore because of the token-lookahead.
 502		 *
 503		 * However, we can test the lookahead-token for
 504		 * being "non-expression" type, in which case we
 505		 * continue. Fortunately, tNL is the only token that
 506		 * will break expression parsing and is implicitly
 507		 * void, so we just remove it. This scheme makes it
 508		 * possible to do some (not all) fancy preprocessor
 509		 * stuff.
 510		 * BTW, we also need to make sure that the next
 511		 * reduction of 'resources' above will *not* set
 512		 * want_id because we already have a lookahead that
 513		 * cannot be undone.
 514		 */
 515		if(yychar != YYEMPTY && yychar != tNL)
 516			dont_want_id = 1;
 517
 518		if(yychar == tNL)
 519			yychar = YYEMPTY;	/* Could use 'yyclearin', but we already need the*/
 520						/* direct access to yychar in rule 'usrcvt' below. */
 521		else if(yychar == tIDENT)
 522			parser_warning("LANGUAGE statement not delimited with newline; next identifier might be wrong\n");
 523
 524		want_nl = 0;	/* We don't want it anymore if we didn't get it */
 525
 526		if(!win32)
 527			parser_warning("LANGUAGE not supported in 16-bit mode\n");
 528		free(currentlanguage);
 529		if (get_language_codepage($3, $5) == -1)
 530			yyerror( "Language %04x is not supported", ($5<<10) + $3);
 531		currentlanguage = new_language($3, $5);
 532		$$ = NULL;
 533		chat("Got LANGUAGE %d,%d (0x%04x)\n", $3, $5, ($5<<10) + $3);
 534		}
 535	;
 536
 537/*
 538 * Remapping of numerical resource types
 539 * (see also comment of called function below)
 540 */
 541usrcvt	: /* Empty */	{ yychar = rsrcid_to_token(yychar); }
 542	;
 543
 544/*
 545 * Get a valid name/id
 546 */
 547nameid	: expr	{
 548		if($1 > 65535 || $1 < -32768)
 549			yyerror("Resource's ID out of range (%d)", $1);
 550		$$ = new_name_id();
 551		$$->type = name_ord;
 552		$$->name.i_name = $1;
 553		}
 554	| tIDENT {
 555		$$ = new_name_id();
 556		$$->type = name_str;
 557		$$->name.s_name = $1;
 558		}
 559	;
 560
 561/*
 562 * Extra string recognition for CLASS statement in dialogs
 563 */
 564nameid_s: nameid	{ $$ = $1; }
 565	| tSTRING	{
 566		$$ = new_name_id();
 567		$$->type = name_str;
 568		$$->name.s_name = $1;
 569		}
 570	;
 571
 572/* get the value for a single resource*/
 573resource_definition
 574	: accelerators	{ $$ = new_resource(res_acc, $1, $1->memopt, $1->lvc.language); }
 575	| bitmap	{ $$ = new_resource(res_bmp, $1, $1->memopt, $1->data->lvc.language); }
 576	| cursor {
 577		resource_t *rsc;
 578		if($1->type == res_anicur)
 579		{
 580			$$ = rsc = new_resource(res_anicur, $1->u.ani, $1->u.ani->memopt, $1->u.ani->data->lvc.language);
 581		}
 582		else if($1->type == res_curg)
 583		{
 584			cursor_t *cur;
 585			$$ = rsc = new_resource(res_curg, $1->u.curg, $1->u.curg->memopt, $1->u.curg->lvc.language);
 586			for(cur = $1->u.curg->cursorlist; cur; cur = cur->next)
 587			{
 588				rsc->prev = new_resource(res_cur, cur, $1->u.curg->memopt, $1->u.curg->lvc.language);
 589				rsc->prev->next = rsc;
 590				rsc = rsc->prev;
 591				rsc->name = new_name_id();
 592				rsc->name->type = name_ord;
 593				rsc->name->name.i_name = cur->id;
 594			}
 595		}
 596		else
 597			internal_error(__FILE__, __LINE__, "Invalid top-level type %d in cursor resource\n", $1->type);
 598		free($1);
 599		}
 600	| dialog	{ $$ = new_resource(res_dlg, $1, $1->memopt, $1->lvc.language); }
 601	| dialogex {
 602		if(win32)
 603			$$ = new_resource(res_dlg, $1, $1->memopt, $1->lvc.language);
 604		else
 605			$$ = NULL;
 606		}
 607	| dlginit	{ $$ = new_resource(res_dlginit, $1, $1->memopt, $1->data->lvc.language); }
 608	| font		{ $$ = new_resource(res_fnt, $1, $1->memopt, $1->data->lvc.language); }
 609	| fontdir	{ $$ = new_resource(res_fntdir, $1, $1->memopt, $1->data->lvc.language); }
 610	| icon {
 611		resource_t *rsc;
 612		if($1->type == res_aniico)
 613		{
 614			$$ = rsc = new_resource(res_aniico, $1->u.ani, $1->u.ani->memopt, $1->u.ani->data->lvc.language);
 615		}
 616		else if($1->type == res_icog)
 617		{
 618			icon_t *ico;
 619			$$ = rsc = new_resource(res_icog, $1->u.icog, $1->u.icog->memopt, $1->u.icog->lvc.language);
 620			for(ico = $1->u.icog->iconlist; ico; ico = ico->next)
 621			{
 622				rsc->prev = new_resource(res_ico, ico, $1->u.icog->memopt, $1->u.icog->lvc.language);
 623				rsc->prev->next = rsc;
 624				rsc = rsc->prev;
 625				rsc->name = new_name_id();
 626				rsc->name->type = name_ord;
 627				rsc->name->name.i_name = ico->id;
 628			}
 629		}
 630		else
 631			internal_error(__FILE__, __LINE__, "Invalid top-level type %d in icon resource\n", $1->type);
 632		free($1);
 633		}
 634	| menu		{ $$ = new_resource(res_men, $1, $1->memopt, $1->lvc.language); }
 635	| menuex {
 636		if(win32)
 637			$$ = new_resource(res_men, $1, $1->memopt, $1->lvc.language);
 638		else
 639			$$ = NULL;
 640		}
 641	| messagetable	{ $$ = new_resource(res_msg, $1, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, $1->data->lvc.language); }
 642	| html		{ $$ = new_resource(res_html, $1, $1->memopt, $1->data->lvc.language); }
 643	| rcdata	{ $$ = new_resource(res_rdt, $1, $1->memopt, $1->data->lvc.language); }
 644	| toolbar	{ $$ = new_resource(res_toolbar, $1, $1->memopt, $1->lvc.language); }
 645	| userres	{ $$ = new_resource(res_usr, $1, $1->memopt, $1->data->lvc.language); }
 646	| versioninfo	{ $$ = new_resource(res_ver, $1, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, $1->lvc.language); }
 647	;
 648
 649
 650filename: tFILENAME	{ $$ = make_filename($1); }
 651	| tIDENT	{ $$ = make_filename($1); }
 652	| tSTRING	{ $$ = make_filename($1); }
 653	;
 654
 655/* ------------------------------ Bitmap ------------------------------ */
 656bitmap	: tBITMAP loadmemopts file_raw	{ $$ = new_bitmap($3, $2); }
 657	;
 658
 659/* ------------------------------ Cursor ------------------------------ */
 660cursor	: tCURSOR loadmemopts file_raw	{
 661		$$ = new_ani_any();
 662		if($3->size > 4 && !memcmp($3->data, riff, sizeof(riff)))
 663		{
 664			$$->type = res_anicur;
 665			$$->u.ani = new_ani_curico(res_anicur, $3, $2);
 666		}
 667		else
 668		{
 669			$$->type = res_curg;
 670			$$->u.curg = new_cursor_group($3, $2);
 671		}
 672	}
 673	;
 674
 675/* ------------------------------ Icon ------------------------------ */
 676icon	: tICON loadmemopts file_raw	{
 677		$$ = new_ani_any();
 678		if($3->size > 4 && !memcmp($3->data, riff, sizeof(riff)))
 679		{
 680			$$->type = res_aniico;
 681			$$->u.ani = new_ani_curico(res_aniico, $3, $2);
 682		}
 683		else
 684		{
 685			$$->type = res_icog;
 686			$$->u.icog = new_icon_group($3, $2);
 687		}
 688	}
 689	;
 690
 691/* ------------------------------ Font ------------------------------ */
 692	/*
 693	 * The reading of raw_data for fonts is a Borland BRC
 694	 * extension. MS generates an error. However, it is
 695	 * most logical to support this, considering how wine
 696	 * enters things in CVS (ascii).
 697	 */
 698font	: tFONT loadmemopts file_raw	{ $$ = new_font($3, $2); }
 699	;
 700
 701	/*
 702	 * The fontdir is a Borland BRC extension which only
 703	 * reads the data as 'raw_data' from the file.
 704	 * I don't know whether it is interpreted.
 705	 * The fontdir is generated if it was not present and
 706	 * fonts are defined in the source.
 707	 */
 708fontdir	: tFONTDIR loadmemopts file_raw	{ $$ = new_fontdir($3, $2); }
 709	;
 710
 711/* ------------------------------ MessageTable ------------------------------ */
 712/* It might be interesting to implement the MS Message compiler here as well
 713 * to get everything in one source. Might be a future project.
 714 */
 715messagetable
 716	: tMESSAGETABLE loadmemopts file_raw	{
 717		if(!win32)
 718			parser_warning("MESSAGETABLE not supported in 16-bit mode\n");
 719		$$ = new_messagetable($3, $2);
 720		}
 721	;
 722
 723/* ------------------------------ HTML ------------------------------ */
 724html	: tHTML loadmemopts file_raw	{ $$ = new_html($3, $2); }
 725	;
 726
 727/* ------------------------------ RCData ------------------------------ */
 728rcdata	: tRCDATA loadmemopts file_raw	{ $$ = new_rcdata($3, $2); }
 729	;
 730
 731/* ------------------------------ DLGINIT ------------------------------ */
 732dlginit	: tDLGINIT loadmemopts file_raw	{ $$ = new_dlginit($3, $2); }
 733	;
 734
 735/* ------------------------------ UserType ------------------------------ */
 736userres	: usertype loadmemopts file_raw		{
 737#ifdef WORDS_BIGENDIAN
 738			if(pedantic && byteorder != WRC_BO_LITTLE)
 739#else
 740			if(pedantic && byteorder == WRC_BO_BIG)
 741#endif
 742				parser_warning("Byteordering is not little-endian and type cannot be interpreted\n");
 743			$$ = new_user($1, $3, $2);
 744		}
 745	;
 746
 747usertype: tNUMBER {
 748		$$ = new_name_id();
 749		$$->type = name_ord;
 750		$$->name.i_name = $1;
 751		}
 752	| tIDENT {
 753		$$ = new_name_id();
 754		$$->type = name_str;
 755		$$->name.s_name = $1;
 756		}
 757	;
 758
 759/* ------------------------------ Accelerator ------------------------------ */
 760accelerators
 761	: tACCELERATORS loadmemopts opt_lvc tBEGIN events tEND {
 762		$$ = new_accelerator();
 763		if($2)
 764		{
 765			$$->memopt = *($2);
 766			free($2);
 767		}
 768		else
 769		{
 770			$$->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE;
 771		}
 772		if(!$5)
 773			yyerror("Accelerator table must have at least one entry");
 774		$$->events = get_event_head($5);
 775		if($3)
 776		{
 777			$$->lvc = *($3);
 778			free($3);
 779		}
 780		if(!$$->lvc.language)
 781			$$->lvc.language = dup_language(currentlanguage);
 782		}
 783	;
 784
 785events	: /* Empty */ 				{ $$=NULL; }
 786	| events tSTRING ',' expr acc_opt	{ $$=add_string_event($2, $4, $5, $1); }
 787	| events expr ',' expr acc_opt		{ $$=add_event($2, $4, $5, $1); }
 788	;
 789
 790/*
 791 * The empty rule generates a s/r conflict because of {bi,u}nary expr
 792 * on - and +. It cannot be solved in any way because it is the same as
 793 * the if/then/else problem (LALR(1) problem). The conflict is moved
 794 * away by forcing it to be in the expression handling below.
 795 */
 796acc_opt	: /* Empty */	{ $$ = 0; }
 797	| ',' accs	{ $$ = $2; }
 798	;
 799
 800accs	: acc		{ $$ = $1; }
 801	| accs ',' acc	{ $$ = $1 | $3; }
 802	;
 803
 804acc	: tNOINVERT 	{ $$ = WRC_AF_NOINVERT; }
 805	| tSHIFT	{ $$ = WRC_AF_SHIFT; }
 806	| tCONTROL	{ $$ = WRC_AF_CONTROL; }
 807	| tALT		{ $$ = WRC_AF_ALT; }
 808	| tASCII	{ $$ = WRC_AF_ASCII; }
 809	| tVIRTKEY	{ $$ = WRC_AF_VIRTKEY; }
 810	;
 811
 812/* ------------------------------ Dialog ------------------------------ */
 813/* FIXME: Support EXSTYLE in the dialog line itself */
 814dialog	: tDIALOG loadmemopts expr ',' expr ',' expr ',' expr dlg_attributes
 815	  tBEGIN  ctrls tEND {
 816		if($2)
 817		{
 818			$10->memopt = *($2);
 819			free($2);
 820		}
 821		else
 822			$10->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
 823		$10->x = $3;
 824		$10->y = $5;
 825		$10->width = $7;
 826		$10->height = $9;
 827		$10->controls = get_control_head($12);
 828		$$ = $10;
 829		if(!$$->gotstyle)
 830		{
 831			$$->style = new_style(0,0);
 832			$$->style->or_mask = WS_POPUP;
 833			$$->gotstyle = TRUE;
 834		}
 835		if($$->title)
 836			$$->style->or_mask |= WS_CAPTION;
 837		if($$->font)
 838			$$->style->or_mask |= DS_SETFONT;
 839
 840		$$->style->or_mask &= ~($$->style->and_mask);
 841		$$->style->and_mask = 0;
 842
 843		if(!$$->lvc.language)
 844			$$->lvc.language = dup_language(currentlanguage);
 845		}
 846	;
 847
 848dlg_attributes
 849	: /* Empty */				{ $$=new_dialog(); }
 850	| dlg_attributes tSTYLE style		{ $$=dialog_style($3,$1); }
 851	| dlg_attributes tEXSTYLE style		{ $$=dialog_exstyle($3,$1); }
 852	| dlg_attributes tCAPTION tSTRING	{ $$=dialog_caption($3,$1); }
 853	| dlg_attributes opt_font		{ $$=dialog_font($2,$1); }
 854	| dlg_attributes tCLASS nameid_s	{ $$=dialog_class($3,$1); }
 855	| dlg_attributes tMENU nameid		{ $$=dialog_menu($3,$1); }
 856	| dlg_attributes opt_language		{ $$=dialog_language($2,$1); }
 857	| dlg_attributes opt_characts		{ $$=dialog_characteristics($2,$1); }
 858	| dlg_attributes opt_version		{ $$=dialog_version($2,$1); }
 859	;
 860
 861ctrls	: /* Empty */				{ $$ = NULL; }
 862	| ctrls tCONTROL	gen_ctrl	{ $$=ins_ctrl(-1, 0, $3, $1); }
 863	| ctrls tEDITTEXT	ctrl_desc	{ $$=ins_ctrl(CT_EDIT, 0, $3, $1); }
 864	| ctrls tLISTBOX	ctrl_desc	{ $$=ins_ctrl(CT_LISTBOX, 0, $3, $1); }
 865	| ctrls tCOMBOBOX	ctrl_desc	{ $$=ins_ctrl(CT_COMBOBOX, 0, $3, $1); }
 866	| ctrls tSCROLLBAR	ctrl_desc	{ $$=ins_ctrl(CT_SCROLLBAR, 0, $3, $1); }
 867	| ctrls tCHECKBOX	lab_ctrl	{ $$=ins_ctrl(CT_BUTTON, BS_CHECKBOX, $3, $1); }
 868	| ctrls tDEFPUSHBUTTON	lab_ctrl	{ $$=ins_ctrl(CT_BUTTON, BS_DEFPUSHBUTTON, $3, $1); }
 869	| ctrls tGROUPBOX	lab_ctrl	{ $$=ins_ctrl(CT_BUTTON, BS_GROUPBOX, $3, $1);}
 870	| ctrls tPUSHBUTTON	lab_ctrl	{ $$=ins_ctrl(CT_BUTTON, BS_PUSHBUTTON, $3, $1); }
 871/*	| ctrls tPUSHBOX	lab_ctrl	{ $$=ins_ctrl(CT_BUTTON, BS_PUSHBOX, $3, $1); } */
 872	| ctrls tRADIOBUTTON	lab_ctrl	{ $$=ins_ctrl(CT_BUTTON, BS_RADIOBUTTON, $3, $1); }
 873	| ctrls tAUTO3STATE	lab_ctrl	{ $$=ins_ctrl(CT_BUTTON, BS_AUTO3STATE, $3, $1); }
 874	| ctrls tSTATE3		lab_ctrl	{ $$=ins_ctrl(CT_BUTTON, BS_3STATE, $3, $1); }
 875	| ctrls tAUTOCHECKBOX	lab_ctrl	{ $$=ins_ctrl(CT_BUTTON, BS_AUTOCHECKBOX, $3, $1); }
 876	| ctrls tAUTORADIOBUTTON lab_ctrl	{ $$=ins_ctrl(CT_BUTTON, BS_AUTORADIOBUTTON, $3, $1); }
 877	| ctrls tLTEXT		lab_ctrl	{ $$=ins_ctrl(CT_STATIC, SS_LEFT, $3, $1); }
 878	| ctrls tCTEXT		lab_ctrl	{ $$=ins_ctrl(CT_STATIC, SS_CENTER, $3, $1); }
 879	| ctrls tRTEXT		lab_ctrl	{ $$=ins_ctrl(CT_STATIC, SS_RIGHT, $3, $1); }
 880	/* special treatment for icons, as the extent is optional */
 881	| ctrls tICON nameid_s opt_comma expr ',' expr ',' expr iconinfo {
 882		$10->title = $3;
 883		$10->id = $5;
 884		$10->x = $7;
 885		$10->y = $9;
 886		$$ = ins_ctrl(CT_STATIC, SS_ICON, $10, $1);
 887		}
 888	;
 889
 890lab_ctrl
 891	: nameid_s opt_comma expr ',' expr ',' expr ',' expr ',' expr optional_style_pair {
 892		$$=new_control();
 893		$$->title = $1;
 894		$$->id = $3;
 895		$$->x = $5;
 896		$$->y = $7;
 897		$$->width = $9;
 898		$$->height = $11;
 899		if($12)
 900		{
 901			$$->style = $12->style;
 902			$$->gotstyle = TRUE;
 903			if ($12->exstyle)
 904			{
 905			    $$->exstyle = $12->exstyle;
 906			    $$->gotexstyle = TRUE;
 907			}
 908			free($12);
 909		}
 910		}
 911	;
 912
 913ctrl_desc
 914	: expr ',' expr ',' expr ',' expr ',' expr optional_style_pair {
 915		$$ = new_control();
 916		$$->id = $1;
 917		$$->x = $3;
 918		$$->y = $5;
 919		$$->width = $7;
 920		$$->height = $9;
 921		if($10)
 922		{
 923			$$->style = $10->style;
 924			$$->gotstyle = TRUE;
 925			if ($10->exstyle)
 926			{
 927			    $$->exstyle = $10->exstyle;
 928			    $$->gotexstyle = TRUE;
 929			}
 930			free($10);
 931		}
 932		}
 933	;
 934
 935iconinfo: /* Empty */
 936		{ $$ = new_control(); }
 937
 938	| ',' expr ',' expr {
 939		$$ = new_control();
 940		$$->width = $2;
 941		$$->height = $4;
 942		}
 943	| ',' expr ',' expr ',' style {
 944		$$ = new_control();
 945		$$->width = $2;
 946		$$->height = $4;
 947		$$->style = $6;
 948		$$->gotstyle = TRUE;
 949		}
 950	| ',' expr ',' expr ',' style ',' style {
 951		$$ = new_control();
 952		$$->width = $2;
 953		$$->height = $4;
 954		$$->style = $6;
 955		$$->gotstyle = TRUE;
 956		$$->exstyle = $8;
 957		$$->gotexstyle = TRUE;
 958		}
 959	;
 960
 961gen_ctrl: nameid_s opt_comma expr ',' ctlclass ',' style ',' expr ',' expr ',' expr ',' expr ',' style {
 962		$$=new_control();
 963		$$->title = $1;
 964		$$->id = $3;
 965		$$->ctlclass = convert_ctlclass($5);
 966		$$->style = $7;
 967		$$->gotstyle = TRUE;
 968		$$->x = $9;
 969		$$->y = $11;
 970		$$->width = $13;
 971		$$->height = $15;
 972		$$->exstyle = $17;
 973		$$->gotexstyle = TRUE;
 974		}
 975	| nameid_s opt_comma expr ',' ctlclass ',' style ',' expr ',' expr ',' expr ',' expr {
 976		$$=new_control();
 977		$$->title = $1;
 978		$$->id = $3;
 979		$$->ctlclass = convert_ctlclass($5);
 980		$$->style = $7;
 981		$$->gotstyle = TRUE;
 982		$$->x = $9;
 983		$$->y = $11;
 984		$$->width = $13;
 985		$$->height = $15;
 986		}
 987	;
 988
 989opt_font
 990	: tFONT expr ',' tSTRING	{ $$ = new_font_id($2, $4, 0, 0); }
 991	;
 992
 993/* ------------------------------ style flags ------------------------------ */
 994optional_style_pair
 995	: /* Empty */		{ $$ = NULL; }
 996	| ',' style		{ $$ = new_style_pair($2, 0); }
 997	| ',' style ',' style 	{ $$ = new_style_pair($2, $4); }
 998	;
 999
1000style
1001	: style '|' style	{ $$ = new_style($1->or_mask | $3->or_mask, $1->and_mask | $3->and_mask); free($1); free($3);}
1002	| '(' style ')'		{ $$ = $2; }
1003        | any_num       	{ $$ = new_style($1, 0); }
1004        | tNOT any_num		{ $$ = new_style(0, $2); }
1005        ;
1006
1007ctlclass
1008	: expr	{
1009		$$ = new_name_id();
1010		$$->type = name_ord;
1011		$$->name.i_name = $1;
1012		}
1013	| tSTRING {
1014		$$ = new_name_id();
1015		$$->type = name_str;
1016		$$->name.s_name = $1;
1017		}
1018	;
1019
1020/* ------------------------------ DialogEx ------------------------------ */
1021dialogex: tDIALOGEX loadmemopts expr ',' expr ',' expr ',' expr helpid dlgex_attribs
1022	  tBEGIN  exctrls tEND {
1023		if(!win32)
1024			parser_warning("DIALOGEX not supported in 16-bit mode\n");
1025		if($2)
1026		{
1027			$11->memopt = *($2);
1028			free($2);
1029		}
1030		else
1031			$11->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
1032		$11->x = $3;
1033		$11->y = $5;
1034		$11->width = $7;
1035		$11->height = $9;
1036		if($10)
1037		{
1038			$11->helpid = *($10);
1039			$11->gothelpid = TRUE;
1040			free($10);
1041		}
1042		$11->controls = get_control_head($13);
1043		$$ = $11;
1044
1045		assert($$->style != NULL);
1046		if(!$$->gotstyle)
1047		{
1048			$$->style->or_mask = WS_POPUP;
1049			$$->gotstyle = TRUE;
1050		}
1051		if($$->title)
1052			$$->style->or_mask |= WS_CAPTION;
1053		if($$->font)
1054			$$->style->or_mask |= DS_SETFONT;
1055
1056		$$->style->or_mask &= ~($$->style->and_mask);
1057		$$->style->and_mask = 0;
1058
1059		if(!$$->lvc.language)
1060			$$->lvc.language = dup_language(currentlanguage);
1061		}
1062	;
1063
1064dlgex_attribs
1065	: /* Empty */				{ $$=new_dialog(); $$->is_ex = TRUE; }
1066	| dlgex_attribs tSTYLE style		{ $$=dialog_style($3,$1); }
1067	| dlgex_attribs tEXSTYLE style		{ $$=dialog_exstyle($3,$1); }
1068	| dlgex_attribs tCAPTION tSTRING	{ $$=dialog_caption($3,$1); }
1069	| dlgex_attribs opt_font		{ $$=dialog_font($2,$1); }
1070	| dlgex_attribs opt_exfont		{ $$=dialog_font($2,$1); }
1071	| dlgex_attribs tCLASS nameid_s		{ $$=dialog_class($3,$1); }
1072	| dlgex_attribs tMENU nameid		{ $$=dialog_menu($3,$1); }
1073	| dlgex_attribs opt_language		{ $$=dialog_language($2,$1); }
1074	| dlgex_attribs opt_characts		{ $$=dialog_characteristics($2,$1); }
1075	| dlgex_attribs opt_version		{ $$=dialog_version($2,$1); }
1076	;
1077
1078exctrls	: /* Empty */				{ $$ = NULL; }
1079	| exctrls tCONTROL	gen_exctrl	{ $$=ins_ctrl(-1, 0, $3, $1); }
1080	| exctrls tEDITTEXT	exctrl_desc	{ $$=ins_ctrl(CT_EDIT, 0, $3, $1); }
1081	| exctrls tLISTBOX	exctrl_desc	{ $$=ins_ctrl(CT_LISTBOX, 0, $3, $1); }
1082	| exctrls tCOMBOBOX	exctrl_desc	{ $$=ins_ctrl(CT_COMBOBOX, 0, $3, $1); }
1083	| exctrls tSCROLLBAR	exctrl_desc	{ $$=ins_ctrl(CT_SCROLLBAR, 0, $3, $1); }
1084	| exctrls tCHECKBOX	lab_exctrl	{ $$=ins_ctrl(CT_BUTTON, BS_CHECKBOX, $3, $1); }
1085	| exctrls tDEFPUSHBUTTON lab_exctrl	{ $$=ins_ctrl(CT_BUTTON, BS_DEFPUSHBUTTON, $3, $1); }
1086	| exctrls tGROUPBOX	lab_exctrl	{ $$=ins_ctrl(CT_BUTTON, BS_GROUPBOX, $3, $1);}
1087	| exctrls tPUSHBUTTON	lab_exctrl	{ $$=ins_ctrl(CT_BUTTON, BS_PUSHBUTTON, $3, $1); }
1088/*	| exctrls tPUSHBOX	lab_exctrl	{ $$=ins_ctrl(CT_BUTTON, BS_PUSHBOX, $3, $1); } */
1089	| exctrls tRADIOBUTTON	lab_exctrl	{ $$=ins_ctrl(CT_BUTTON, BS_RADIOBUTTON, $3, $1); }
1090	| exctrls tAUTO3STATE	lab_exctrl	{ $$=ins_ctrl(CT_BUTTON, BS_AUTO3STATE, $3, $1); }
1091	| exctrls tSTATE3	lab_exctrl	{ $$=ins_ctrl(CT_BUTTON, BS_3STATE, $3, $1); }
1092	| exctrls tAUTOCHECKBOX	lab_exctrl	{ $$=ins_ctrl(CT_BUTTON, BS_AUTOCHECKBOX, $3, $1); }
1093	| exctrls tAUTORADIOBUTTON lab_exctrl	{ $$=ins_ctrl(CT_BUTTON, BS_AUTORADIOBUTTON, $3, $1); }
1094	| exctrls tLTEXT	lab_exctrl	{ $$=ins_ctrl(CT_STATIC, SS_LEFT, $3, $1); }
1095	| exctrls tCTEXT	lab_exctrl	{ $$=ins_ctrl(CT_STATIC, SS_CENTER, $3, $1); }
1096	| exctrls tRTEXT	lab_exctrl	{ $$=ins_ctrl(CT_STATIC, SS_RIGHT, $3, $1); }
1097	/* special treatment for icons, as the extent is optional */
1098	| exctrls tICON nameid_s opt_comma expr ',' expr ',' expr iconinfo {
1099		$10->title = $3;
1100		$10->id = $5;
1101		$10->x = $7;
1102		$10->y = $9;
1103		$$ = ins_ctrl(CT_STATIC, SS_ICON, $10, $1);
1104		}
1105	;
1106
1107gen_exctrl
1108	: nameid_s opt_comma expr ',' ctlclass ',' style ',' expr ',' expr ',' expr ','
1109	  expr ',' style helpid opt_data {
1110		$$=new_control();
1111		$$->title = $1;
1112		$$->id = $3;
1113		$$->ctlclass = convert_ctlclass($5);
1114		$$->style = $7;
1115		$$->gotstyle = TRUE;
1116		$$->x = $9;
1117		$$->y = $11;
1118		$$->width = $13;
1119		$$->height = $15;
1120		if($17)
1121		{
1122			$$->exstyle = $17;
1123			$$->gotexstyle = TRUE;
1124		}
1125		if($18)
1126		{
1127			$$->helpid = *($18);
1128			$$->gothelpid = TRUE;
1129			free($18);
1130		}
1131		$$->extra = $19;
1132		}
1133	| nameid_s opt_comma expr ',' ctlclass ',' style ',' expr ',' expr ',' expr ',' expr opt_data {
1134		$$=new_control();
1135		$$->title = $1;
1136		$$->id = $3;
1137		$$->style = $7;
1138		$$->gotstyle = TRUE;
1139		$$->ctlclass = convert_ctlclass($5);
1140		$$->x = $9;
1141		$$->y = $11;
1142		$$->width = $13;
1143		$$->height = $15;
1144		$$->extra = $16;
1145		}
1146	;
1147
1148lab_exctrl
1149	: nameid_s opt_comma expr ',' expr ',' expr ',' expr ',' expr optional_style_pair helpid opt_data {
1150		$$=new_control();
1151		$$->title = $1;
1152		$$->id = $3;
1153		$$->x = $5;
1154		$$->y = $7;
1155		$$->width = $9;
1156		$$->height = $11;
1157		if($12)
1158		{
1159			$$->style = $12->style;
1160			$$->gotstyle = TRUE;
1161
1162			if ($12->exstyle)
1163			{
1164			    $$->exstyle = $12->exstyle;
1165			    $$->gotexstyle = TRUE;
1166			}
1167			free($12);
1168		}
1169
1170		$$->extra = $14;
1171		}
1172	;
1173
1174exctrl_desc
1175	: expr ',' expr ',' expr ',' expr ',' expr optional_style_pair helpid opt_data {
1176		$$ = new_control();
1177		$$->id = $1;
1178		$$->x = $3;
1179		$$->y = $5;
1180		$$->width = $7;
1181		$$->height = $9;
1182		if($10)
1183		{
1184			$$->style = $10->style;
1185			$$->gotstyle = TRUE;
1186
1187			if ($10->exstyle)
1188			{
1189			    $$->exstyle = $10->exstyle;
1190			    $$->gotexstyle = TRUE;
1191			}
1192			free($10);
1193		}
1194		$$->extra = $12;
1195		}
1196	;
1197
1198opt_data: /* Empty */	{ $$ = NULL; }
1199	| raw_data	{ $$ = $1; }
1200	;
1201
1202helpid	: /* Empty */	{ $$ = NULL; }
1203	| ',' expr	{ $$ = new_int($2); }
1204	;
1205
1206opt_exfont
1207	: tFONT expr ',' tSTRING ',' expr ',' expr  opt_expr { $$ = new_font_id($2, $4, $6, $8); }
1208	;
1209
1210/*
1211 * FIXME: This odd expression is here to nullify an extra token found
1212 * in some appstudio produced resources which appear to do nothing.
1213 */
1214opt_expr: /* Empty */	{ $$ = NULL; }
1215	| ',' expr	{ $$ = NULL; }
1216	;
1217
1218/* ------------------------------ Menu ------------------------------ */
1219menu	: tMENU loadmemopts opt_lvc menu_body {
1220		if(!$4)
1221			yyerror("Menu must contain items");
1222		$$ = new_menu();
1223		if($2)
1224		{
1225			$$->memopt = *($2);
1226			free($2);
1227		}
1228		else
1229			$$->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
1230		$$->items = get_item_head($4);
1231		if($3)
1232		{
1233			$$->lvc = *($3);
1234			free($3);
1235		}
1236		if(!$$->lvc.language)
1237			$$->lvc.language = dup_language(currentlanguage);
1238		}
1239	;
1240
1241menu_body
1242	: tBEGIN item_definitions tEND	{ $$ = $2; }
1243	;
1244
1245item_definitions
1246	: /* Empty */	{$$ = NULL;}
1247	| item_definitions tMENUITEM tSTRING opt_comma expr item_options {
1248		$$=new_menu_item();
1249		$$->prev = $1;
1250		if($1)
1251			$1->next = $$;
1252		$$->id =  $5;
1253		$$->state = $6;
1254		$$->name = $3;
1255		}
1256	| item_definitions tMENUITEM tSEPARATOR {
1257		$$=new_menu_item();
1258		$$->prev = $1;
1259		if($1)
1260			$1->next = $$;
1261		}
1262	| item_definitions tPOPUP tSTRING item_options menu_body {
1263		$$ = new_menu_item();
1264		$$->prev = $1;
1265		if($1)
1266			$1->next = $$;
1267		$$->popup = get_item_head($5);
1268		$$->name = $3;
1269		}
1270	;
1271
1272/* NOTE: item_options is right recursive because it would introduce
1273 * a shift/reduce conflict on ',' in itemex_options due to the
1274 * empty rule here. The parser is now forced to look beyond the ','
1275 * before reducing (force shift).
1276 * Right recursion here is not a problem because we cannot expect
1277 * more than 7 parserstack places to be occupied while parsing this
1278 * (who would want to specify a MF_x flag twice?).
1279 */
1280item_options
1281	:  /* Empty */			{ $$ = 0; }
1282	| ','		item_options	{ $$ = $2; }
1283	| tCHECKED	item_options	{ $$ = $2 | MF_CHECKED; }
1284	| tGRAYED	item_options	{ $$ = $2 | MF_GRAYED; }
1285	| tHELP		item_options	{ $$ = $2 | MF_HELP; }
1286	| tINACTIVE	item_options	{ $$ = $2 | MF_DISABLED; }
1287	| tMENUBARBREAK	item_options	{ $$ = $2 | MF_MENUBARBREAK; }
1288	| tMENUBREAK	item_options	{ $$ = $2 | MF_MENUBREAK; }
1289	;
1290
1291/* ------------------------------ MenuEx ------------------------------ */
1292menuex	: tMENUEX loadmemopts opt_lvc menuex_body	{
1293		if(!win32)
1294			parser_warning("MENUEX not supported in 16-bit mode\n");
1295		if(!$4)
1296			yyerror("MenuEx must contain items");
1297		$$ = new_menu();
1298		$$->is_ex = TRUE;
1299		if($2)
1300		{
1301			$$->memopt = *($2);
1302			free($2);
1303		}
1304		else
1305			$$->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
1306		$$->items = get_item_head($4);
1307		if($3)
1308		{
1309			$$->lvc = *($3);
1310			free($3);
1311		}
1312		if(!$$->lvc.language)
1313			$$->lvc.language = dup_language(currentlanguage);
1314		}
1315	;
1316
1317menuex_body
1318	: tBEGIN itemex_definitions tEND { $$ = $2; }
1319	;
1320
1321itemex_definitions
1322	: /* Empty */	{$$ = NULL; }
1323	| itemex_definitions tMENUITEM tSTRING itemex_options {
1324		$$ = new_menu_item();
1325		$$->prev = $1;
1326		if($1)
1327			$1->next = $$;
1328		$$->name = $3;
1329		$$->id = $4->id;
1330		$$->type = $4->type;
1331		$$->state = $4->state;
1332		$$->helpid = $4->helpid;
1333		$$->gotid = $4->gotid;
1334		$$->gottype = $4->gottype;
1335		$$->gotstate = $4->gotstate;
1336		$$->gothelpid = $4->gothelpid;
1337		free($4);
1338		}
1339	| itemex_definitions tMENUITEM tSEPARATOR {
1340		$$ = new_menu_item();
1341		$$->prev = $1;
1342		if($1)
1343			$1->next = $$;
1344		}
1345	| itemex_definitions tPOPUP tSTRING itemex_p_options menuex_body {
1346		$$ = new_menu_item();
1347		$$->prev = $1;
1348		if($1)
1349			$1->next = $$;
1350		$$->popup = get_item_head($5);
1351		$$->name = $3;
1352		$$->id = $4->id;
1353		$$->type = $4->type;
1354		$$->state = $4->state;
1355		$$->helpid = $4->helpid;
1356		$$->gotid = $4->gotid;
1357		$$->gottype = $4->gottype;
1358		$$->gotstate = $4->gotstate;
1359		$$->gothelpid = $4->gothelpid;
1360		free($4);
1361		}
1362	;
1363
1364itemex_options
1365	: /* Empty */			{ $$ = new_itemex_opt(0, 0, 0, 0); }
1366	| ',' expr {
1367		$$ = new_itemex_opt($2, 0, 0, 0);
1368		$$->gotid = TRUE;
1369		}
1370	| ',' e_expr ',' e_expr item_options {
1371		$$ = new_itemex_opt($2 ? *($2) : 0, $4 ? *($4) : 0, $5, 0);
1372		$$->gotid = TRUE;
1373		$$->gottype = TRUE;
1374		$$->gotstate = TRUE;
1375		free($2);
1376		free($4);
1377		}
1378	| ',' e_expr ',' e_expr ',' expr {
1379		$$ = new_itemex_opt($2 ? *($2) : 0, $4 ? *($4) : 0, $6, 0);
1380		$$->gotid = TRUE;
1381		$$->gottype = TRUE;
1382		$$->gotstate = TRUE;
1383		free($2);
1384		free($4);
1385		}
1386	;
1387
1388itemex_p_options
1389	: /* Empty */			{ $$ = new_itemex_opt(0, 0, 0, 0); }
1390	| ',' expr {
1391		$$ = new_itemex_opt($2, 0, 0, 0);
1392		$$->gotid = TRUE;
1393		}
1394	| ',' e_expr ',' expr {
1395		$$ = new_itemex_opt($2 ? *($2) : 0, $4, 0, 0);
1396		free($2);
1397		$$->gotid = TRUE;
1398		$$->gottype = TRUE;
1399		}
1400	| ',' e_expr ',' e_expr ',' expr {
1401		$$ = new_itemex_opt($2 ? *($2) : 0, $4 ? *($4) : 0, $6, 0);
1402		free($2);
1403		free($4);
1404		$$->gotid = TRUE;
1405		$$->gottype = TRUE;
1406		$$->gotstate = TRUE;
1407		}
1408	| ',' e_expr ',' e_expr ',' e_expr ',' expr {
1409		$$ = new_itemex_opt($2 ? *($2) : 0, $4 ? *($4) : 0, $6 ? *($6) : 0, $8);
1410		free($2);
1411		free($4);
1412		free($6);
1413		$$->gotid = TRUE;
1414		$$->gottype = TRUE;
1415		$$->gotstate = TRUE;
1416		$$->gothelpid = TRUE;
1417		}
1418	;
1419
1420/* ------------------------------ StringTable ------------------------------ */
1421/* Stringtables are parsed differently than other resources because their
1422 * layout is substantially different from other resources.
1423 * The table is parsed through a _global_ variable 'tagstt' which holds the
1424 * current stringtable descriptor (stringtable_t *) and 'sttres' that holds a
1425 * list of stringtables of different languages.
1426 */
1427stringtable
1428	: stt_head tBEGIN strings tEND {
1429		if(!$3)
1430		{
1431			yyerror("Stringtable must have at least one entry");
1432		}
1433		else
1434		{
1435			stringtable_t *stt;
1436			/* Check if we added to a language table or created
1437			 * a new one.
1438			 */
1439			 for(stt = sttres; stt; stt = stt->next)
1440			 {
1441				if(stt == tagstt)
1442					break;
1443			 }
1444			 if(!stt)
1445			 {
1446				/* It is a new one */
1447				if(sttres)
1448				{
1449					sttres->prev = tagstt;
1450					tagstt->next = sttres;
1451					sttres = tagstt;
1452				}
1453				else
1454					sttres = tagstt;
1455			 }
1456			 /* Else were done */
1457		}
1458		free(tagstt_memopt);
1459		tagstt_memopt = NULL;
1460
1461		$$ = tagstt;
1462		}
1463	;
1464
1465/* This is to get the language of the currently parsed stringtable */
1466stt_head: tSTRINGTABLE loadmemopts opt_lvc {
1467		if((tagstt = find_stringtable($3)) == NULL)
1468			tagstt = new_stringtable($3);
1469		tagstt_memopt = $2;
1470		tagstt_version = $3->version;
1471		tagstt_characts = $3->characts;
1472		free($3);
1473		}
1474	;
1475
1476strings	: /* Empty */	{ $$ = NULL; }
1477	| strings expr opt_comma tSTRING {
1478		int i;
1479		assert(tagstt != NULL);
1480		if($2 > 65535 || $2 < -32768)
1481			yyerror("Stringtable entry's ID out of range (%d)", $2);
1482		/* Search for the ID */
1483		for(i = 0; i < tagstt->nentries; i++)
1484		{
1485			if(tagstt->entries[i].id == $2)
1486				yyerror("Stringtable ID %d already in use", $2);
1487		}
1488		/* If we get here, then we have a new unique entry */
1489		tagstt->nentries++;
1490		tagstt->entries = xrealloc(tagstt->entries, sizeof(tagstt->entries[0]) * tagstt->nentries);
1491		tagstt->entries[tagstt->nentries-1].id = $2;
1492		tagstt->entries[tagstt->nentries-1].str = $4;
1493		if(tagstt_memopt)
1494			tagstt->entries[tagstt->nentries-1].memopt = *tagstt_memopt;
1495		else
1496			tagstt->entries[tagstt->nentries-1].memopt = WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE | WRC_MO_PURE;
1497		tagstt->entries[tagstt->nentries-1].version = tagstt_version;
1498		tagstt->entries[tagstt->nentries-1].characts = tagstt_characts;
1499
1500		if(pedantic && !$4->size)
1501			parser_warning("Zero length strings make no sense\n");
1502		if(!win32 && $4->size > 254)
1503			yyerror("Stringtable entry more than 254 characters");
1504		if(win32 && $4->size > 65534) /* Hmm..., does this happen? */
1505			yyerror("Stringtable entry more than 65534 characters (probably something else that went wrong)");
1506		$$ = tagstt;
1507		}
1508	;
1509
1510opt_comma	/* There seem to be two ways to specify a stringtable... */
1511	: /* Empty */
1512	| ','
1513	;
1514
1515/* ------------------------------ VersionInfo ------------------------------ */
1516versioninfo
1517	: tVERSIONINFO loadmemopts fix_version tBEGIN ver_blocks tEND {
1518		$$ = $3;
1519		if($2)
1520		{
1521			$$->memopt = *($2);
1522			free($2);
1523		}
1524		else
1525			$$->memopt = WRC_MO_MOVEABLE | (win32 ? WRC_MO_PURE : 0);
1526		$$->blocks = get_ver_block_head($5);
1527		/* Set language; there is no version or characteristics */
1528		$$->lvc.language = dup_language(currentlanguage);
1529		}
1530	;
1531
1532fix_version
1533	: /* Empty */			{ $$ = new_versioninfo(); }
1534	| fix_version tFILEVERSION expr ',' expr ',' expr ',' expr {
1535		if($1->gotit.fv)
1536			yyerror("FILEVERSION already defined");
1537		$$ = $1;
1538		$$->filever_maj1 = $3;
1539		$$->filever_maj2 = $5;
1540		$$->filever_min1 = $7;
1541		$$->filever_min2 = $9;
1542		$$->gotit.fv = 1;
1543		}
1544	| fix_version tPRODUCTVERSION expr ',' expr ',' expr ',' expr {
1545		if($1->gotit.pv)
1546			yyerror("PRODUCTVERSION already defined");
1547		$$ = $1;
1548		$$->prodver_maj1 = $3;
1549		$$->prodver_maj2 = $5;
1550		$$->prodver_min1 = $7;
1551		$$->prodver_min2 = $9;
1552		$$->gotit.pv = 1;
1553		}
1554	| fix_version tFILEFLAGS expr {
1555		if($1->gotit.ff)
1556			yyerror("FILEFLAGS already defined");
1557		$$ = $1;
1558		$$->fileflags = $3;
1559		$$->gotit.ff = 1;
1560		}
1561	| fix_version tFILEFLAGSMASK expr {
1562		if($1->gotit.ffm)
1563			yyerror("FILEFLAGSMASK already defined");
1564		$$ = $1;
1565		$$->fileflagsmask = $3;
1566		$$->gotit.ffm = 1;
1567		}
1568	| fix_version tFILEOS expr {
1569		if($1->gotit.fo)
1570			yyerror("FILEOS already defined");
1571		$$ = $1;
1572		$$->fileos = $3;
1573		$$->gotit.fo = 1;
1574		}
1575	| fix_version tFILETYPE expr {
1576		if($1->gotit.ft)
1577			yyerror("FILETYPE already defined");
1578		$$ = $1;
1579		$$->filetype = $3;
1580		$$->gotit.ft = 1;
1581		}
1582	| fix_version tFILESUBTYPE expr {
1583		if($1->gotit.fst)
1584			yyerror("FILESUBTYPE already defined");
1585		$$ = $1;
1586		$$->filesubtype = $3;
1587		$$->gotit.fst = 1;
1588		}
1589	;
1590
1591ver_blocks
1592	: /* Empty */			{ $$ = NULL; }
1593	| ver_blocks ver_block {
1594		$$ = $2;
1595		$$->prev = $1;
1596		if($1)
1597			$1->next = $$;
1598		}
1599	;
1600
1601ver_block
1602	: tBLOCK tSTRING tBEGIN ver_values tEND {
1603		$$ = new_ver_block();
1604		$$->name = $2;
1605		$$->values = get_ver_value_head($4);
1606		}
1607	;
1608
1609ver_values
1610	: /* Empty */			{ $$ = NULL; }
1611	| ver_values ver_value {
1612		$$ = $2;
1613		$$->prev = $1;
1614		if($1)
1615			$1->next = $$;
1616		}
1617	;
1618
1619ver_value
1620	: ver_block {
1621		$$ = new_ver_value();
1622		$$->type = val_block;
1623		$$->value.block = $1;
1624		}
1625	| tVALUE tSTRING ',' tSTRING {
1626		$$ = new_ver_value();
1627		$$->type = val_str;
1628		$$->key = $2;
1629		$$->value.str = $4;
1630		}
1631	| tVALUE tSTRING ',' ver_words {
1632		$$ = new_ver_value();
1633		$$->type = val_words;
1634		$$->key = $2;
1635		$$->value.words = $4;
1636		}
1637	;
1638
1639ver_words
1640	: expr			{ $$ = new_ver_words($1); }
1641	| ver_words ',' expr	{ $$ = add_ver_words($1, $3); }
1642	;
1643
1644/* ------------------------------ Toolbar ------------------------------ */
1645toolbar: tTOOLBAR loadmemopts expr ',' expr opt_lvc tBEGIN toolbar_items tEND {
1646		int nitems;
1647		toolbar_item_t *items = get_tlbr_buttons_head($8, &nitems);
1648		$$ = new_toolbar($3, $5, items, nitems);
1649		if($2)
1650		{
1651			$$->memopt = *($2);
1652			free($2);
1653		}
1654		else
1655		{
1656			$$->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE;
1657		}
1658		if($6)
1659		{
1660			$$->lvc = *($6);
1661			free($6);
1662		}
1663		if(!$$->lvc.language)
1664		{
1665			$$->lvc.language = dup_language(currentlanguage);
1666		}
1667		}
1668	;
1669
1670toolbar_items
1671	:  /* Empty */			{ $$ = NULL; }
1672	| toolbar_items tBUTTON expr	{
1673		toolbar_item_t *idrec = new_toolbar_item();
1674		idrec->id = $3;
1675		$$ = ins_tlbr_button($1, idrec);
1676		}
1677	| toolbar_items tSEPARATOR	{
1678		toolbar_item_t *idrec = new_toolbar_item();
1679		idrec->id = 0;
1680		$$ = ins_tlbr_button($1, idrec);
1681	}
1682	;
1683
1684/* ------------------------------ Memory options ------------------------------ */
1685loadmemopts
1686	: /* Empty */		{ $$ = NULL; }
1687	| loadmemopts lamo {
1688		if($1)
1689		{
1690			*($1) |= *($2);
1691			$$ = $1;
1692			free($2);
1693		}
1694		else
1695			$$ = $2;
1696		}
1697	| loadmemopts lama {
1698		if($1)
1699		{
1700			*($1) &= *($2);
1701			$$ = $1;
1702			free($2);
1703		}
1704		else
1705		{
1706			*$2 &= WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE | WRC_MO_PURE;
1707			$$ = $2;
1708		}
1709		}
1710	;
1711
1712lamo	: tPRELOAD	{ $$ = new_int(WRC_MO_PRELOAD);
1713			  if (win32 && pedantic) parser_warning("PRELOAD is ignored in 32-bit mode\n"); }
1714	| tMOVEABLE	{ $$ = new_int(WRC_MO_MOVEABLE);
1715			  if (win32 && pedantic) parser_warning("MOVEABLE is ignored in 32-bit mode\n"); }
1716	| tDISCARDABLE	{ $$ = new_int(WRC_MO_DISCARDABLE);
1717			  if (win32 && pedantic) parser_warning("DISCARDABLE is ignored in 32-bit mode\n"); }
1718	| tPURE		{ $$ = new_int(WRC_MO_PURE);
1719			  if (win32 && pedantic) parser_warning("PURE is ignored in 32-bit mode\n"); }
1720	;
1721
1722lama	: tLOADONCALL	{ $$ = new_int(~WRC_MO_PRELOAD);
1723			  if (win32 && pedantic) parser_warning("LOADONCALL is ignored in 32-bit mode\n"); }
1724	| tFIXED	{ $$ = new_int(~WRC_MO_MOVEABLE);
1725			  if (win32 && pedantic) parser_warning("FIXED is ignored in 32-bit mode\n"); }
1726	| tIMPURE	{ $$ = new_int(~WRC_MO_PURE);
1727			  if (win32 && pedantic) parser_warning("IMPURE is ignored in 32-bit mode\n"); }
1728	;
1729
1730/* ------------------------------ Win32 options ------------------------------ */
1731opt_lvc	: /* Empty */		{ $$ = new_lvc(); }
1732	| opt_lvc opt_langu…

Large files files are truncated, but you can click here to view the full file