source: trunk/tools/wrc/parser.y@ 1036

Last change on this file since 1036 was 882, checked in by sandervl, 26 years ago

Created Wine port of wrc (using EMX/GCC)

File size: 63.0 KB
Line 
1%{
2/*
3 * Copyright Martin von Loewis, 1994
4 * Copyright 1998 Bertho A. Stultiens (BS)
5 *
6 * 29-Dec-1998 AdH - Grammar and function extensions.
7 * grammar: TOOLBAR resources, Named ICONs in
8 * DIALOGS
9 * functions: semantic actions for the grammar
10 * changes, resource files can now be anywhere
11 * on the include path instead of just in the
12 * current directory
13 *
14 * 20-Jun-1998 BS - Fixed a bug in load_file() where the name was not
15 * printed out correctly.
16 *
17 * 17-Jun-1998 BS - Fixed a bug in CLASS statement parsing which should
18 * also accept a tSTRING as argument.
19 *
20 * 25-May-1998 BS - Found out that I need to support language, version
21 * and characteristics in inline resources (bitmap,
22 * cursor, etc) but they can also be specified with
23 * a filename. This renders my filename-scanning scheme
24 * worthless. Need to build newline parsing to solve
25 * this one.
26 * It will come with version 1.1.0 (sigh).
27 *
28 * 19-May-1998 BS - Started to build a builtin preprocessor
29 *
30 * 30-Apr-1998 BS - Redid the stringtable parsing/handling. My previous
31 * ideas had some serious flaws.
32 *
33 * 27-Apr-1998 BS - Removed a lot of dead comments and put it in a doc
34 * file.
35 *
36 * 21-Apr-1998 BS - Added correct behavior for cursors and icons.
37 * - This file is growing too big. It is time to strip
38 * things and put it in a support file.
39 *
40 * 19-Apr-1998 BS - Tagged the stringtable resource so that only one
41 * resource will be created. This because the table
42 * has a different layout than other resources. The
43 * table has to be sorted, and divided into smaller
44 * resource entries (see comment in source).
45 *
46 * 17-Apr-1998 BS - Almost all strings, including identifiers, are parsed
47 * as string_t which include unicode strings upon
48 * input.
49 * - Parser now emits a warning when compiling win32
50 * extensions in win16 mode.
51 *
52 * 16-Apr-1998 BS - Raw data elements are now *optionally* seperated
53 * by commas. Read the comments in file sq2dq.l.
54 * - FIXME: there are instances in the source that rely
55 * on the fact that int==32bit and pointers are int size.
56 * - Fixed the conflict in menuex by changing a rule
57 * back into right recursion. See note in source.
58 * - UserType resources cannot have an expression as its
59 * typeclass. See note in source.
60 *
61 * 15-Apr-1998 BS - Changed all right recursion into left recursion to
62 * get reduction of the parsestack.
63 * This also helps communication between bison and flex.
64 * Main advantage is that the Empty rule gets reduced
65 * first, which is used to allocate/link things.
66 * It also added a shift/reduce conflict in the menuex
67 * handling, due to expression/option possibility,
68 * although not serious.
69 *
70 * 14-Apr-1998 BS - Redone almost the entire parser. We're not talking
71 * about making it more efficient, but readable (for me)
72 * and slightly easier to expand/change.
73 * This is done primarily by using more reduce states
74 * with many (intuitive) types for the various resource
75 * statements.
76 * - Added expression handling for all resources where a
77 * number is accepted (not only for win32). Also added
78 * multiply and division (not MS compatible, but handy).
79 * Unary minus introduced a shift/reduce conflict, but
80 * it is not serious.
81 *
82 * 13-Apr-1998 BS - Reordered a lot of things
83 * - Made the source more readable
84 * - Added Win32 resource definitions
85 * - Corrected syntax problems with an old yacc (;)
86 * - Added extra comment about grammar
87 */
88#include "config.h"
89
90#include <stdio.h>
91#include <stdlib.h>
92#include <stdarg.h>
93#include <assert.h>
94#include <ctype.h>
95#include <string.h>
96#ifdef HAVE_ALLOCA_H
97#include <alloca.h>
98#endif
99
100#include "wrc.h"
101#include "utils.h"
102#include "newstruc.h"
103#include "dumpres.h"
104#include "preproc.h"
105#include "parser.h"
106#include "winuser.h"
107
108#ifdef __BORLANDC__
109#pragma warn -sig
110#endif
111
112DWORD andmask; /* Used to parse 'NOT NUMBER' expressions */
113int indialog = 0; /* Signal flex that we're parsing a dialog */
114int want_rscname = 0; /* Set when a resource's name is required */
115stringtable_t *tagstt; /* Stringtable tag.
116 * It is set while parsing a stringtable to one of
117 * the stringtables in the sttres list or a new one
118 * if the language was not parsed before.
119 */
120stringtable_t *sttres; /* Stringtable resources. This holds the list of
121 * stringtables with different lanuages
122 */
123/* Set to the current options of the currently scanning stringtable */
124static int *tagstt_memopt;
125static characts_t *tagstt_characts;
126static version_t *tagstt_version;
127
128/* Prototypes of here defined functions */
129void split_cursors(raw_data_t *rd, cursor_group_t *curg, int *ncur);
130void split_icons(raw_data_t *rd, icon_group_t *icog, int *nico);
131int alloc_cursor_id(language_t *);
132int alloc_icon_id(language_t *);
133void ins_stt_entry(stt_entry_t *ste);
134int check_stt_entry(stringtable_t *tabs, stt_entry_t *ste);
135event_t *get_event_head(event_t *p);
136control_t *get_control_head(control_t *p);
137ver_value_t *get_ver_value_head(ver_value_t *p);
138ver_block_t *get_ver_block_head(ver_block_t *p);
139resource_t *get_resource_head(resource_t *p);
140menuex_item_t *get_itemex_head(menuex_item_t *p);
141menu_item_t *get_item_head(menu_item_t *p);
142raw_data_t *merge_raw_data_str(raw_data_t *r1, string_t *str);
143raw_data_t *merge_raw_data_int(raw_data_t *r1, int i);
144raw_data_t *merge_raw_data_long(raw_data_t *r1, int i);
145raw_data_t *merge_raw_data(raw_data_t *r1, raw_data_t *r2);
146raw_data_t *str2raw_data(string_t *str);
147raw_data_t *int2raw_data(int i);
148raw_data_t *long2raw_data(int i);
149raw_data_t *load_file(string_t *name);
150itemex_opt_t *new_itemex_opt(int id, int type, int state, int helpid);
151event_t *add_string_event(string_t *key, int id, int flags, event_t *prev);
152event_t *add_event(int key, int id, int flags, event_t *prev);
153dialogex_t *dialogex_version(version_t *v, dialogex_t *dlg);
154dialogex_t *dialogex_characteristics(characts_t *c, dialogex_t *dlg);
155dialogex_t *dialogex_language(language_t *l, dialogex_t *dlg);
156dialogex_t *dialogex_menu(name_id_t *m, dialogex_t *dlg);
157dialogex_t *dialogex_class(name_id_t *n, dialogex_t *dlg);
158dialogex_t *dialogex_font(font_id_t *f, dialogex_t *dlg);
159dialogex_t *dialogex_caption(string_t *s, dialogex_t *dlg);
160dialogex_t *dialogex_exstyle(int st, dialogex_t *dlg);
161dialogex_t *dialogex_style(int st, dialogex_t *dlg);
162name_id_t *convert_ctlclass(name_id_t *cls);
163control_t *ins_ctrl(int type, int style, control_t *ctrl, control_t *prev);
164dialog_t *dialog_version(version_t *v, dialog_t *dlg);
165dialog_t *dialog_characteristics(characts_t *c, dialog_t *dlg);
166dialog_t *dialog_language(language_t *l, dialog_t *dlg);
167dialog_t *dialog_menu(name_id_t *m, dialog_t *dlg);
168dialog_t *dialog_class(name_id_t *n, dialog_t *dlg);
169dialog_t *dialog_font(font_id_t *f, dialog_t *dlg);
170dialog_t *dialog_caption(string_t *s, dialog_t *dlg);
171dialog_t *dialog_exstyle(int st, dialog_t *dlg);
172dialog_t *dialog_style(int st, dialog_t *dlg);
173resource_t *build_stt_resources(stringtable_t *stthead);
174stringtable_t *find_stringtable(lvc_t *lvc);
175toolbar_item_t *ins_tlbr_button(toolbar_item_t *prev, toolbar_item_t *idrec);
176toolbar_item_t *get_tlbr_buttons_head(toolbar_item_t *p, int *nitems);
177
178%}
179%union{
180 string_t *str;
181 int num;
182 int *iptr;
183 resource_t *res;
184 accelerator_t *acc;
185 bitmap_t *bmp;
186 cursor_t *cur;
187 cursor_group_t *curg;
188 dialog_t *dlg;
189 dialogex_t *dlgex;
190 font_t *fnt;
191 icon_t *ico;
192 icon_group_t *icog;
193 menu_t *men;
194 menuex_t *menex;
195 rcdata_t *rdt;
196 stringtable_t *stt;
197 stt_entry_t *stte;
198 user_t *usr;
199 messagetable_t *msg;
200 versioninfo_t *veri;
201 control_t *ctl;
202 name_id_t *nid;
203 font_id_t *fntid;
204 language_t *lan;
205 version_t *ver;
206 characts_t *chars;
207 event_t *event;
208 menu_item_t *menitm;
209 menuex_item_t *menexitm;
210 itemex_opt_t *exopt;
211 raw_data_t *raw;
212 lvc_t *lvc;
213 ver_value_t *val;
214 ver_block_t *blk;
215 ver_words_t *verw;
216 toolbar_t *tlbar;
217 toolbar_item_t *tlbarItems;
218 dlginit_t *dginit;
219 style_pair_t *styles;
220}
221
222%token tIF tIFDEF tIFNDEF tELSE tELIF tENDIF tDEFINED tNL
223%token tTYPEDEF tEXTERN
224%token <num> NUMBER LNUMBER
225%token <str> tSTRING IDENT FILENAME
226%token <raw> RAWDATA
227%token ACCELERATORS tBITMAP CURSOR DIALOG DIALOGEX MENU MENUEX MESSAGETABLE
228%token RCDATA VERSIONINFO STRINGTABLE FONT ICON
229%token AUTO3STATE AUTOCHECKBOX AUTORADIOBUTTON CHECKBOX DEFPUSHBUTTON
230%token PUSHBUTTON RADIOBUTTON STATE3 /* PUSHBOX */
231%token GROUPBOX COMBOBOX LISTBOX SCROLLBAR
232%token CONTROL EDITTEXT
233%token RTEXT CTEXT LTEXT
234%token BLOCK VALUE
235%token SHIFT ALT ASCII VIRTKEY GRAYED CHECKED INACTIVE NOINVERT
236%token tPURE IMPURE DISCARDABLE LOADONCALL PRELOAD tFIXED MOVEABLE
237%token CLASS CAPTION CHARACTERISTICS EXSTYLE STYLE VERSION LANGUAGE
238%token FILEVERSION PRODUCTVERSION FILEFLAGSMASK FILEOS FILETYPE FILEFLAGS FILESUBTYPE
239%token MENUBARBREAK MENUBREAK MENUITEM POPUP SEPARATOR
240%token HELP
241%token tSTRING IDENT RAWDATA
242%token TOOLBAR BUTTON
243%token tBEGIN tEND
244%token DLGINIT
245%left LOGOR
246%left LOGAND
247%left '|'
248%left '^'
249%left '&'
250%left EQ NE
251%left '<' LTE '>' GTE
252%left '+' '-'
253%left '*' '/'
254%right '~' '!' NOT
255
256%type <res> resource_file resource resources resource_definition
257%type <stt> stringtable strings
258%type <fnt> font
259%type <icog> icon
260%type <acc> accelerators
261%type <event> events
262%type <bmp> bitmap
263%type <curg> cursor
264%type <dlg> dialog dlg_attributes
265%type <ctl> ctrls gen_ctrl lab_ctrl ctrl_desc iconinfo
266%type <iptr> optional_style helpid
267%type <dlgex> dialogex dlgex_attribs
268%type <ctl> exctrls gen_exctrl lab_exctrl exctrl_desc
269%type <rdt> rcdata
270%type <raw> raw_data raw_elements opt_data
271%type <veri> versioninfo fix_version
272%type <verw> ver_words
273%type <blk> ver_blocks ver_block
274%type <val> ver_values ver_value
275%type <men> menu
276%type <menitm> item_definitions menu_body
277%type <menex> menuex
278%type <menexitm> itemex_definitions menuex_body
279%type <exopt> itemex_p_options itemex_options
280%type <msg> messagetable
281%type <usr> userres
282%type <num> item_options
283%type <nid> nameid nameid_s ctlclass usertype
284%type <num> acc_opt
285%type <iptr> loadmemopts lamo lama
286%type <fntid> opt_font opt_exfont opt_expr
287%type <lvc> opt_lvc
288%type <lan> opt_language
289%type <chars> opt_characts
290%type <ver> opt_version
291%type <num> expr xpr dummy
292%type <iptr> e_expr
293%type <iptr> pp_expr pp_constant
294%type <tlbar> toolbar
295%type <tlbarItems> toolbar_items
296%type <dginit> dlginit
297%type <styles> optional_style_pair
298%type <num> any_num
299
300%%
301
302resource_file
303 : resources {
304 resource_t *rsc;
305 /* First add stringtables to the resource-list */
306 rsc = build_stt_resources(sttres);
307 /* 'build_stt_resources' returns a head and $1 is a tail */
308 if($1)
309 {
310 $1->next = rsc;
311 if(rsc)
312 rsc->prev = $1;
313 }
314 else
315 $1 = rsc;
316 /* Final statement before were done */
317 resource_top = get_resource_head($1);
318 }
319 ;
320
321/* Resources are put into a linked list */
322resources
323 : /* Empty */ { $$ = NULL; want_rscname = 1; }
324 | resources resource {
325 if($2)
326 {
327 resource_t *tail = $2;
328 resource_t *head = $2;
329 while(tail->next)
330 tail = tail->next;
331 while(head->prev)
332 head = head->prev;
333 head->prev = $1;
334 if($1)
335 $1->next = head;
336 $$ = tail;
337 }
338 else if($1)
339 {
340 resource_t *tail = $1;
341 while(tail->next)
342 tail = tail->next;
343 $$ = tail;
344 }
345 else
346 $$ = NULL;
347 want_rscname = 1;
348 }
349 | resources preprocessor { $$ = $1; want_rscname = 1; }
350 | resources cjunk { $$ = $1; want_rscname = 1; }
351 ;
352
353/* The buildin preprocessor */
354preprocessor
355 : tIF pp_expr tNL { pop_start(); push_if($2 ? *($2) : 0, 0, 0); if($2) free($2);}
356 | tIFDEF IDENT tNL { pop_start(); push_if(pp_lookup($2->str.cstr) != NULL, 0, 0); }
357 | tIFNDEF IDENT tNL { pop_start(); push_if(pp_lookup($2->str.cstr) == NULL, 0, 0); }
358 | tELIF pp_expr tNL { pop_start(); push_if($2 ? *($2) : 0, pop_if(), 0); if($2) free($2); }
359 | tELSE tNL { pop_start(); push_if(1, pop_if(), 0); }
360 | tENDIF tNL { pop_if(); }
361 ;
362
363pp_expr : pp_constant { $$ = $1; }
364 | pp_expr LOGOR pp_expr { $$ = new_int($1 && $3 ? (*$1 || *$3) : 0); if($1) free($1); if($3) free($3); }
365 | pp_expr LOGAND pp_expr { $$ = new_int($1 && $3 ? (*$1 && *$3) : 0); if($1) free($1); if($3) free($3); }
366 | pp_expr '+' pp_expr { $$ = new_int($1 && $3 ? (*$1 + *$3) : 0); if($1) free($1); if($3) free($3); }
367 | pp_expr '-' pp_expr { $$ = new_int($1 && $3 ? (*$1 - *$3) : 0); if($1) free($1); if($3) free($3); }
368 | pp_expr '^' pp_expr { $$ = new_int($1 && $3 ? (*$1 ^ *$3) : 0); if($1) free($1); if($3) free($3); }
369 | pp_expr EQ pp_expr { $$ = new_int($1 && $3 ? (*$1 == *$3) : 0); if($1) free($1); if($3) free($3); }
370 | pp_expr NE pp_expr { $$ = new_int($1 && $3 ? (*$1 != *$3) : 0); if($1) free($1); if($3) free($3); }
371 | pp_expr '<' pp_expr { $$ = new_int($1 && $3 ? (*$1 < *$3) : 0); if($1) free($1); if($3) free($3); }
372 | pp_expr '>' pp_expr { $$ = new_int($1 && $3 ? (*$1 > *$3) : 0); if($1) free($1); if($3) free($3); }
373 | pp_expr LTE pp_expr { $$ = new_int($1 && $3 ? (*$1 <= *$3) : 0); if($1) free($1); if($3) free($3); }
374 | pp_expr GTE pp_expr { $$ = new_int($1 && $3 ? (*$1 >= *$3) : 0); if($1) free($1); if($3) free($3); }
375 | '~' pp_expr { $$ = $2; if($2) *$2 = ~(*$2); }
376 | '+' pp_expr { $$ = $2; }
377 | '-' pp_expr { $$ = $2; if($2) *$2 = -(*$2); }
378 | '!' pp_expr { $$ = $2; if($2) *$2 = !(*$2); }
379 | '(' pp_expr ')' { $$ = $2; }
380 ;
381
382pp_constant
383 : any_num { $$ = new_int($1); }
384 | IDENT { $$ = NULL; }
385 | tDEFINED IDENT { $$ = new_int(pp_lookup($2->str.cstr) != NULL); }
386 | tDEFINED '(' IDENT ')' { $$ = new_int(pp_lookup($3->str.cstr) != NULL); }
387 ;
388
389/* C ignore stuff */
390cjunk : tTYPEDEF { strip_til_semicolon(); }
391 | tEXTERN { strip_til_semicolon(); }
392 | IDENT IDENT { strip_til_semicolon(); }
393 | IDENT '(' { strip_til_parenthesis(); }
394 | IDENT '*' { strip_til_semicolon(); }
395 ;
396
397/* Parse top level resource definitions etc. */
398resource
399 : nameid resource_definition {
400 $$ = $2;
401 if($$)
402 {
403 $$->name = $1;
404 if($1->type == name_ord)
405 {
406 chat("Got %s (%d)",get_typename($2),$1->name.i_name);
407 }
408 else if($1->type == name_str)
409 {
410 chat("Got %s (%s)",get_typename($2),$1->name.s_name->str.cstr);
411 }
412 }
413 }
414 | stringtable {
415 /* Don't do anything, stringtables are converted to
416 * resource_t structures when we are finished parsing and
417 * the final rule of the parser is reduced (see above)
418 */
419 $$ = NULL;
420 chat("Got STRINGTABLE");
421 }
422 | opt_language {
423 if(!win32)
424 yywarning("LANGUAGE not supported in 16-bit mode");
425 if(currentlanguage)
426 free(currentlanguage);
427 currentlanguage = $1;
428 $$ = NULL;
429 }
430 ;
431
432/*
433 * Get a valid name/id
434 */
435nameid : expr {
436 $$ = new_name_id();
437 $$->type = name_ord;
438 $$->name.i_name = $1;
439 want_rscname = 0;
440 }
441 | IDENT {
442 $$ = new_name_id();
443 $$->type = name_str;
444 $$->name.s_name = $1;
445 want_rscname = 0;
446 }
447 ;
448
449/*
450 * Extra string recognition for CLASS statement in dialogs
451 */
452nameid_s: nameid { $$ = $1; }
453 | tSTRING {
454 $$ = new_name_id();
455 $$->type = name_str;
456 $$->name.s_name = $1;
457 want_rscname = 0;
458 }
459 ;
460
461/* get the value for a single resource*/
462resource_definition
463 : accelerators { $$ = new_resource(res_acc, $1, $1->memopt, $1->lvc.language); }
464 | bitmap { $$ = new_resource(res_bmp, $1, $1->memopt, dup_language(currentlanguage)); }
465 | cursor {
466 resource_t *rsc;
467 cursor_t *cur;
468 $$ = rsc = new_resource(res_curg, $1, $1->memopt, dup_language(currentlanguage));
469 for(cur = $1->cursorlist; cur; cur = cur->next)
470 {
471 rsc->prev = new_resource(res_cur, cur, $1->memopt, dup_language(currentlanguage));
472 rsc->prev->next = rsc;
473 rsc = rsc->prev;
474 rsc->name = new_name_id();
475 rsc->name->type = name_ord;
476 rsc->name->name.i_name = cur->id;
477 }
478 }
479 | dialog { $$ = new_resource(res_dlg, $1, $1->memopt, $1->lvc.language); }
480 | dialogex {
481 if(win32)
482 $$ = new_resource(res_dlgex, $1, $1->memopt, $1->lvc.language);
483 else
484 $$ = NULL;
485 }
486 | dlginit { $$ = new_resource(res_dlginit, $1, $1->memopt, $1->lvc.language); }
487 | font { $$ = new_resource(res_fnt, $1, $1->memopt, dup_language(currentlanguage)); }
488 | icon {
489 resource_t *rsc;
490 icon_t *ico;
491 $$ = rsc = new_resource(res_icog, $1, $1->memopt, dup_language(currentlanguage));
492 for(ico = $1->iconlist; ico; ico = ico->next)
493 {
494 rsc->prev = new_resource(res_ico, ico, $1->memopt, dup_language(currentlanguage));
495 rsc->prev->next = rsc;
496 rsc = rsc->prev;
497 rsc->name = new_name_id();
498 rsc->name->type = name_ord;
499 rsc->name->name.i_name = ico->id;
500 }
501 }
502 | menu { $$ = new_resource(res_men, $1, $1->memopt, $1->lvc.language); }
503 | menuex {
504 if(win32)
505 $$ = new_resource(res_menex, $1, $1->memopt, $1->lvc.language);
506 else
507 $$ = NULL;
508 }
509 | messagetable { $$ = new_resource(res_msg, $1, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, dup_language(currentlanguage)); }
510 | rcdata { $$ = new_resource(res_rdt, $1, $1->memopt, $1->lvc.language); }
511 | toolbar { $$ = new_resource(res_toolbar, $1, $1->memopt, $1->lvc.language); }
512 | userres { $$ = new_resource(res_usr, $1, $1->memopt, dup_language(currentlanguage)); }
513 | versioninfo { $$ = new_resource(res_ver, $1, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, dup_language(currentlanguage)); }
514 ;
515
516/* ------------------------------ Bitmap ------------------------------ */
517bitmap : tBITMAP loadmemopts FILENAME { $$ = new_bitmap(load_file($3), $2); }
518 | tBITMAP loadmemopts raw_data { $$ = new_bitmap($3, $2); }
519 ;
520
521/* ------------------------------ Cursor ------------------------------ */
522cursor : CURSOR loadmemopts FILENAME { $$ = new_cursor_group(load_file($3), $2); }
523 | CURSOR loadmemopts raw_data { $$ = new_cursor_group($3, $2); }
524 ;
525
526/* ------------------------------ Font ------------------------------ */
527/* FIXME: Should we allow raw_data here? */
528font : FONT loadmemopts FILENAME { $$ = new_font(load_file($3), $2); }
529 ;
530
531/* ------------------------------ Icon ------------------------------ */
532icon : ICON loadmemopts FILENAME { $$ = new_icon_group(load_file($3), $2); }
533 | ICON loadmemopts raw_data { $$ = new_icon_group($3, $2); }
534 ;
535
536/* ------------------------------ MessageTable ------------------------------ */
537/* It might be interesting to implement the MS Message compiler here as well
538 * to get everything in one source. Might be a future project.
539 */
540messagetable
541 : MESSAGETABLE FILENAME {
542 if(!win32)
543 yywarning("MESSAGETABLE not supported in 16-bit mode");
544 $$ = new_messagetable(load_file($2));
545 }
546 ;
547
548/* ------------------------------ RCData ------------------------------ */
549rcdata : RCDATA loadmemopts opt_lvc raw_data {
550 $$ = new_rcdata($4, $2);
551 if($3)
552 {
553 $$->lvc = *($3);
554 free($3);
555 }
556 if(!$$->lvc.language)
557 $$->lvc.language = dup_language(currentlanguage);
558 }
559 ;
560
561/* ------------------------------ DLGINIT ------------------------------ */
562dlginit : DLGINIT loadmemopts opt_lvc raw_data {
563 $$ = new_dlginit($4, $2);
564 if($3)
565 {
566 $$->lvc = *($3);
567 free($3);
568 }
569 if(!$$->lvc.language)
570 $$->lvc.language = dup_language(currentlanguage);
571 }
572 ;
573
574/* ------------------------------ UserType ------------------------------ */
575userres : usertype loadmemopts FILENAME { $$ = new_user($1, load_file($3), $2); }
576 | usertype loadmemopts raw_data { $$ = new_user($1, $3, $2); }
577 ;
578
579/* NOTE: This here is an exception where I do not allow an expression.
580 * Reason for this is that it is not possible to set the 'yywf' condition
581 * for flex if loadmemopts is empty. Reading an expression requires a
582 * lookahead to determine its end. In this case here, that would mean that
583 * the filename has been read as IDENT or tSTRING, which is incorrect.
584 * Note also that IDENT cannot be used as a file-name because it is lacking
585 * the '.'.
586 */
587
588/* I also allow string identifiers as classtypes. Not MS implemented, but
589 * seems to be reasonable to implement.
590 */
591/* Allowing anything else than NUMBER makes it very hard to get rid of
592 * prototypes. So, I remove IDENT to be able to get prototypes out of the
593 * world.
594 */
595usertype: NUMBER {
596 $$ = new_name_id();
597 $$->type = name_ord;
598 $$->name.i_name = $1;
599 set_yywf();
600 }
601/* | IDENT {
602 $$ = new_name_id();
603 $$->type = name_str;
604 $$->name.s_name = $1;
605 set_yywf();
606 }
607*/ | tSTRING {
608 $$ = new_name_id();
609 $$->type = name_str;
610 $$->name.s_name = $1;
611 set_yywf();
612 }
613 ;
614
615/* ------------------------------ Accelerator ------------------------------ */
616accelerators
617 : ACCELERATORS loadmemopts opt_lvc tBEGIN events tEND {
618 $$ = new_accelerator();
619 if($2)
620 {
621 $$->memopt = *($2);
622 free($2);
623 }
624 else
625 {
626 $$->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE;
627 }
628 if(!$5)
629 yyerror("Accelerator table must have at least one entry");
630 $$->events = get_event_head($5);
631 if($3)
632 {
633 $$->lvc = *($3);
634 free($3);
635 }
636 if(!$$->lvc.language)
637 $$->lvc.language = dup_language(currentlanguage);
638 }
639 ;
640
641events : /* Empty */ { $$=NULL; }
642 | events tSTRING ',' expr acc_opt { $$=add_string_event($2, $4, $5, $1); }
643 | events expr ',' expr acc_opt { $$=add_event($2, $4, $5, $1); }
644 ;
645
646acc_opt : /* Empty */ { $$=0; }
647 | acc_opt ',' NOINVERT { $$=$1 | WRC_AF_NOINVERT; }
648 | acc_opt ',' SHIFT { $$=$1 | WRC_AF_SHIFT; }
649 | acc_opt ',' CONTROL { $$=$1 | WRC_AF_CONTROL; }
650 | acc_opt ',' ALT { $$=$1 | WRC_AF_ALT; }
651 | acc_opt ',' ASCII { $$=$1 | WRC_AF_ASCII; }
652 | acc_opt ',' VIRTKEY { $$=$1 | WRC_AF_VIRTKEY; }
653 ;
654
655/* ------------------------------ Dialog ------------------------------ */
656/* FIXME: Support EXSTYLE in the dialog line itself */
657dialog : DIALOG loadmemopts expr ',' expr ',' expr ',' expr dlg_attributes
658 tBEGIN ctrls tEND {
659 if($2)
660 {
661 $10->memopt = *($2);
662 free($2);
663 }
664 else
665 $10->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
666 $10->x = $3;
667 $10->y = $5;
668 $10->width = $7;
669 $10->height = $9;
670 $10->controls = get_control_head($12);
671 $$ = $10;
672 if(!$$->gotstyle)
673 {
674 $$->style = WS_POPUP;
675 $$->gotstyle = TRUE;
676 }
677 if($$->title)
678 $$->style |= WS_CAPTION;
679 if($$->font)
680 $$->style |= DS_SETFONT;
681 indialog = FALSE;
682 if(!$$->lvc.language)
683 $$->lvc.language = dup_language(currentlanguage);
684 }
685 ;
686
687dlg_attributes
688 : /* Empty */ { $$=new_dialog(); }
689 | dlg_attributes STYLE expr { $$=dialog_style($3,$1); }
690 | dlg_attributes EXSTYLE expr { $$=dialog_exstyle($3,$1); }
691 | dlg_attributes CAPTION tSTRING { $$=dialog_caption($3,$1); }
692 | dlg_attributes opt_font { $$=dialog_font($2,$1); }
693 | dlg_attributes CLASS nameid_s { $$=dialog_class($3,$1); }
694 | dlg_attributes MENU nameid { $$=dialog_menu($3,$1); }
695 | dlg_attributes opt_language { $$=dialog_language($2,$1); }
696 | dlg_attributes opt_characts { $$=dialog_characteristics($2,$1); }
697 | dlg_attributes opt_version { $$=dialog_version($2,$1); }
698 ;
699
700ctrls : /* Empty */ { $$ = NULL; }
701 | ctrls CONTROL gen_ctrl { $$=ins_ctrl(-1, 0, $3, $1); }
702 | ctrls EDITTEXT ctrl_desc { $$=ins_ctrl(CT_EDIT, 0, $3, $1); }
703 | ctrls LISTBOX ctrl_desc { $$=ins_ctrl(CT_LISTBOX, 0, $3, $1); }
704 | ctrls COMBOBOX ctrl_desc { $$=ins_ctrl(CT_COMBOBOX, 0, $3, $1); }
705 | ctrls SCROLLBAR ctrl_desc { $$=ins_ctrl(CT_SCROLLBAR, 0, $3, $1); }
706 | ctrls CHECKBOX lab_ctrl { $$=ins_ctrl(CT_BUTTON, BS_CHECKBOX, $3, $1); }
707 | ctrls DEFPUSHBUTTON lab_ctrl { $$=ins_ctrl(CT_BUTTON, BS_DEFPUSHBUTTON, $3, $1); }
708 | ctrls GROUPBOX lab_ctrl { $$=ins_ctrl(CT_BUTTON, BS_GROUPBOX, $3, $1);}
709 | ctrls PUSHBUTTON lab_ctrl { $$=ins_ctrl(CT_BUTTON, BS_PUSHBUTTON, $3, $1); }
710/* | ctrls PUSHBOX lab_ctrl { $$=ins_ctrl(CT_BUTTON, BS_PUSHBOX, $3, $1); } */
711 | ctrls RADIOBUTTON lab_ctrl { $$=ins_ctrl(CT_BUTTON, BS_RADIOBUTTON, $3, $1); }
712 | ctrls AUTO3STATE lab_ctrl { $$=ins_ctrl(CT_BUTTON, BS_AUTO3STATE, $3, $1); }
713 | ctrls STATE3 lab_ctrl { $$=ins_ctrl(CT_BUTTON, BS_3STATE, $3, $1); }
714 | ctrls AUTOCHECKBOX lab_ctrl { $$=ins_ctrl(CT_BUTTON, BS_AUTOCHECKBOX, $3, $1); }
715 | ctrls AUTORADIOBUTTON lab_ctrl { $$=ins_ctrl(CT_BUTTON, BS_AUTORADIOBUTTON, $3, $1); }
716 | ctrls LTEXT lab_ctrl { $$=ins_ctrl(CT_STATIC, SS_LEFT, $3, $1); }
717 | ctrls CTEXT lab_ctrl { $$=ins_ctrl(CT_STATIC, SS_CENTER, $3, $1); }
718 | ctrls RTEXT lab_ctrl { $$=ins_ctrl(CT_STATIC, SS_RIGHT, $3, $1); }
719 /* special treatment for icons, as the extent is optional */
720 | ctrls ICON nameid_s ',' expr ',' expr ',' expr iconinfo {
721 $10->title = $3;
722 $10->id = $5;
723 $10->x = $7;
724 $10->y = $9;
725 $$ = ins_ctrl(CT_STATIC, SS_ICON, $10, $1);
726 }
727 ;
728
729lab_ctrl
730 : tSTRING ',' expr ',' expr ',' expr ',' expr ',' expr optional_style {
731 $$=new_control();
732 $$->title = new_name_id();
733 $$->title->type = name_str;
734 $$->title->name.s_name = $1;
735 $$->id = $3;
736 $$->x = $5;
737 $$->y = $7;
738 $$->width = $9;
739 $$->height = $11;
740 if($12)
741 {
742 $$->style = *($12);
743 $$->gotstyle = TRUE;
744 free($12);
745 }
746 }
747 ;
748
749ctrl_desc
750 : expr ',' expr ',' expr ',' expr ',' expr optional_style {
751 $$ = new_control();
752 $$->id = $1;
753 $$->x = $3;
754 $$->y = $5;
755 $$->width = $7;
756 $$->height = $9;
757 if($10)
758 {
759 $$->style = *($10);
760 $$->gotstyle = TRUE;
761 free($10);
762 }
763 }
764 ;
765
766iconinfo: /* Empty */
767 { $$ = new_control(); }
768
769 | ',' expr ',' expr {
770 $$ = new_control();
771 $$->width = $2;
772 $$->height = $4;
773 }
774 | ',' expr ',' expr ',' expr {
775 $$ = new_control();
776 $$->width = $2;
777 $$->height = $4;
778 $$->style = $6;
779 $$->gotstyle = TRUE;
780 }
781 | ',' expr ',' expr ',' expr ',' expr {
782 $$ = new_control();
783 $$->width = $2;
784 $$->height = $4;
785 $$->style = $6;
786 $$->gotstyle = TRUE;
787 $$->exstyle = $8;
788 $$->gotexstyle = TRUE;
789 }
790 ;
791
792gen_ctrl: nameid_s ',' expr ',' ctlclass ',' expr ',' expr ',' expr ',' expr ',' expr ',' expr {
793 $$=new_control();
794 $$->title = $1;
795 $$->id = $3;
796 $$->ctlclass = convert_ctlclass($5);
797 $$->style = $7;
798 $$->gotstyle = TRUE;
799 $$->x = $9;
800 $$->y = $11;
801 $$->width = $13;
802 $$->height = $15;
803 $$->exstyle = $17;
804 $$->gotexstyle = TRUE;
805 }
806 | nameid_s ',' expr ',' ctlclass ',' expr ',' expr ',' expr ',' expr ',' expr {
807 $$=new_control();
808 $$->title = $1;
809 $$->id = $3;
810 $$->ctlclass = convert_ctlclass($5);
811 $$->style = $7;
812 $$->gotstyle = TRUE;
813 $$->x = $9;
814 $$->y = $11;
815 $$->width = $13;
816 $$->height = $15;
817 }
818 ;
819
820opt_font
821 : FONT expr ',' tSTRING { $$ = new_font_id($2, $4, 0, 0); }
822 ;
823
824optional_style /* Abbused once to get optional ExStyle */
825 : /* Empty */ { $$ = NULL; }
826 | ',' expr { $$ = new_int($2); }
827 ;
828
829optional_style_pair
830 : /* Enpty */ { $$ = NULL; }
831 | ',' expr { $$ = new_style_pair($2, 0); }
832 | ',' expr ',' expr { $$ = new_style_pair($2, $4); }
833 ;
834
835ctlclass
836 : expr {
837 $$ = new_name_id();
838 $$->type = name_ord;
839 $$->name.i_name = $1;
840 }
841 | tSTRING {
842 $$ = new_name_id();
843 $$->type = name_str;
844 $$->name.s_name = $1;
845 }
846 ;
847
848/* ------------------------------ DialogEx ------------------------------ */
849dialogex: DIALOGEX loadmemopts expr ',' expr ',' expr ',' expr helpid dlgex_attribs
850 tBEGIN exctrls tEND {
851 if(!win32)
852 yywarning("DIALOGEX not supported in 16-bit mode");
853 if($2)
854 {
855 $11->memopt = *($2);
856 free($2);
857 }
858 else
859 $11->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
860 $11->x = $3;
861 $11->y = $5;
862 $11->width = $7;
863 $11->height = $9;
864 if($10)
865 {
866 $11->helpid = *($10);
867 $11->gothelpid = TRUE;
868 free($10);
869 }
870 $11->controls = get_control_head($13);
871 $$ = $11;
872 if(!$$->gotstyle)
873 {
874 $$->style = WS_POPUP;
875 $$->gotstyle = TRUE;
876 }
877 if($$->title)
878 $$->style |= WS_CAPTION;
879 if($$->font)
880 $$->style |= DS_SETFONT;
881 indialog = FALSE;
882 if(!$$->lvc.language)
883 $$->lvc.language = dup_language(currentlanguage);
884 }
885 ;
886
887dlgex_attribs
888 : /* Empty */ { $$=new_dialogex(); }
889 | dlgex_attribs STYLE expr { $$=dialogex_style($3,$1); }
890 | dlgex_attribs EXSTYLE expr { $$=dialogex_exstyle($3,$1); }
891 | dlgex_attribs CAPTION tSTRING { $$=dialogex_caption($3,$1); }
892 | dlgex_attribs opt_font { $$=dialogex_font($2,$1); }
893 | dlgex_attribs opt_exfont { $$=dialogex_font($2,$1); }
894 | dlgex_attribs CLASS nameid_s { $$=dialogex_class($3,$1); }
895 | dlgex_attribs MENU nameid { $$=dialogex_menu($3,$1); }
896 | dlgex_attribs opt_language { $$=dialogex_language($2,$1); }
897 | dlgex_attribs opt_characts { $$=dialogex_characteristics($2,$1); }
898 | dlgex_attribs opt_version { $$=dialogex_version($2,$1); }
899 ;
900
901exctrls : /* Empty */ { $$ = NULL; }
902 | exctrls CONTROL gen_exctrl { $$=ins_ctrl(-1, 0, $3, $1); }
903 | exctrls EDITTEXT exctrl_desc { $$=ins_ctrl(CT_EDIT, 0, $3, $1); }
904 | exctrls LISTBOX exctrl_desc { $$=ins_ctrl(CT_LISTBOX, 0, $3, $1); }
905 | exctrls COMBOBOX exctrl_desc { $$=ins_ctrl(CT_COMBOBOX, 0, $3, $1); }
906 | exctrls SCROLLBAR exctrl_desc { $$=ins_ctrl(CT_SCROLLBAR, 0, $3, $1); }
907 | exctrls CHECKBOX lab_exctrl { $$=ins_ctrl(CT_BUTTON, BS_CHECKBOX, $3, $1); }
908 | exctrls DEFPUSHBUTTON lab_exctrl { $$=ins_ctrl(CT_BUTTON, BS_DEFPUSHBUTTON, $3, $1); }
909 | exctrls GROUPBOX lab_exctrl { $$=ins_ctrl(CT_BUTTON, BS_GROUPBOX, $3, $1);}
910 | exctrls PUSHBUTTON lab_exctrl { $$=ins_ctrl(CT_BUTTON, BS_PUSHBUTTON, $3, $1); }
911/* | exctrls PUSHBOX lab_exctrl { $$=ins_ctrl(CT_BUTTON, BS_PUSHBOX, $3, $1); } */
912 | exctrls RADIOBUTTON lab_exctrl { $$=ins_ctrl(CT_BUTTON, BS_RADIOBUTTON, $3, $1); }
913 | exctrls AUTO3STATE lab_exctrl { $$=ins_ctrl(CT_BUTTON, BS_AUTO3STATE, $3, $1); }
914 | exctrls STATE3 lab_exctrl { $$=ins_ctrl(CT_BUTTON, BS_3STATE, $3, $1); }
915 | exctrls AUTOCHECKBOX lab_exctrl { $$=ins_ctrl(CT_BUTTON, BS_AUTOCHECKBOX, $3, $1); }
916 | exctrls AUTORADIOBUTTON lab_exctrl { $$=ins_ctrl(CT_BUTTON, BS_AUTORADIOBUTTON, $3, $1); }
917 | exctrls LTEXT lab_exctrl { $$=ins_ctrl(CT_STATIC, SS_LEFT, $3, $1); }
918 | exctrls CTEXT lab_exctrl { $$=ins_ctrl(CT_STATIC, SS_CENTER, $3, $1); }
919 | exctrls RTEXT lab_exctrl { $$=ins_ctrl(CT_STATIC, SS_RIGHT, $3, $1); }
920 /* special treatment for icons, as the extent is optional */
921 | exctrls ICON nameid_s ',' expr ',' expr ',' expr iconinfo {
922 $10->title = $3;
923 $10->id = $5;
924 $10->x = $7;
925 $10->y = $9;
926 $$ = ins_ctrl(CT_STATIC, SS_ICON, $10, $1);
927 }
928 ;
929
930gen_exctrl
931 : nameid_s ',' expr ',' ctlclass ',' expr ',' expr ',' expr ',' expr ','
932 expr ',' e_expr helpid opt_data {
933 $$=new_control();
934 $$->title = $1;
935 $$->id = $3;
936 $$->ctlclass = convert_ctlclass($5);
937 $$->style = $7;
938 $$->gotstyle = TRUE;
939 $$->x = $9;
940 $$->y = $11;
941 $$->width = $13;
942 $$->height = $15;
943 if($17)
944 {
945 $$->exstyle = *($17);
946 $$->gotexstyle = TRUE;
947 free($17);
948 }
949 if($18)
950 {
951 $$->helpid = *($18);
952 $$->gothelpid = TRUE;
953 free($18);
954 }
955 $$->extra = $19;
956 }
957 | nameid_s ',' expr ',' ctlclass ',' expr ',' expr ',' expr ',' expr ',' expr opt_data {
958 $$=new_control();
959 $$->title = $1;
960 $$->id = $3;
961 $$->style = $7;
962 $$->gotstyle = TRUE;
963 $$->ctlclass = convert_ctlclass($5);
964 $$->x = $9;
965 $$->y = $11;
966 $$->width = $13;
967 $$->height = $15;
968 $$->extra = $16;
969 }
970 ;
971
972lab_exctrl
973 : tSTRING ',' expr ',' expr ',' expr ',' expr ',' expr optional_style_pair opt_data {
974 $$=new_control();
975 $$->title = new_name_id();
976 $$->title->type = name_str;
977 $$->title->name.s_name = $1;
978 $$->id = $3;
979 $$->x = $5;
980 $$->y = $7;
981 $$->width = $9;
982 $$->height = $11;
983 if($12)
984 {
985 $$->style = $12->style;
986 $$->gotstyle = TRUE;
987
988 if ($12->exstyle)
989 {
990 $$->exstyle = $12->exstyle;
991 $$->gotexstyle = TRUE;
992 }
993 free($12);
994 }
995
996 $$->extra = $13;
997 }
998 ;
999
1000exctrl_desc
1001 : expr ',' expr ',' expr ',' expr ',' expr optional_style_pair opt_data {
1002 $$ = new_control();
1003 $$->id = $1;
1004 $$->x = $3;
1005 $$->y = $5;
1006 $$->width = $7;
1007 $$->height = $9;
1008 if($10)
1009 {
1010 $$->style = $10->style;
1011 $$->gotstyle = TRUE;
1012
1013 if ($10->exstyle)
1014 {
1015 $$->exstyle = $10->exstyle;
1016 $$->gotexstyle = TRUE;
1017 }
1018 free($10);
1019 }
1020 $$->extra = $11;
1021 }
1022 ;
1023
1024opt_data: /* Empty */ { $$ = NULL; }
1025 | raw_data { $$ = $1; }
1026 ;
1027
1028helpid : /* Empty */ { $$ = NULL; }
1029 | ',' expr { $$ = new_int($2); }
1030 ;
1031
1032opt_exfont
1033 : FONT expr ',' tSTRING ',' expr ',' expr opt_expr { $$ = new_font_id($2, $4, $6, $8); }
1034 ;
1035
1036/*
1037 * FIXME: This odd expression is here to nullify an extra token found
1038 * in some appstudio produced resources which appear to do nothing.
1039 */
1040opt_expr: /* Empty */ { $$ = NULL; }
1041 | ',' expr { $$ = NULL; }
1042 ;
1043
1044/* ------------------------------ Menu ------------------------------ */
1045menu : MENU loadmemopts opt_lvc menu_body {
1046 if(!$4)
1047 yyerror("Menu must contain items");
1048 $$ = new_menu();
1049 if($2)
1050 {
1051 $$->memopt = *($2);
1052 free($2);
1053 }
1054 else
1055 $$->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
1056 $$->items = get_item_head($4);
1057 if($3)
1058 {
1059 $$->lvc = *($3);
1060 free($3);
1061 }
1062 if(!$$->lvc.language)
1063 $$->lvc.language = dup_language(currentlanguage);
1064 }
1065 ;
1066
1067menu_body
1068 : tBEGIN item_definitions tEND { $$ = $2; }
1069 ;
1070
1071item_definitions
1072 : /* Empty */ {$$ = NULL;}
1073 | item_definitions MENUITEM tSTRING ',' expr item_options {
1074 $$=new_menu_item();
1075 $$->prev = $1;
1076 if($1)
1077 $1->next = $$;
1078 $$->id = $5;
1079 $$->state = $6;
1080 $$->name = $3;
1081 }
1082 | item_definitions MENUITEM SEPARATOR {
1083 $$=new_menu_item();
1084 $$->prev = $1;
1085 if($1)
1086 $1->next = $$;
1087 }
1088 | item_definitions POPUP tSTRING item_options menu_body {
1089 $$ = new_menu_item();
1090 $$->prev = $1;
1091 if($1)
1092 $1->next = $$;
1093 $$->popup = get_item_head($5);
1094 $$->name = $3;
1095 }
1096 ;
1097
1098/* NOTE: item_options is right recursive because it would introduce
1099 * a shift/reduce conflict on ',' in itemex_options due to the
1100 * empty rule here. The parser is now forced to look beyond the ','
1101 * before reducing (force shift).
1102 * Right recursion here is not a problem because we cannot expect
1103 * more than 7 parserstack places to be occupied while parsing this
1104 * (who would want to specify a MF_x flag twice?).
1105 */
1106item_options
1107 : /* Empty */ { $$ = 0; }
1108 | ',' CHECKED item_options { $$ = $3 | MF_CHECKED; }
1109 | ',' GRAYED item_options { $$ = $3 | MF_GRAYED; }
1110 | ',' HELP item_options { $$ = $3 | MF_HELP; }
1111 | ',' INACTIVE item_options { $$ = $3 | MF_DISABLED; }
1112 | ',' MENUBARBREAK item_options { $$ = $3 | MF_MENUBARBREAK; }
1113 | ',' MENUBREAK item_options { $$ = $3 | MF_MENUBREAK; }
1114 ;
1115
1116/* ------------------------------ MenuEx ------------------------------ */
1117menuex : MENUEX loadmemopts opt_lvc menuex_body {
1118 if(!win32)
1119 yywarning("MENUEX not supported in 16-bit mode");
1120 if(!$4)
1121 yyerror("MenuEx must contain items");
1122 $$ = new_menuex();
1123 if($2)
1124 {
1125 $$->memopt = *($2);
1126 free($2);
1127 }
1128 else
1129 $$->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE;
1130 $$->items = get_itemex_head($4);
1131 if($3)
1132 {
1133 $$->lvc = *($3);
1134 free($3);
1135 }
1136 if(!$$->lvc.language)
1137 $$->lvc.language = dup_language(currentlanguage);
1138 }
1139 ;
1140
1141menuex_body
1142 : tBEGIN itemex_definitions tEND { $$ = $2; }
1143 ;
1144
1145itemex_definitions
1146 : /* Empty */ {$$ = NULL; }
1147 | itemex_definitions MENUITEM tSTRING itemex_options {
1148 $$ = new_menuex_item();
1149 $$->prev = $1;
1150 if($1)
1151 $1->next = $$;
1152 $$->name = $3;
1153 $$->id = $4->id;
1154 $$->type = $4->type;
1155 $$->state = $4->state;
1156 $$->helpid = $4->helpid;
1157 $$->gotid = $4->gotid;
1158 $$->gottype = $4->gottype;
1159 $$->gotstate = $4->gotstate;
1160 $$->gothelpid = $4->gothelpid;
1161 free($4);
1162 }
1163 | itemex_definitions MENUITEM SEPARATOR {
1164 $$ = new_menuex_item();
1165 $$->prev = $1;
1166 if($1)
1167 $1->next = $$;
1168 }
1169 | itemex_definitions POPUP tSTRING itemex_p_options menuex_body {
1170 $$ = new_menuex_item();
1171 $$->prev = $1;
1172 if($1)
1173 $1->next = $$;
1174 $$->popup = get_itemex_head($5);
1175 $$->name = $3;
1176 $$->id = $4->id;
1177 $$->type = $4->type;
1178 $$->state = $4->state;
1179 $$->helpid = $4->helpid;
1180 $$->gotid = $4->gotid;
1181 $$->gottype = $4->gottype;
1182 $$->gotstate = $4->gotstate;
1183 $$->gothelpid = $4->gothelpid;
1184 free($4);
1185 }
1186 ;
1187
1188itemex_options
1189 : /* Empty */ { $$ = new_itemex_opt(0, 0, 0, 0); }
1190 | ',' expr {
1191 $$ = new_itemex_opt($2, 0, 0, 0);
1192 $$->gotid = TRUE;
1193 }
1194 | ',' e_expr ',' e_expr item_options {
1195 $$ = new_itemex_opt($2 ? *($2) : 0, $4 ? *($4) : 0, $5, 0);
1196 $$->gotid = TRUE;
1197 $$->gottype = TRUE;
1198 $$->gotstate = TRUE;
1199 if($2) free($2);
1200 if($4) free($4);
1201 }
1202 | ',' e_expr ',' e_expr ',' expr {
1203 $$ = new_itemex_opt($2 ? *($2) : 0, $4 ? *($4) : 0, $6, 0);
1204 $$->gotid = TRUE;
1205 $$->gottype = TRUE;
1206 $$->gotstate = TRUE;
1207 if($2) free($2);
1208 if($4) free($4);
1209 }
1210 ;
1211
1212itemex_p_options
1213 : /* Empty */ { $$ = new_itemex_opt(0, 0, 0, 0); }
1214 | ',' expr {
1215 $$ = new_itemex_opt($2, 0, 0, 0);
1216 $$->gotid = TRUE;
1217 }
1218 | ',' e_expr ',' expr {
1219 $$ = new_itemex_opt($2 ? *($2) : 0, $4, 0, 0);
1220 if($2) free($2);
1221 $$->gotid = TRUE;
1222 $$->gottype = TRUE;
1223 }
1224 | ',' e_expr ',' e_expr ',' expr {
1225 $$ = new_itemex_opt($2 ? *($2) : 0, $4 ? *($4) : 0, $6, 0);
1226 if($2) free($2);
1227 if($4) free($4);
1228 $$->gotid = TRUE;
1229 $$->gottype = TRUE;
1230 $$->gotstate = TRUE;
1231 }
1232 | ',' e_expr ',' e_expr ',' e_expr ',' expr {
1233 $$ = new_itemex_opt($2 ? *($2) : 0, $4 ? *($4) : 0, $6 ? *($6) : 0, $8);
1234 if($2) free($2);
1235 if($4) free($4);
1236 if($6) free($6);
1237 $$->gotid = TRUE;
1238 $$->gottype = TRUE;
1239 $$->gotstate = TRUE;
1240 $$->gothelpid = TRUE;
1241 }
1242 ;
1243
1244/* ------------------------------ StringTable ------------------------------ */
1245/* Stringtables are parsed differently than other resources because their
1246 * layout is substantially different from other resources.
1247 * The table is parsed through a _global_ variable 'tagstt' which holds the
1248 * current stringtable descriptor (stringtable_t *) and 'sttres' that holds a
1249 * list of stringtables of different languages.
1250 */
1251stringtable
1252 : stt_head tBEGIN strings tEND {
1253 if(!$3)
1254 {
1255 yyerror("Stringtable must have at least one entry");
1256 }
1257 else
1258 {
1259 stringtable_t *stt;
1260 /* Check if we added to a language table or created
1261 * a new one.
1262 */
1263 for(stt = sttres; stt; stt = stt->next)
1264 {
1265 if(stt == tagstt)
1266 break;
1267 }
1268 if(!stt)
1269 {
1270 /* It is a new one */
1271 if(sttres)
1272 {
1273 sttres->prev = tagstt;
1274 tagstt->next = sttres;
1275 sttres = tagstt;
1276 }
1277 else
1278 sttres = tagstt;
1279 }
1280 /* Else were done */
1281 }
1282 if(tagstt_memopt)
1283 {
1284 free(tagstt_memopt);
1285 tagstt_memopt = NULL;
1286 }
1287
1288 $$ = tagstt;
1289 }
1290 ;
1291
1292/* This is to get the language of the currently parsed stringtable */
1293stt_head: STRINGTABLE loadmemopts opt_lvc {
1294 if((tagstt = find_stringtable($3)) == NULL)
1295 tagstt = new_stringtable($3);
1296 tagstt_memopt = $2;
1297 tagstt_version = $3->version;
1298 tagstt_characts = $3->characts;
1299 if($3)
1300 free($3);
1301 }
1302 ;
1303
1304strings : /* Empty */ { $$ = NULL; }
1305 | strings expr opt_comma tSTRING {
1306 int i;
1307 assert(tagstt != NULL);
1308 /* Search for the ID */
1309 for(i = 0; i < tagstt->nentries; i++)
1310 {
1311 if(tagstt->entries[i].id == $2)
1312 yyerror("Stringtable ID %d already in use", $2);
1313 }
1314 /* If we get here, then we have a new unique entry */
1315 tagstt->nentries++;
1316 tagstt->entries = xrealloc(tagstt->entries, sizeof(tagstt->entries[0]) * tagstt->nentries);
1317 tagstt->entries[tagstt->nentries-1].id = $2;
1318 tagstt->entries[tagstt->nentries-1].str = $4;
1319 if(tagstt_memopt)
1320 tagstt->entries[tagstt->nentries-1].memopt = *tagstt_memopt;
1321 else
1322 tagstt->entries[tagstt->nentries-1].memopt = WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE | WRC_MO_PURE;
1323 tagstt->entries[tagstt->nentries-1].version = tagstt_version;
1324 tagstt->entries[tagstt->nentries-1].characts = tagstt_characts;
1325
1326 if(!win32 && $4->size > 254)
1327 yyerror("Stringtable entry more than 254 characters");
1328 if(win32 && $4->size > 65534) /* Hmm..., does this happen? */
1329 yyerror("Stringtable entry more than 65534 characters (probably something else that went wrong)");
1330 $$ = tagstt;
1331 }
1332 ;
1333
1334opt_comma /* There seem to be two ways to specify a stringtable... */
1335 : /* Empty */
1336 | ','
1337 ;
1338
1339/* ------------------------------ VersionInfo ------------------------------ */
1340versioninfo
1341 : VERSIONINFO fix_version tBEGIN ver_blocks tEND {
1342 $$ = $2;
1343 $2->blocks = get_ver_block_head($4);
1344 }
1345 ;
1346
1347fix_version
1348 : /* Empty */ { $$ = new_versioninfo(); }
1349 | fix_version FILEVERSION expr ',' expr ',' expr ',' expr {
1350 if($1->gotit.fv)
1351 yyerror("FILEVERSION already defined");
1352 $$ = $1;
1353 $$->filever_maj1 = $3;
1354 $$->filever_maj2 = $5;
1355 $$->filever_min1 = $7;
1356 $$->filever_min2 = $9;
1357 $$->gotit.fv = 1;
1358 }
1359 | fix_version PRODUCTVERSION expr ',' expr ',' expr ',' expr {
1360 if($1->gotit.pv)
1361 yyerror("PRODUCTVERSION already defined");
1362 $$ = $1;
1363 $$->prodver_maj1 = $3;
1364 $$->prodver_maj2 = $5;
1365 $$->prodver_min1 = $7;
1366 $$->prodver_min2 = $9;
1367 $$->gotit.pv = 1;
1368 }
1369 | fix_version FILEFLAGS expr {
1370 if($1->gotit.ff)
1371 yyerror("FILEFLAGS already defined");
1372 $$ = $1;
1373 $$->fileflags = $3;
1374 $$->gotit.ff = 1;
1375 }
1376 | fix_version FILEFLAGSMASK expr {
1377 if($1->gotit.ffm)
1378 yyerror("FILEFLAGSMASK already defined");
1379 $$ = $1;
1380 $$->fileflagsmask = $3;
1381 $$->gotit.ffm = 1;
1382 }
1383 | fix_version FILEOS expr {
1384 if($1->gotit.fo)
1385 yyerror("FILEOS already defined");
1386 $$ = $1;
1387 $$->fileos = $3;
1388 $$->gotit.fo = 1;
1389 }
1390 | fix_version FILETYPE expr {
1391 if($1->gotit.ft)
1392 yyerror("FILETYPE already defined");
1393 $$ = $1;
1394 $$->filetype = $3;
1395 $$->gotit.ft = 1;
1396 }
1397 | fix_version FILESUBTYPE expr {
1398 if($1->gotit.fst)
1399 yyerror("FILESUBTYPE already defined");
1400 $$ = $1;
1401 $$->filesubtype = $3;
1402 $$->gotit.fst = 1;
1403 }
1404 ;
1405
1406ver_blocks
1407 : /* Empty */ { $$ = NULL; }
1408 | ver_blocks ver_block {
1409 $$ = $2;
1410 $$->prev = $1;
1411 if($1)
1412 $1->next = $$;
1413 }
1414 ;
1415
1416ver_block
1417 : BLOCK tSTRING tBEGIN ver_values tEND {
1418 $$ = new_ver_block();
1419 $$->name = $2;
1420 $$->values = get_ver_value_head($4);
1421 }
1422 ;
1423
1424ver_values
1425 : /* Empty */ { $$ = NULL; }
1426 | ver_values ver_value {
1427 $$ = $2;
1428 $$->prev = $1;
1429 if($1)
1430 $1->next = $$;
1431 }
1432 ;
1433
1434ver_value
1435 : ver_block {
1436 $$ = new_ver_value();
1437 $$->type = val_block;
1438 $$->value.block = $1;
1439 }
1440 | VALUE tSTRING ',' tSTRING {
1441 $$ = new_ver_value();
1442 $$->type = val_str;
1443 $$->key = $2;
1444 $$->value.str = $4;
1445 }
1446 | VALUE tSTRING ',' ver_words {
1447 $$ = new_ver_value();
1448 $$->type = val_words;
1449 $$->key = $2;
1450 $$->value.words = $4;
1451 }
1452 ;
1453
1454ver_words
1455 : expr { $$ = new_ver_words($1); }
1456 | ver_words ',' expr { $$ = add_ver_words($1, $3); }
1457 ;
1458
1459/* ------------------------------ Toolbar ------------------------------ */
1460toolbar: TOOLBAR loadmemopts expr ',' expr opt_lvc tBEGIN toolbar_items tEND {
1461 int nitems;
1462 toolbar_item_t *items = get_tlbr_buttons_head($8, &nitems);
1463 $$ = new_toolbar($3, $5, items, nitems);
1464 if($2)
1465 {
1466 $$->memopt = *($2);
1467 free($2);
1468 }
1469 else
1470 {
1471 $$->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE;
1472 }
1473 if($6)
1474 {
1475 $$->lvc = *($6);
1476 free($6);
1477 }
1478 if(!$$->lvc.language)
1479 {
1480 $$->lvc.language = dup_language(currentlanguage);
1481 }
1482 }
1483 ;
1484
1485toolbar_items
1486 : /* Empty */ { $$ = NULL; }
1487 | toolbar_items BUTTON expr {
1488 toolbar_item_t *idrec = new_toolbar_item();
1489 idrec->id = $3;
1490 $$ = ins_tlbr_button($1, idrec);
1491 }
1492 | toolbar_items SEPARATOR {
1493 toolbar_item_t *idrec = new_toolbar_item();
1494 idrec->id = 0;
1495 $$ = ins_tlbr_button($1, idrec);
1496 }
1497 ;
1498
1499/* ------------------------------ Memory options ------------------------------ */
1500loadmemopts
1501 : /* Empty */ { $$ = NULL; }
1502 | loadmemopts lamo {
1503 if($1)
1504 {
1505 *($1) |= *($2);
1506 $$ = $1;
1507 free($2);
1508 }
1509 else
1510 $$ = $2;
1511 }
1512 | loadmemopts lama {
1513 if($1)
1514 {
1515 *($1) &= *($2);
1516 $$ = $1;
1517 free($2);
1518 }
1519 else
1520 {
1521 *$2 &= WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE | WRC_MO_PURE;
1522 $$ = $2;
1523 }
1524 }
1525 ;
1526
1527lamo : PRELOAD { $$ = new_int(WRC_MO_PRELOAD); }
1528 | MOVEABLE { $$ = new_int(WRC_MO_MOVEABLE); }
1529 | DISCARDABLE { $$ = new_int(WRC_MO_DISCARDABLE); }
1530 | tPURE { $$ = new_int(WRC_MO_PURE); }
1531 ;
1532
1533lama : LOADONCALL { $$ = new_int(~WRC_MO_PRELOAD); }
1534 | tFIXED { $$ = new_int(~WRC_MO_MOVEABLE); }
1535 | IMPURE { $$ = new_int(~WRC_MO_PURE); }
1536 ;
1537
1538/* ------------------------------ Win32 options ------------------------------ */
1539opt_lvc : /* Empty */ { $$ = new_lvc(); }
1540 | opt_lvc opt_language {
1541 if(!win32)
1542 yywarning("LANGUAGE not supported in 16-bit mode");
1543 if($1->language)
1544 yyerror("Language already defined");
1545 $$ = $1;
1546 $1->language = $2;
1547 }
1548 | opt_lvc opt_characts {
1549 if(!win32)
1550 yywarning("CHARACTERISTICS not supported in 16-bit mode");
1551 if($1->characts)
1552 yyerror("Characteristics already defined");
1553 $$ = $1;
1554 $1->characts = $2;
1555 }
1556 | opt_lvc opt_version {
1557 if(!win32)
1558 yywarning("VERSION not supported in 16-bit mode");
1559 if($1->version)
1560 yyerror("Version already defined");
1561 $$ = $1;
1562 $1->version = $2;
1563 }
1564 ;
1565
1566opt_language
1567 : LANGUAGE expr ',' expr { $$ = new_language($2, $4); }
1568 ;
1569
1570opt_characts
1571 : CHARACTERISTICS expr { $$ = new_characts($2); }
1572 ;
1573
1574opt_version
1575 : VERSION expr { $$ = new_version($2); }
1576 ;
1577
1578/* ------------------------------ Raw data handking ------------------------------ */
1579raw_data: tBEGIN raw_elements tEND { $$ = $2; }
1580 ;
1581
1582raw_elements
1583 : RAWDATA { $$ = $1; }
1584 | NUMBER { $$ = int2raw_data($1); }
1585 | LNUMBER { $$ = long2raw_data($1); }
1586 | tSTRING { $$ = str2raw_data($1); }
1587 | raw_elements opt_comma RAWDATA { $$ = merge_raw_data($1, $3); free($3->data); free($3); }
1588 | raw_elements opt_comma NUMBER { $$ = merge_raw_data_int($1, $3); }
1589 | raw_elements opt_comma LNUMBER { $$ = merge_raw_data_long($1, $3); }
1590 | raw_elements opt_comma tSTRING { $$ = merge_raw_data_str($1, $3); }
1591 ;
1592
1593/* ------------------------------ Win32 expressions ------------------------------ */
1594/* All win16 numbers are also handled here. This is inconsistent with MS'
1595 * resource compiler, but what the heck, its just handy to have.
1596 */
1597e_expr : /* Empty */ { $$ = 0; }
1598 | expr { $$ = new_int($1); }
1599 ;
1600expr : dummy xpr { $$ = ($2) & andmask; }
1601 ;
1602
1603dummy : /* Empty */ { $$ = 0; andmask = -1; }
1604 ;
1605
1606xpr : xpr '+' xpr { $$ = ($1) + ($3); }
1607 | xpr '-' xpr { $$ = ($1) - ($3); }
1608 | xpr '|' xpr { $$ = ($1) | ($3); }
1609 | xpr '&' xpr { $$ = ($1) & ($3); }
1610 | xpr '*' xpr { $$ = ($1) * ($3); }
1611 | xpr '/' xpr { $$ = ($1) / ($3); }
1612 | '~' xpr { $$ = ~($2); }
1613 | '-' xpr { $$ = -($2); } /* FIXME: shift/reduce conflict */
1614/* | '+' xpr { $$ = $2; } */
1615 | '(' xpr ')' { $$ = $2; }
1616 | any_num { $$ = $1; want_rscname = 0; }
1617 | NOT any_num { $$ = 0; andmask &= ~($2); }
1618 ;
1619
1620any_num : NUMBER { $$ = $1; }
1621 | LNUMBER { $$ = $1; }
1622 ;
1623
1624%%
1625/* Dialog specific functions */
1626dialog_t *dialog_style(int st, dialog_t *dlg)
1627{
1628 DWORD s = 0;
1629 assert(dlg != NULL);
1630 if(dlg->gotstyle)
1631 {
1632 yywarning("Style already defined, or-ing together");
1633 s = dlg->style;
1634 }
1635 dlg->style = st | s;
1636 dlg->gotstyle = TRUE;
1637 return dlg;
1638}
1639
1640dialog_t *dialog_exstyle(int st, dialog_t *dlg)
1641{
1642 DWORD s = 0;
1643 assert(dlg != NULL);
1644 if(dlg->gotexstyle)
1645 {
1646 yywarning("ExStyle already defined, or-ing together");
1647 s = dlg->style;
1648 }
1649 dlg->exstyle = st | s;
1650 dlg->gotexstyle = TRUE;
1651 return dlg;
1652}
1653
1654dialog_t *dialog_caption(string_t *s, dialog_t *dlg)
1655{
1656 assert(dlg != NULL);
1657 if(dlg->title)
1658 yyerror("Caption already defined");
1659 dlg->title = s;
1660 return dlg;
1661}
1662
1663dialog_t *dialog_font(font_id_t *f, dialog_t *dlg)
1664{
1665 assert(dlg != NULL);
1666 if(dlg->font)
1667 yyerror("Font already defined");
1668 dlg->font = f;
1669 return dlg;
1670}
1671
1672dialog_t *dialog_class(name_id_t *n, dialog_t *dlg)
1673{
1674 assert(dlg != NULL);
1675 if(dlg->dlgclass)
1676 yyerror("Class already defined");
1677 dlg->dlgclass = n;
1678 return dlg;
1679}
1680
1681dialog_t *dialog_menu(name_id_t *m, dialog_t *dlg)
1682{
1683 assert(dlg != NULL);
1684 if(dlg->menu)
1685 yyerror("Menu already defined");
1686 dlg->menu = m;
1687 return dlg;
1688}
1689
1690dialog_t *dialog_language(language_t *l, dialog_t *dlg)
1691{
1692 assert(dlg != NULL);
1693 if(dlg->lvc.language)
1694 yyerror("Language already defined");
1695 dlg->lvc.language = l;
1696 return dlg;
1697}
1698
1699dialog_t *dialog_characteristics(characts_t *c, dialog_t *dlg)
1700{
1701 assert(dlg != NULL);
1702 if(dlg->lvc.characts)
1703 yyerror("Characteristics already defined");
1704 dlg->lvc.characts = c;
1705 return dlg;
1706}
1707
1708dialog_t *dialog_version(version_t *v, dialog_t *dlg)
1709{
1710 assert(dlg != NULL);
1711 if(dlg->lvc.version)
1712 yyerror("Version already defined");
1713 dlg->lvc.version = v;
1714 return dlg;
1715}
1716
1717/* Controls specific functions */
1718control_t *ins_ctrl(int type, int style, control_t *ctrl, control_t *prev)
1719{
1720 assert(ctrl != NULL);
1721 ctrl->prev = prev;
1722 if(prev)
1723 prev->next = ctrl;
1724 if(type != -1)
1725 {
1726 ctrl->ctlclass = new_name_id();
1727 ctrl->ctlclass->type = name_ord;
1728 ctrl->ctlclass->name.i_name = type;
1729 }
1730
1731 /* Hm... this seems to be jammed in at all time... */
1732 ctrl->style |= WS_CHILD | WS_VISIBLE;
1733 switch(type)
1734 {
1735 case CT_BUTTON:
1736 ctrl->style |= style;
1737 if(style != BS_GROUPBOX && style != BS_RADIOBUTTON)
1738 ctrl->style |= WS_TABSTOP;
1739 break;
1740 case CT_EDIT:
1741 ctrl->style |= WS_TABSTOP | WS_BORDER;
1742 break;
1743 case CT_LISTBOX:
1744 ctrl->style |= LBS_NOTIFY | WS_BORDER;
1745 break;
1746 case CT_COMBOBOX:
1747 ctrl->style |= CBS_SIMPLE;
1748 break;
1749 case CT_STATIC:
1750 ctrl->style |= style;
1751 if(style == SS_CENTER || style == SS_LEFT || style == SS_RIGHT)
1752 ctrl->style |= WS_GROUP;
1753 break;
1754 }
1755
1756 if(!ctrl->gotstyle) /* Handle default style setting */
1757 {
1758 switch(type)
1759 {
1760 case CT_EDIT:
1761 ctrl->style |= ES_LEFT;
1762 break;
1763 case CT_LISTBOX:
1764 ctrl->style |= LBS_NOTIFY;
1765 break;
1766 case CT_COMBOBOX:
1767 ctrl->style |= CBS_SIMPLE | WS_TABSTOP;
1768 break;
1769 case CT_SCROLLBAR:
1770 ctrl->style |= SBS_HORZ;
1771 break;
1772 case CT_BUTTON:
1773 switch(style)
1774 {
1775 case BS_CHECKBOX:
1776 case BS_DEFPUSHBUTTON:
1777 case BS_PUSHBUTTON:
1778 case BS_GROUPBOX:
1779/* case BS_PUSHBOX: */
1780 case BS_AUTORADIOBUTTON:
1781 case BS_AUTO3STATE:
1782 case BS_3STATE:
1783 case BS_AUTOCHECKBOX:
1784 ctrl->style |= WS_TABSTOP;
1785 break;
1786 default:
1787 yywarning("Unknown default button control-style 0x%08x", style);
1788 case BS_RADIOBUTTON:
1789 break;
1790 }
1791 break;
1792
1793 case CT_STATIC:
1794 switch(style)
1795 {
1796 case SS_LEFT:
1797 case SS_RIGHT:
1798 case SS_CENTER:
1799 ctrl->style |= WS_GROUP;
1800 break;
1801 case SS_ICON: /* Special case */
1802 break;
1803 default:
1804 yywarning("Unknown default static control-style 0x%08x", style);
1805 break;
1806 }
1807 break;
1808 case -1: /* Generic control */
1809 goto byebye;
1810
1811 default:
1812 yyerror("Internal error (report this): Got weird control type 0x%08x", type);
1813 }
1814 }
1815
1816 /* The SS_ICON flag is always forced in for icon controls */
1817 if(type == CT_STATIC && style == SS_ICON)
1818 ctrl->style |= SS_ICON;
1819
1820 ctrl->gotstyle = TRUE;
1821byebye:
1822 return ctrl;
1823}
1824
1825name_id_t *convert_ctlclass(name_id_t *cls)
1826{
1827 char *cc;
1828 int iclass;
1829
1830 if(cls->type == name_ord)
1831 return cls;
1832 assert(cls->type == name_str);
1833 if(cls->type == str_unicode)
1834 {
1835 yyerror("Don't yet support unicode class comparison");
1836 }
1837 else
1838 cc = cls->name.s_name->str.cstr;
1839
1840 if(!strcasecmp("BUTTON", cc))
1841 iclass = CT_BUTTON;
1842 else if(!strcasecmp("COMBOBOX", cc))
1843 iclass = CT_COMBOBOX;
1844 else if(!strcasecmp("LISTBOX", cc))
1845 iclass = CT_LISTBOX;
1846 else if(!strcasecmp("EDIT", cc))
1847 iclass = CT_EDIT;
1848 else if(!strcasecmp("STATIC", cc))
1849 iclass = CT_STATIC;
1850 else if(!strcasecmp("SCROLLBAR", cc))
1851 iclass = CT_SCROLLBAR;
1852 else
1853 return cls; /* No default, return user controlclass */
1854
1855 free(cls->name.s_name->str.cstr);
1856 free(cls->name.s_name);
1857 cls->type = name_ord;
1858 cls->name.i_name = iclass;
1859 return cls;
1860}
1861
1862/* DialogEx specific functions */
1863dialogex_t *dialogex_style(int st, dialogex_t *dlg)
1864{
1865 DWORD s = 0;
1866 assert(dlg != NULL);
1867 if(dlg->gotstyle)
1868 {
1869 yywarning("Style already defined, or-ing together");
1870 s = dlg->style;
1871 }
1872 dlg->style = st | s;
1873 dlg->gotstyle = TRUE;
1874 return dlg;
1875}
1876
1877dialogex_t *dialogex_exstyle(int st, dialogex_t *dlg)
1878{
1879 DWORD s = 0;
1880 assert(dlg != NULL);
1881 if(dlg->gotexstyle)
1882 {
1883 yywarning("ExStyle already defined, or-ing together");
1884 s = dlg->exstyle;
1885 }
1886 dlg->exstyle = st | s;
1887 dlg->gotexstyle = TRUE;
1888 return dlg;
1889}
1890
1891dialogex_t *dialogex_caption(string_t *s, dialogex_t *dlg)
1892{
1893 assert(dlg != NULL);
1894 if(dlg->title)
1895 yyerror("Caption already defined");
1896 dlg->title = s;
1897 return dlg;
1898}
1899
1900dialogex_t *dialogex_font(font_id_t *f, dialogex_t *dlg)
1901{
1902 assert(dlg != NULL);
1903 if(dlg->font)
1904 yyerror("Font already defined");
1905 dlg->font = f;
1906 return dlg;
1907}
1908
1909dialogex_t *dialogex_class(name_id_t *n, dialogex_t *dlg)
1910{
1911 assert(dlg != NULL);
1912 if(dlg->dlgclass)
1913 yyerror("Class already defined");
1914 dlg->dlgclass = n;
1915 return dlg;
1916}
1917
1918dialogex_t *dialogex_menu(name_id_t *m, dialogex_t *dlg)
1919{
1920 assert(dlg != NULL);
1921 if(dlg->menu)
1922 yyerror("Menu already defined");
1923 dlg->menu = m;
1924 return dlg;
1925}
1926
1927dialogex_t *dialogex_language(language_t *l, dialogex_t *dlg)
1928{
1929 assert(dlg != NULL);
1930 if(dlg->lvc.language)
1931 yyerror("Language already defined");
1932 dlg->lvc.language = l;
1933 return dlg;
1934}
1935
1936dialogex_t *dialogex_characteristics(characts_t *c, dialogex_t *dlg)
1937{
1938 assert(dlg != NULL);
1939 if(dlg->lvc.characts)
1940 yyerror("Characteristics already defined");
1941 dlg->lvc.characts = c;
1942 return dlg;
1943}
1944
1945dialogex_t *dialogex_version(version_t *v, dialogex_t *dlg)
1946{
1947 assert(dlg != NULL);
1948 if(dlg->lvc.version)
1949 yyerror("Version already defined");
1950 dlg->lvc.version = v;
1951 return dlg;
1952}
1953
1954/* Accelerator specific functions */
1955event_t *add_event(int key, int id, int flags, event_t *prev)
1956{
1957 event_t *ev = new_event();
1958
1959 if((flags & (WRC_AF_VIRTKEY | WRC_AF_ASCII)) == (WRC_AF_VIRTKEY | WRC_AF_ASCII))
1960 yyerror("Cannot use both ASCII and VIRTKEY");
1961
1962 ev->key = key;
1963 ev->id = id;
1964 ev->flags = flags & ~WRC_AF_ASCII;
1965 ev->prev = prev;
1966 if(prev)
1967 prev->next = ev;
1968 return ev;
1969}
1970
1971event_t *add_string_event(string_t *key, int id, int flags, event_t *prev)
1972{
1973 int keycode = 0;
1974 event_t *ev = new_event();
1975
1976 if(key->type != str_char)
1977 yyerror("Key code must be an ascii string");
1978
1979 if((flags & WRC_AF_VIRTKEY) && (!isupper(key->str.cstr[0]) && !isdigit(key->str.cstr[0])))
1980 yyerror("VIRTKEY code is not equal to ascii value");
1981
1982 if(key->str.cstr[0] == '^' && (flags & WRC_AF_CONTROL) != 0)
1983 {
1984 yyerror("Cannot use both '^' and CONTROL modifier");
1985 }
1986 else if(key->str.cstr[0] == '^')
1987 {
1988 keycode = toupper(key->str.cstr[1]) - '@';
1989 if(keycode >= ' ')
1990 yyerror("Control-code out of range");
1991 }
1992 else
1993 keycode = key->str.cstr[0];
1994 ev->key = keycode;
1995 ev->id = id;
1996 ev->flags = flags & ~WRC_AF_ASCII;
1997 ev->prev = prev;
1998 if(prev)
1999 prev->next = ev;
2000 return ev;
2001}
2002
2003/* MenuEx specific functions */
2004itemex_opt_t *new_itemex_opt(int id, int type, int state, int helpid)
2005{
2006 itemex_opt_t *opt = (itemex_opt_t *)xmalloc(sizeof(itemex_opt_t));
2007 opt->id = id;
2008 opt->type = type;
2009 opt->state = state;
2010 opt->helpid = helpid;
2011 return opt;
2012}
2013
2014/* Raw data functions */
2015raw_data_t *load_file(string_t *name)
2016{
2017 FILE *fp;
2018 raw_data_t *rd;
2019 if(name->type != str_char)
2020 yyerror("Filename must be ASCII string");
2021
2022 fp = open_include(name->str.cstr, 1);
2023 if(!fp)
2024 yyerror("Cannot open file %s", name->str.cstr);
2025 rd = new_raw_data();
2026 fseek(fp, 0, SEEK_END);
2027 rd->size = ftell(fp);
2028 fseek(fp, 0, SEEK_SET);
2029 rd->data = (char *)xmalloc(rd->size);
2030 fread(rd->data, rd->size, 1, fp);
2031 fclose(fp);
2032 HEAPCHECK();
2033 return rd;
2034}
2035
2036raw_data_t *int2raw_data(int i)
2037{
2038 raw_data_t *rd;
2039
2040 if((int)((short)i) != i)
2041 yywarning("Integer constant out of 16bit range (%d), truncated to %d\n", i, (short)i);
2042
2043 rd = new_raw_data();
2044 rd->size = sizeof(short);
2045 rd->data = (char *)xmalloc(rd->size);
2046 *(short *)(rd->data) = (short)i;
2047 return rd;
2048}
2049
2050raw_data_t *long2raw_data(int i)
2051{
2052 raw_data_t *rd;
2053 rd = new_raw_data();
2054 rd->size = sizeof(int);
2055 rd->data = (char *)xmalloc(rd->size);
2056 *(int *)(rd->data) = i;
2057 return rd;
2058}
2059
2060raw_data_t *str2raw_data(string_t *str)
2061{
2062 raw_data_t *rd;
2063 rd = new_raw_data();
2064 rd->size = str->size * (str->type == str_char ? 1 : 2);
2065 rd->data = (char *)xmalloc(rd->size);
2066 memcpy(rd->data, str->str.cstr, rd->size);
2067 return rd;
2068}
2069
2070raw_data_t *merge_raw_data(raw_data_t *r1, raw_data_t *r2)
2071{
2072 r1->data = xrealloc(r1->data, r1->size + r2->size);
2073 memcpy(r1->data + r1->size, r2->data, r2->size);
2074 r1->size += r2->size;
2075 return r1;
2076}
2077
2078raw_data_t *merge_raw_data_int(raw_data_t *r1, int i)
2079{
2080 raw_data_t *t = int2raw_data(i);
2081 merge_raw_data(r1, t);
2082 free(t->data);
2083 free(t);
2084 return r1;
2085}
2086
2087raw_data_t *merge_raw_data_long(raw_data_t *r1, int i)
2088{
2089 raw_data_t *t = long2raw_data(i);
2090 merge_raw_data(r1, t);
2091 free(t->data);
2092 free(t);
2093 return r1;
2094}
2095
2096raw_data_t *merge_raw_data_str(raw_data_t *r1, string_t *str)
2097{
2098 raw_data_t *t = str2raw_data(str);
2099 merge_raw_data(r1, t);
2100 free(t->data);
2101 free(t);
2102 return r1;
2103}
2104
2105/* Function the go back in a list to get the head */
2106menu_item_t *get_item_head(menu_item_t *p)
2107{
2108 if(!p)
2109 return NULL;
2110 while(p->prev)
2111 p = p->prev;
2112 return p;
2113}
2114
2115menuex_item_t *get_itemex_head(menuex_item_t *p)
2116{
2117 if(!p)
2118 return NULL;
2119 while(p->prev)
2120 p = p->prev;
2121 return p;
2122}
2123
2124resource_t *get_resource_head(resource_t *p)
2125{
2126 if(!p)
2127 return NULL;
2128 while(p->prev)
2129 p = p->prev;
2130 return p;
2131}
2132
2133ver_block_t *get_ver_block_head(ver_block_t *p)
2134{
2135 if(!p)
2136 return NULL;
2137 while(p->prev)
2138 p = p->prev;
2139 return p;
2140}
2141
2142ver_value_t *get_ver_value_head(ver_value_t *p)
2143{
2144 if(!p)
2145 return NULL;
2146 while(p->prev)
2147 p = p->prev;
2148 return p;
2149}
2150
2151control_t *get_control_head(control_t *p)
2152{
2153 if(!p)
2154 return NULL;
2155 while(p->prev)
2156 p = p->prev;
2157 return p;
2158}
2159
2160event_t *get_event_head(event_t *p)
2161{
2162 if(!p)
2163 return NULL;
2164 while(p->prev)
2165 p = p->prev;
2166 return p;
2167}
2168
2169/* Find a stringtable with given language */
2170stringtable_t *find_stringtable(lvc_t *lvc)
2171{
2172 stringtable_t *stt;
2173
2174 assert(lvc != NULL);
2175
2176 if(!lvc->language)
2177 lvc->language = dup_language(currentlanguage);
2178
2179 for(stt = sttres; stt; stt = stt->next)
2180 {
2181 if(stt->lvc.language->id == lvc->language->id
2182 && stt->lvc.language->id == lvc->language->id)
2183 {
2184 /* Found a table with the same language */
2185 /* The version and characteristics are now handled
2186 * in the generation of the individual stringtables.
2187 * This enables localized analysis.
2188 if((stt->lvc.version && lvc->version && *(stt->lvc.version) != *(lvc->version))
2189 || (!stt->lvc.version && lvc->version)
2190 || (stt->lvc.version && !lvc->version))
2191 yywarning("Stringtable's versions are not the same, using first definition");
2192
2193 if((stt->lvc.characts && lvc->characts && *(stt->lvc.characts) != *(lvc->characts))
2194 || (!stt->lvc.characts && lvc->characts)
2195 || (stt->lvc.characts && !lvc->characts))
2196 yywarning("Stringtable's characteristics are not the same, using first definition");
2197 */
2198 return stt;
2199 }
2200 }
2201 return NULL;
2202}
2203
2204/* qsort sorting function for string table entries */
2205#define STE(p) ((stt_entry_t *)(p))
2206int sort_stt_entry(const void *e1, const void *e2)
2207{
2208 return STE(e1)->id - STE(e2)->id;
2209}
2210#undef STE
2211
2212resource_t *build_stt_resources(stringtable_t *stthead)
2213{
2214 stringtable_t *stt;
2215 stringtable_t *newstt;
2216 resource_t *rsc;
2217 resource_t *rsclist = NULL;
2218 resource_t *rsctail = NULL;
2219 int i;
2220 int j;
2221 DWORD andsum;
2222 DWORD orsum;
2223 characts_t *characts;
2224 version_t *version;
2225
2226 if(!stthead)
2227 return NULL;
2228
2229 /* For all languages defined */
2230 for(stt = stthead; stt; stt = stt->next)
2231 {
2232 assert(stt->nentries > 0);
2233
2234 /* Sort the entries */
2235 if(stt->nentries > 1)
2236 qsort(stt->entries, stt->nentries, sizeof(stt->entries[0]), sort_stt_entry);
2237
2238 for(i = 0; i < stt->nentries; )
2239 {
2240 newstt = new_stringtable(&stt->lvc);
2241 newstt->entries = (stt_entry_t *)xmalloc(16 * sizeof(stt_entry_t));
2242 newstt->nentries = 16;
2243 newstt->idbase = stt->entries[i].id & ~0xf;
2244 for(j = 0; j < 16 && i < stt->nentries; j++)
2245 {
2246 if(stt->entries[i].id - newstt->idbase == j)
2247 {
2248 newstt->entries[j] = stt->entries[i];
2249 i++;
2250 }
2251 }
2252 andsum = ~0;
2253 orsum = 0;
2254 characts = NULL;
2255 version = NULL;
2256 /* Check individual memory options and get
2257 * the first characteristics/version
2258 */
2259 for(j = 0; j < 16; j++)
2260 {
2261 if(!newstt->entries[j].str)
2262 continue;
2263 andsum &= newstt->entries[j].memopt;
2264 orsum |= newstt->entries[j].memopt;
2265 if(!characts)
2266 characts = newstt->entries[j].characts;
2267 if(!version)
2268 version = newstt->entries[j].version;
2269 }
2270 if(andsum != orsum)
2271 {
2272 warning("Stringtable's memory options are not equal (idbase: %d)", newstt->idbase);
2273 }
2274 /* Check version and characteristics */
2275 for(j = 0; j < 16; j++)
2276 {
2277 if(characts
2278 && newstt->entries[j].characts
2279 && *newstt->entries[j].characts != *characts)
2280 warning("Stringtable's characteristics are not the same (idbase: %d)", newstt->idbase);
2281 if(version
2282 && newstt->entries[j].version
2283 && *newstt->entries[j].version != *version)
2284 warning("Stringtable's versions are not the same (idbase: %d)", newstt->idbase);
2285 }
2286 rsc = new_resource(res_stt, newstt, newstt->memopt, newstt->lvc.language);
2287 rsc->name = new_name_id();
2288 rsc->name->type = name_ord;
2289 rsc->name->name.i_name = (newstt->idbase >> 4) + 1;
2290 rsc->memopt = andsum; /* Set to least common denominator */
2291 newstt->memopt = andsum;
2292 newstt->lvc.characts = characts;
2293 newstt->lvc.version = version;
2294 if(!rsclist)
2295 {
2296 rsclist = rsc;
2297 rsctail = rsc;
2298 }
2299 else
2300 {
2301 rsctail->next = rsc;
2302 rsc->prev = rsctail;
2303 rsctail = rsc;
2304 }
2305 }
2306 }
2307 return rsclist;
2308}
2309
2310/* Cursor and icon splitter functions */
2311typedef struct {
2312 language_t lan;
2313 int id;
2314} id_alloc_t;
2315
2316static int get_new_id(id_alloc_t **list, int *n, language_t *lan)
2317{
2318 int i;
2319 assert(lan != NULL);
2320 assert(list != NULL);
2321 assert(n != NULL);
2322
2323 if(!*list)
2324 {
2325 *list = (id_alloc_t *)xmalloc(sizeof(id_alloc_t));
2326 *n = 1;
2327 (*list)[0].lan = *lan;
2328 (*list)[0].id = 1;
2329 return 1;
2330 }
2331
2332 for(i = 0; i < *n; i++)
2333 {
2334 if((*list)[i].lan.id == lan->id && (*list)[i].lan.sub == lan->sub)
2335 return ++((*list)[i].id);
2336 }
2337
2338 *list = (id_alloc_t *)xrealloc(*list, sizeof(id_alloc_t) * (*n+1));
2339 (*list)[*n].lan = *lan;
2340 (*list)[*n].id = 1;
2341 *n += 1;
2342 return 1;
2343}
2344
2345int alloc_icon_id(language_t *lan)
2346{
2347 static id_alloc_t *idlist = NULL;
2348 static int nid = 0;
2349
2350 return get_new_id(&idlist, &nid, lan);
2351}
2352
2353int alloc_cursor_id(language_t *lan)
2354{
2355 static id_alloc_t *idlist = NULL;
2356 static int nid = 0;
2357
2358 return get_new_id(&idlist, &nid, lan);
2359}
2360
2361#define BPTR(base) ((char *)(rd->data + (base)))
2362#define WPTR(base) ((WORD *)(rd->data + (base)))
2363#define DPTR(base) ((DWORD *)(rd->data + (base)))
2364void split_icons(raw_data_t *rd, icon_group_t *icog, int *nico)
2365{
2366 int cnt;
2367 int i;
2368 icon_dir_entry_t *ide;
2369 icon_t *ico;
2370 icon_t *list = NULL;
2371
2372 /* FIXME: Distinguish between normal and animated icons (RIFF format) */
2373 if(WPTR(0)[1] != 1)
2374 yyerror("Icon resource data has invalid type id %d", WPTR(0)[1]);
2375 cnt = WPTR(0)[2];
2376 ide = (icon_dir_entry_t *)&(WPTR(0)[3]);
2377 for(i = 0; i < cnt; i++)
2378 {
2379 ico = new_icon();
2380 ico->id = alloc_icon_id(icog->lvc.language);
2381 ico->lvc.language = dup_language(icog->lvc.language);
2382 if(ide[i].offset > rd->size
2383 || ide[i].offset + ide[i].ressize > rd->size)
2384 yyerror("Icon resource data corrupt");
2385 ico->width = ide[i].width;
2386 ico->height = ide[i].height;
2387 ico->nclr = ide[i].nclr;
2388 ico->planes = ide[i].planes;
2389 ico->bits = ide[i].bits;
2390 if(!ico->planes)
2391 {
2392 /* Argh! They did not fill out the resdir structure */
2393 ico->planes = ((BITMAPINFOHEADER *)BPTR(ide[i].offset))->biPlanes;
2394 }
2395 if(!ico->bits)
2396 {
2397 /* Argh! They did not fill out the resdir structure */
2398 ico->bits = ((BITMAPINFOHEADER *)BPTR(ide[i].offset))->biBitCount;
2399 }
2400 ico->data = new_raw_data();
2401 copy_raw_data(ico->data, rd, ide[i].offset, ide[i].ressize);
2402 if(!list)
2403 {
2404 list = ico;
2405 }
2406 else
2407 {
2408 ico->next = list;
2409 list->prev = ico;
2410 list = ico;
2411 }
2412 }
2413 icog->iconlist = list;
2414 *nico = cnt;
2415}
2416
2417void split_cursors(raw_data_t *rd, cursor_group_t *curg, int *ncur)
2418{
2419 int cnt;
2420 int i;
2421 cursor_dir_entry_t *cde;
2422 cursor_t *cur;
2423 cursor_t *list = NULL;
2424
2425 /* FIXME: Distinguish between normal and animated cursors (RIFF format)*/
2426 if(WPTR(0)[1] != 2)
2427 yyerror("Cursor resource data has invalid type id %d", WPTR(0)[1]);
2428 cnt = WPTR(0)[2];
2429 cde = (cursor_dir_entry_t *)&(WPTR(0)[3]);
2430 for(i = 0; i < cnt; i++)
2431 {
2432 cur = new_cursor();
2433 cur->id = alloc_cursor_id(curg->lvc.language);
2434 cur->lvc.language = dup_language(curg->lvc.language);
2435 if(cde[i].offset > rd->size
2436 || cde[i].offset + cde[i].ressize > rd->size)
2437 yyerror("Cursor resource data corrupt");
2438 cur->width = cde[i].width;
2439 cur->height = cde[i].height;
2440 cur->nclr = cde[i].nclr;
2441 /* The next two are to support color cursors */
2442 cur->planes = ((BITMAPINFOHEADER *)BPTR(cde[i].offset))->biPlanes;
2443 cur->bits = ((BITMAPINFOHEADER *)BPTR(cde[i].offset))->biBitCount;
2444 if(!win32 && (cur->planes != 1 || cur->bits != 1))
2445 yywarning("Win16 cursor contains colors");
2446 cur->xhot = cde[i].xhot;
2447 cur->yhot = cde[i].yhot;
2448 cur->data = new_raw_data();
2449 copy_raw_data(cur->data, rd, cde[i].offset, cde[i].ressize);
2450 if(!list)
2451 {
2452 list = cur;
2453 }
2454 else
2455 {
2456 cur->next = list;
2457 list->prev = cur;
2458 list = cur;
2459 }
2460 }
2461 curg->cursorlist = list;
2462 *ncur = cnt;
2463}
2464
2465#undef BPTR
2466#undef WPTR
2467#undef DPTR
2468
2469
2470toolbar_item_t *ins_tlbr_button(toolbar_item_t *prev, toolbar_item_t *idrec)
2471{
2472 idrec->prev = prev;
2473 if(prev)
2474 prev->next = idrec;
2475
2476 return idrec;
2477}
2478
2479toolbar_item_t *get_tlbr_buttons_head(toolbar_item_t *p, int *nitems)
2480{
2481 if(!p)
2482 {
2483 *nitems = 0;
2484 return NULL;
2485 }
2486
2487 *nitems = 1;
2488
2489 while(p->prev)
2490 {
2491 (*nitems)++;
2492 p = p->prev;
2493 }
2494
2495 return p;
2496}
2497
Note: See TracBrowser for help on using the repository browser.