| 1 | %{ | 
|---|
| 2 | /* | 
|---|
| 3 | * Copyright 1994       Martin von Loewis | 
|---|
| 4 | * Copyright 1998-2000  Bertho A. Stultiens (BS) | 
|---|
| 5 | *           1999       Juergen Schmied (JS) | 
|---|
| 6 | * | 
|---|
| 7 | * 24-Jul-2000 BS       - Made a fix for broken Berkeley yacc on | 
|---|
| 8 | *                        non-terminals (see cjunk rule). | 
|---|
| 9 | * 21-May-2000 BS       - Partial implementation of font resources. | 
|---|
| 10 | *                      - Corrected language propagation for binary | 
|---|
| 11 | *                        resources such as bitmaps, isons, cursors, | 
|---|
| 12 | *                        userres and rcdata. The language is now | 
|---|
| 13 | *                        correct in .res files. | 
|---|
| 14 | *                      - Fixed reading the resource name as ident, | 
|---|
| 15 | *                        so that it may overlap keywords. | 
|---|
| 16 | * 20-May-2000 BS       - Implemented animated cursors and icons | 
|---|
| 17 | *                        resource types. | 
|---|
| 18 | * 30-Apr-2000 BS       - Reintegration into the wine-tree | 
|---|
| 19 | * 14-Jan-2000 BS       - Redid the usertype resources so that they | 
|---|
| 20 | *                        are compatible. | 
|---|
| 21 | * 02-Jan-2000 BS       - Removed the preprocessor from the grammar | 
|---|
| 22 | *                        expect for the # command (line numbers). | 
|---|
| 23 | * | 
|---|
| 24 | * 06-Nov-1999 JS       - see CHANGES | 
|---|
| 25 | * | 
|---|
| 26 | * 29-Dec-1998 AdH      - Grammar and function extensions. | 
|---|
| 27 | *                           grammar: TOOLBAR resources, Named ICONs in | 
|---|
| 28 | *                              DIALOGS | 
|---|
| 29 | *                           functions: semantic actions for the grammar | 
|---|
| 30 | *                              changes, resource files can now be anywhere | 
|---|
| 31 | *                              on the include path instead of just in the | 
|---|
| 32 | *                              current directory | 
|---|
| 33 | * | 
|---|
| 34 | * 20-Jun-1998 BS       - Fixed a bug in load_file() where the name was not | 
|---|
| 35 | *                        printed out correctly. | 
|---|
| 36 | * | 
|---|
| 37 | * 17-Jun-1998 BS       - Fixed a bug in CLASS statement parsing which should | 
|---|
| 38 | *                        also accept a tSTRING as argument. | 
|---|
| 39 | * | 
|---|
| 40 | * 25-May-1998 BS       - Found out that I need to support language, version | 
|---|
| 41 | *                        and characteristics in inline resources (bitmap, | 
|---|
| 42 | *                        cursor, etc) but they can also be specified with | 
|---|
| 43 | *                        a filename. This renders my filename-scanning scheme | 
|---|
| 44 | *                        worthless. Need to build newline parsing to solve | 
|---|
| 45 | *                        this one. | 
|---|
| 46 | *                        It will come with version 1.1.0 (sigh). | 
|---|
| 47 | * | 
|---|
| 48 | * 19-May-1998 BS       - Started to build a builtin preprocessor | 
|---|
| 49 | * | 
|---|
| 50 | * 30-Apr-1998 BS       - Redid the stringtable parsing/handling. My previous | 
|---|
| 51 | *                        ideas had some serious flaws. | 
|---|
| 52 | * | 
|---|
| 53 | * 27-Apr-1998 BS       - Removed a lot of dead comments and put it in a doc | 
|---|
| 54 | *                        file. | 
|---|
| 55 | * | 
|---|
| 56 | * 21-Apr-1998 BS       - Added correct behavior for cursors and icons. | 
|---|
| 57 | *                      - This file is growing too big. It is time to strip | 
|---|
| 58 | *                        things and put it in a support file. | 
|---|
| 59 | * | 
|---|
| 60 | * 19-Apr-1998 BS       - Tagged the stringtable resource so that only one | 
|---|
| 61 | *                        resource will be created. This because the table | 
|---|
| 62 | *                        has a different layout than other resources. The | 
|---|
| 63 | *                        table has to be sorted, and divided into smaller | 
|---|
| 64 | *                        resource entries (see comment in source). | 
|---|
| 65 | * | 
|---|
| 66 | * 17-Apr-1998 BS       - Almost all strings, including identifiers, are parsed | 
|---|
| 67 | *                        as string_t which include unicode strings upon | 
|---|
| 68 | *                        input. | 
|---|
| 69 | *                      - Parser now emits a warning when compiling win32 | 
|---|
| 70 | *                        extensions in win16 mode. | 
|---|
| 71 | * | 
|---|
| 72 | * 16-Apr-1998 BS       - Raw data elements are now *optionally* seperated | 
|---|
| 73 | *                        by commas. Read the comments in file sq2dq.l. | 
|---|
| 74 | *                      - FIXME: there are instances in the source that rely | 
|---|
| 75 | *                        on the fact that int==32bit and pointers are int size. | 
|---|
| 76 | *                      - Fixed the conflict in menuex by changing a rule | 
|---|
| 77 | *                        back into right recursion. See note in source. | 
|---|
| 78 | *                      - UserType resources cannot have an expression as its | 
|---|
| 79 | *                        typeclass. See note in source. | 
|---|
| 80 | * | 
|---|
| 81 | * 15-Apr-1998 BS       - Changed all right recursion into left recursion to | 
|---|
| 82 | *                        get reduction of the parsestack. | 
|---|
| 83 | *                        This also helps communication between bison and flex. | 
|---|
| 84 | *                        Main advantage is that the Empty rule gets reduced | 
|---|
| 85 | *                        first, which is used to allocate/link things. | 
|---|
| 86 | *                        It also added a shift/reduce conflict in the menuex | 
|---|
| 87 | *                        handling, due to expression/option possibility, | 
|---|
| 88 | *                        although not serious. | 
|---|
| 89 | * | 
|---|
| 90 | * 14-Apr-1998 BS       - Redone almost the entire parser. We're not talking | 
|---|
| 91 | *                        about making it more efficient, but readable (for me) | 
|---|
| 92 | *                        and slightly easier to expand/change. | 
|---|
| 93 | *                        This is done primarily by using more reduce states | 
|---|
| 94 | *                        with many (intuitive) types for the various resource | 
|---|
| 95 | *                        statements. | 
|---|
| 96 | *                      - Added expression handling for all resources where a | 
|---|
| 97 | *                        number is accepted (not only for win32). Also added | 
|---|
| 98 | *                        multiply and division (not MS compatible, but handy). | 
|---|
| 99 | *                        Unary minus introduced a shift/reduce conflict, but | 
|---|
| 100 | *                        it is not serious. | 
|---|
| 101 | * | 
|---|
| 102 | * 13-Apr-1998 BS       - Reordered a lot of things | 
|---|
| 103 | *                      - Made the source more readable | 
|---|
| 104 | *                      - Added Win32 resource definitions | 
|---|
| 105 | *                      - Corrected syntax problems with an old yacc (;) | 
|---|
| 106 | *                      - Added extra comment about grammar | 
|---|
| 107 | */ | 
|---|
| 108 | #include "config.h" | 
|---|
| 109 |  | 
|---|
| 110 | #include <stdio.h> | 
|---|
| 111 | #include <stdlib.h> | 
|---|
| 112 | #include <stdarg.h> | 
|---|
| 113 | #include <assert.h> | 
|---|
| 114 | #include <ctype.h> | 
|---|
| 115 | #include <string.h> | 
|---|
| 116 | #ifdef HAVE_ALLOCA_H | 
|---|
| 117 | #include <alloca.h> | 
|---|
| 118 | #endif | 
|---|
| 119 |  | 
|---|
| 120 | #include "wrc.h" | 
|---|
| 121 | #include "utils.h" | 
|---|
| 122 | #include "newstruc.h" | 
|---|
| 123 | #include "dumpres.h" | 
|---|
| 124 | #include "preproc.h" | 
|---|
| 125 | #include "parser.h" | 
|---|
| 126 | #include "windef.h" | 
|---|
| 127 | #include "winbase.h" | 
|---|
| 128 | #include "wingdi.h" | 
|---|
| 129 | #include "winuser.h" | 
|---|
| 130 |  | 
|---|
| 131 | #if defined(YYBYACC) | 
|---|
| 132 | /* Berkeley yacc (byacc) doesn't seem to know about these */ | 
|---|
| 133 | /* Some *BSD supplied versions do define these though */ | 
|---|
| 134 | # ifndef YYEMPTY | 
|---|
| 135 | #  define YYEMPTY       (-1)    /* Empty lookahead value of yychar */ | 
|---|
| 136 | # endif | 
|---|
| 137 | # ifndef YYLEX | 
|---|
| 138 | #  define YYLEX         yylex() | 
|---|
| 139 | # endif | 
|---|
| 140 |  | 
|---|
| 141 | #elif defined(YYBISON) | 
|---|
| 142 | /* Bison was used for original development */ | 
|---|
| 143 | /* #define YYEMPTY -2 */ | 
|---|
| 144 | /* #define YYLEX   yylex() */ | 
|---|
| 145 |  | 
|---|
| 146 | #else | 
|---|
| 147 | /* No yacc we know yet */ | 
|---|
| 148 | # if !defined(YYEMPTY) || !defined(YYLEX) | 
|---|
| 149 | #  error Yacc version/type unknown. This version needs to be verified for settings of YYEMPTY and YYLEX. | 
|---|
| 150 | # elif defined(__GNUC__)        /* gcc defines the #warning directive */ | 
|---|
| 151 | #  warning Yacc version/type unknown. It defines YYEMPTY and YYLEX, but is not tested | 
|---|
| 152 | /* #else we just take a chance that it works... */ | 
|---|
| 153 | # endif | 
|---|
| 154 | #endif | 
|---|
| 155 |  | 
|---|
| 156 | int want_nl = 0;        /* Signal flex that we need the next newline */ | 
|---|
| 157 | int want_id = 0;        /* Signal flex that we need the next identifier */ | 
|---|
| 158 | stringtable_t *tagstt;  /* Stringtable tag. | 
|---|
| 159 | * It is set while parsing a stringtable to one of | 
|---|
| 160 | * the stringtables in the sttres list or a new one | 
|---|
| 161 | * if the language was not parsed before. | 
|---|
| 162 | */ | 
|---|
| 163 | stringtable_t *sttres;  /* Stringtable resources. This holds the list of | 
|---|
| 164 | * stringtables with different lanuages | 
|---|
| 165 | */ | 
|---|
| 166 | static int dont_want_id = 0;    /* See language parsing for details */ | 
|---|
| 167 |  | 
|---|
| 168 | /* Set to the current options of the currently scanning stringtable */ | 
|---|
| 169 | static int *tagstt_memopt; | 
|---|
| 170 | static characts_t *tagstt_characts; | 
|---|
| 171 | static version_t *tagstt_version; | 
|---|
| 172 |  | 
|---|
| 173 | static const char riff[4] = "RIFF";     /* RIFF file magic for animated cursor/icon */ | 
|---|
| 174 |  | 
|---|
| 175 | /* Prototypes of here defined functions */ | 
|---|
| 176 | static event_t *get_event_head(event_t *p); | 
|---|
| 177 | static control_t *get_control_head(control_t *p); | 
|---|
| 178 | static ver_value_t *get_ver_value_head(ver_value_t *p); | 
|---|
| 179 | static ver_block_t *get_ver_block_head(ver_block_t *p); | 
|---|
| 180 | static resource_t *get_resource_head(resource_t *p); | 
|---|
| 181 | static menuex_item_t *get_itemex_head(menuex_item_t *p); | 
|---|
| 182 | static menu_item_t *get_item_head(menu_item_t *p); | 
|---|
| 183 | static raw_data_t *merge_raw_data_str(raw_data_t *r1, string_t *str); | 
|---|
| 184 | static raw_data_t *merge_raw_data_int(raw_data_t *r1, int i); | 
|---|
| 185 | static raw_data_t *merge_raw_data_long(raw_data_t *r1, int i); | 
|---|
| 186 | static raw_data_t *merge_raw_data(raw_data_t *r1, raw_data_t *r2); | 
|---|
| 187 | static raw_data_t *str2raw_data(string_t *str); | 
|---|
| 188 | static raw_data_t *int2raw_data(int i); | 
|---|
| 189 | static raw_data_t *long2raw_data(int i); | 
|---|
| 190 | static raw_data_t *load_file(string_t *name); | 
|---|
| 191 | static itemex_opt_t *new_itemex_opt(int id, int type, int state, int helpid); | 
|---|
| 192 | static event_t *add_string_event(string_t *key, int id, int flags, event_t *prev); | 
|---|
| 193 | static event_t *add_event(int key, int id, int flags, event_t *prev); | 
|---|
| 194 | static dialogex_t *dialogex_version(version_t *v, dialogex_t *dlg); | 
|---|
| 195 | static dialogex_t *dialogex_characteristics(characts_t *c, dialogex_t *dlg); | 
|---|
| 196 | static dialogex_t *dialogex_language(language_t *l, dialogex_t *dlg); | 
|---|
| 197 | static dialogex_t *dialogex_menu(name_id_t *m, dialogex_t *dlg); | 
|---|
| 198 | static dialogex_t *dialogex_class(name_id_t *n, dialogex_t *dlg); | 
|---|
| 199 | static dialogex_t *dialogex_font(font_id_t *f, dialogex_t *dlg); | 
|---|
| 200 | static dialogex_t *dialogex_caption(string_t *s, dialogex_t *dlg); | 
|---|
| 201 | static dialogex_t *dialogex_exstyle(style_t *st, dialogex_t *dlg); | 
|---|
| 202 | static dialogex_t *dialogex_style(style_t *st, dialogex_t *dlg); | 
|---|
| 203 | static name_id_t *convert_ctlclass(name_id_t *cls); | 
|---|
| 204 | static control_t *ins_ctrl(int type, int special_style, control_t *ctrl, control_t *prev); | 
|---|
| 205 | static dialog_t *dialog_version(version_t *v, dialog_t *dlg); | 
|---|
| 206 | static dialog_t *dialog_characteristics(characts_t *c, dialog_t *dlg); | 
|---|
| 207 | static dialog_t *dialog_language(language_t *l, dialog_t *dlg); | 
|---|
| 208 | static dialog_t *dialog_menu(name_id_t *m, dialog_t *dlg); | 
|---|
| 209 | static dialog_t *dialog_class(name_id_t *n, dialog_t *dlg); | 
|---|
| 210 | static dialog_t *dialog_font(font_id_t *f, dialog_t *dlg); | 
|---|
| 211 | static dialog_t *dialog_caption(string_t *s, dialog_t *dlg); | 
|---|
| 212 | static dialog_t *dialog_exstyle(style_t * st, dialog_t *dlg); | 
|---|
| 213 | static dialog_t *dialog_style(style_t * st, dialog_t *dlg); | 
|---|
| 214 | static resource_t *build_stt_resources(stringtable_t *stthead); | 
|---|
| 215 | static stringtable_t *find_stringtable(lvc_t *lvc); | 
|---|
| 216 | static toolbar_item_t *ins_tlbr_button(toolbar_item_t *prev, toolbar_item_t *idrec); | 
|---|
| 217 | static toolbar_item_t *get_tlbr_buttons_head(toolbar_item_t *p, int *nitems); | 
|---|
| 218 | static string_t *make_filename(string_t *s); | 
|---|
| 219 | static resource_t *build_fontdirs(resource_t *tail); | 
|---|
| 220 | static resource_t *build_fontdir(resource_t **fnt, int nfnt); | 
|---|
| 221 | static int rsrcid_to_token(int lookahead); | 
|---|
| 222 |  | 
|---|
| 223 | %} | 
|---|
| 224 | %union{ | 
|---|
| 225 | string_t        *str; | 
|---|
| 226 | int             num; | 
|---|
| 227 | int             *iptr; | 
|---|
| 228 | char            *cptr; | 
|---|
| 229 | resource_t      *res; | 
|---|
| 230 | accelerator_t   *acc; | 
|---|
| 231 | bitmap_t        *bmp; | 
|---|
| 232 | dialog_t        *dlg; | 
|---|
| 233 | dialogex_t      *dlgex; | 
|---|
| 234 | font_t          *fnt; | 
|---|
| 235 | fontdir_t       *fnd; | 
|---|
| 236 | menu_t          *men; | 
|---|
| 237 | menuex_t        *menex; | 
|---|
| 238 | rcdata_t        *rdt; | 
|---|
| 239 | stringtable_t   *stt; | 
|---|
| 240 | stt_entry_t     *stte; | 
|---|
| 241 | user_t          *usr; | 
|---|
| 242 | messagetable_t  *msg; | 
|---|
| 243 | versioninfo_t   *veri; | 
|---|
| 244 | control_t       *ctl; | 
|---|
| 245 | name_id_t       *nid; | 
|---|
| 246 | font_id_t       *fntid; | 
|---|
| 247 | language_t      *lan; | 
|---|
| 248 | version_t       *ver; | 
|---|
| 249 | characts_t      *chars; | 
|---|
| 250 | event_t         *event; | 
|---|
| 251 | menu_item_t     *menitm; | 
|---|
| 252 | menuex_item_t   *menexitm; | 
|---|
| 253 | itemex_opt_t    *exopt; | 
|---|
| 254 | raw_data_t      *raw; | 
|---|
| 255 | lvc_t           *lvc; | 
|---|
| 256 | ver_value_t     *val; | 
|---|
| 257 | ver_block_t     *blk; | 
|---|
| 258 | ver_words_t     *verw; | 
|---|
| 259 | toolbar_t       *tlbar; | 
|---|
| 260 | toolbar_item_t  *tlbarItems; | 
|---|
| 261 | dlginit_t       *dginit; | 
|---|
| 262 | style_pair_t    *styles; | 
|---|
| 263 | style_t         *style; | 
|---|
| 264 | ani_any_t       *ani; | 
|---|
| 265 | } | 
|---|
| 266 |  | 
|---|
| 267 | %token tTYPEDEF tEXTERN tSTRUCT tENUM tCPPCLASS tINLINE tSTATIC tNL | 
|---|
| 268 | %token <num> tNUMBER tLNUMBER | 
|---|
| 269 | %token <str> tSTRING tIDENT tFILENAME | 
|---|
| 270 | %token <raw> tRAWDATA | 
|---|
| 271 | %token tACCELERATORS tBITMAP tCURSOR tDIALOG tDIALOGEX tMENU tMENUEX tMESSAGETABLE | 
|---|
| 272 | %token tRCDATA tVERSIONINFO tSTRINGTABLE tFONT tFONTDIR tICON | 
|---|
| 273 | %token tAUTO3STATE tAUTOCHECKBOX tAUTORADIOBUTTON tCHECKBOX tDEFPUSHBUTTON | 
|---|
| 274 | %token tPUSHBUTTON tRADIOBUTTON tSTATE3 /* PUSHBOX */ | 
|---|
| 275 | %token tGROUPBOX tCOMBOBOX tLISTBOX tSCROLLBAR | 
|---|
| 276 | %token tCONTROL tEDITTEXT | 
|---|
| 277 | %token tRTEXT tCTEXT tLTEXT | 
|---|
| 278 | %token tBLOCK tVALUE | 
|---|
| 279 | %token tSHIFT tALT tASCII tVIRTKEY tGRAYED tCHECKED tINACTIVE tNOINVERT | 
|---|
| 280 | %token tPURE tIMPURE tDISCARDABLE tLOADONCALL tPRELOAD tFIXED tMOVEABLE | 
|---|
| 281 | %token tCLASS tCAPTION tCHARACTERISTICS tEXSTYLE tSTYLE tVERSION tLANGUAGE | 
|---|
| 282 | %token tFILEVERSION tPRODUCTVERSION tFILEFLAGSMASK tFILEOS tFILETYPE tFILEFLAGS tFILESUBTYPE | 
|---|
| 283 | %token tMENUBARBREAK tMENUBREAK tMENUITEM tPOPUP tSEPARATOR | 
|---|
| 284 | %token tHELP | 
|---|
| 285 | %token tSTRING tIDENT tRAWDATA | 
|---|
| 286 | %token tTOOLBAR tBUTTON | 
|---|
| 287 | %token tBEGIN tEND | 
|---|
| 288 | %token tDLGINIT | 
|---|
| 289 | %left '|' | 
|---|
| 290 | %left '^' | 
|---|
| 291 | %left '&' | 
|---|
| 292 | %left '+' '-' | 
|---|
| 293 | %left '*' '/' | 
|---|
| 294 | %right '~' tNOT | 
|---|
| 295 | %left pUPM | 
|---|
| 296 |  | 
|---|
| 297 | %type <res>     resource_file resource resources resource_definition | 
|---|
| 298 | %type <stt>     stringtable strings | 
|---|
| 299 | %type <fnt>     font | 
|---|
| 300 | %type <fnd>     fontdir | 
|---|
| 301 | %type <acc>     accelerators | 
|---|
| 302 | %type <event>   events | 
|---|
| 303 | %type <bmp>     bitmap | 
|---|
| 304 | %type <ani>     cursor icon | 
|---|
| 305 | %type <dlg>     dialog dlg_attributes | 
|---|
| 306 | %type <ctl>     ctrls gen_ctrl lab_ctrl ctrl_desc iconinfo | 
|---|
| 307 | %type <iptr>    helpid | 
|---|
| 308 | %type <dlgex>   dialogex dlgex_attribs | 
|---|
| 309 | %type <ctl>     exctrls gen_exctrl lab_exctrl exctrl_desc | 
|---|
| 310 | %type <rdt>     rcdata | 
|---|
| 311 | %type <raw>     raw_data raw_elements opt_data file_raw | 
|---|
| 312 | %type <veri>    versioninfo fix_version | 
|---|
| 313 | %type <verw>    ver_words | 
|---|
| 314 | %type <blk>     ver_blocks ver_block | 
|---|
| 315 | %type <val>     ver_values ver_value | 
|---|
| 316 | %type <men>     menu | 
|---|
| 317 | %type <menitm>  item_definitions menu_body | 
|---|
| 318 | %type <menex>   menuex | 
|---|
| 319 | %type <menexitm> itemex_definitions menuex_body | 
|---|
| 320 | %type <exopt>   itemex_p_options itemex_options | 
|---|
| 321 | %type <msg>     messagetable | 
|---|
| 322 | %type <usr>     userres | 
|---|
| 323 | %type <num>     item_options | 
|---|
| 324 | %type <nid>     nameid nameid_s ctlclass usertype | 
|---|
| 325 | %type <num>     acc_opt acc accs | 
|---|
| 326 | %type <iptr>    loadmemopts lamo lama | 
|---|
| 327 | %type <fntid>   opt_font opt_exfont opt_expr | 
|---|
| 328 | %type <lvc>     opt_lvc | 
|---|
| 329 | %type <lan>     opt_language | 
|---|
| 330 | %type <chars>   opt_characts | 
|---|
| 331 | %type <ver>     opt_version | 
|---|
| 332 | %type <num>     expr xpr | 
|---|
| 333 | %type <iptr>    e_expr | 
|---|
| 334 | %type <tlbar>   toolbar | 
|---|
| 335 | %type <tlbarItems>      toolbar_items | 
|---|
| 336 | %type <dginit>  dlginit | 
|---|
| 337 | %type <styles>  optional_style_pair | 
|---|
| 338 | %type <num>     any_num | 
|---|
| 339 | %type <style>   optional_style | 
|---|
| 340 | %type <style>   style | 
|---|
| 341 | %type <str>     filename | 
|---|
| 342 |  | 
|---|
| 343 | %% | 
|---|
| 344 |  | 
|---|
| 345 | resource_file | 
|---|
| 346 | : resources { | 
|---|
| 347 | resource_t *rsc; | 
|---|
| 348 | /* First add stringtables to the resource-list */ | 
|---|
| 349 | rsc = build_stt_resources(sttres); | 
|---|
| 350 | /* 'build_stt_resources' returns a head and $1 is a tail */ | 
|---|
| 351 | if($1) | 
|---|
| 352 | { | 
|---|
| 353 | $1->next = rsc; | 
|---|
| 354 | if(rsc) | 
|---|
| 355 | rsc->prev = $1; | 
|---|
| 356 | } | 
|---|
| 357 | else | 
|---|
| 358 | $1 = rsc; | 
|---|
| 359 | /* Find the tail again */ | 
|---|
| 360 | while($1 && $1->next) | 
|---|
| 361 | $1 = $1->next; | 
|---|
| 362 | /* Now add any fontdirecory */ | 
|---|
| 363 | rsc = build_fontdirs($1); | 
|---|
| 364 | /* 'build_fontdir' returns a head and $1 is a tail */ | 
|---|
| 365 | if($1) | 
|---|
| 366 | { | 
|---|
| 367 | $1->next = rsc; | 
|---|
| 368 | if(rsc) | 
|---|
| 369 | rsc->prev = $1; | 
|---|
| 370 | } | 
|---|
| 371 | else | 
|---|
| 372 | $1 = rsc; | 
|---|
| 373 | /* Final statement before were done */ | 
|---|
| 374 | resource_top = get_resource_head($1); | 
|---|
| 375 | } | 
|---|
| 376 | ; | 
|---|
| 377 |  | 
|---|
| 378 | /* Resources are put into a linked list */ | 
|---|
| 379 | resources | 
|---|
| 380 | : /* Empty */           { $$ = NULL; want_id = 1; } | 
|---|
| 381 | | resources resource    { | 
|---|
| 382 | if($2) | 
|---|
| 383 | { | 
|---|
| 384 | resource_t *tail = $2; | 
|---|
| 385 | resource_t *head = $2; | 
|---|
| 386 | while(tail->next) | 
|---|
| 387 | tail = tail->next; | 
|---|
| 388 | while(head->prev) | 
|---|
| 389 | head = head->prev; | 
|---|
| 390 | head->prev = $1; | 
|---|
| 391 | if($1) | 
|---|
| 392 | $1->next = head; | 
|---|
| 393 | $$ = tail; | 
|---|
| 394 | /* Check for duplicate identifiers */ | 
|---|
| 395 | while($1 && head) | 
|---|
| 396 | { | 
|---|
| 397 | resource_t *rsc = $1; | 
|---|
| 398 | while(rsc) | 
|---|
| 399 | { | 
|---|
| 400 | if(rsc->type == head->type | 
|---|
| 401 | && rsc->lan->id == head->lan->id | 
|---|
| 402 | && rsc->lan->sub == head->lan->sub | 
|---|
| 403 | && !compare_name_id(rsc->name, head->name)) | 
|---|
| 404 | { | 
|---|
| 405 | yyerror("Duplicate resource name '%s'", get_nameid_str(rsc->name)); | 
|---|
| 406 | } | 
|---|
| 407 | rsc = rsc->prev; | 
|---|
| 408 | } | 
|---|
| 409 | head = head->next; | 
|---|
| 410 | } | 
|---|
| 411 | } | 
|---|
| 412 | else if($1) | 
|---|
| 413 | { | 
|---|
| 414 | resource_t *tail = $1; | 
|---|
| 415 | while(tail->next) | 
|---|
| 416 | tail = tail->next; | 
|---|
| 417 | $$ = tail; | 
|---|
| 418 | } | 
|---|
| 419 | else | 
|---|
| 420 | $$ = NULL; | 
|---|
| 421 |  | 
|---|
| 422 | if(!dont_want_id)       /* See comments in language parsing below */ | 
|---|
| 423 | want_id = 1; | 
|---|
| 424 | dont_want_id = 0; | 
|---|
| 425 | } | 
|---|
| 426 | | resources cjunk                       { $$ = $1; want_id = 1; } | 
|---|
| 427 | ; | 
|---|
| 428 |  | 
|---|
| 429 |  | 
|---|
| 430 | /* C ignore stuff */ | 
|---|
| 431 | cjunk   : tTYPEDEF                      { strip_til_semicolon(); } | 
|---|
| 432 | | tSTRUCT                       { strip_til_semicolon(); } | 
|---|
| 433 | | tEXTERN                       { strip_til_semicolon(); } | 
|---|
| 434 | | tENUM                         { strip_til_semicolon(); } | 
|---|
| 435 | | tCPPCLASS                     { strip_til_semicolon(); } | 
|---|
| 436 | | tSTATIC                       { strip_til_semicolon(); } | 
|---|
| 437 | | tINLINE                       { internal_error(__FILE__, __LINE__, "Don't yet know how to strip inline functions\n"); } | 
|---|
| 438 | /*      | tIDENT tIDENT                 { strip_til_semicolon(); } */ | 
|---|
| 439 | /*      | tIDENT tIDENT '('             { strip_til_parenthesis(); } See comments in 'resource' below */ | 
|---|
| 440 | /*      | tIDENT '('                    { strip_til_parenthesis(); } */ | 
|---|
| 441 | | tIDENT '*'                    { strip_til_semicolon(); } | 
|---|
| 442 | | tNL   /* | 
|---|
| 443 | * This newline rule will never get reduced because we never | 
|---|
| 444 | * get the tNL token, unless we explicitely set the 'want_nl' | 
|---|
| 445 | * flag, which we don't. | 
|---|
| 446 | * The *ONLY* reason for this to be here is because Berkeley | 
|---|
| 447 | * yacc (byacc), at least version 1.9, has a bug. | 
|---|
| 448 | * (identified in the generated parser on the second | 
|---|
| 449 | *  line with: | 
|---|
| 450 | *  static char yysccsid[] = "@(#)yaccpar   1.9 (Berkeley) 02/21/93"; | 
|---|
| 451 | * ) | 
|---|
| 452 | * This extra rule fixes it. | 
|---|
| 453 | * The problem is that the expression handling rule "expr: xpr" | 
|---|
| 454 | * is not reduced on non-terminal tokens, defined above in the | 
|---|
| 455 | * %token declarations. Token tNL is the only non-terminal that | 
|---|
| 456 | * can occur. The error becomes visible in the language parsing | 
|---|
| 457 | * rule below, which looks at the look-ahead token and tests it | 
|---|
| 458 | * for tNL. However, byacc already generates an error upon reading | 
|---|
| 459 | * the token instead of keeping it as a lookahead. The reason | 
|---|
| 460 | * lies in the lack of a $default transition in the "expr : xpr . " | 
|---|
| 461 | * state (currently state 25). It is probably ommitted because tNL | 
|---|
| 462 | * is a non-terminal and the state contains 2 s/r conflicts. The | 
|---|
| 463 | * state enumerates all possible transitions instead of using a | 
|---|
| 464 | * $default transition. | 
|---|
| 465 | * All in all, it is a bug in byacc. (period) | 
|---|
| 466 | */ | 
|---|
| 467 | ; | 
|---|
| 468 |  | 
|---|
| 469 | /* Parse top level resource definitions etc. */ | 
|---|
| 470 | resource | 
|---|
| 471 | : expr usrcvt resource_definition { | 
|---|
| 472 | $$ = $3; | 
|---|
| 473 | if($$) | 
|---|
| 474 | { | 
|---|
| 475 | if($1 > 65535 || $1 < -32768) | 
|---|
| 476 | yyerror("Resource's ID out of range (%d)", $1); | 
|---|
| 477 | $$->name = new_name_id(); | 
|---|
| 478 | $$->name->type = name_ord; | 
|---|
| 479 | $$->name->name.i_name = $1; | 
|---|
| 480 | chat("Got %s (%d)", get_typename($3), $$->name->name.i_name); | 
|---|
| 481 | } | 
|---|
| 482 | } | 
|---|
| 483 | | tIDENT usrcvt resource_definition { | 
|---|
| 484 | $$ = $3; | 
|---|
| 485 | if($$) | 
|---|
| 486 | { | 
|---|
| 487 | $$->name = new_name_id(); | 
|---|
| 488 | $$->name->type = name_str; | 
|---|
| 489 | $$->name->name.s_name = $1; | 
|---|
| 490 | chat("Got %s (%s)", get_typename($3), $$->name->name.s_name->str.cstr); | 
|---|
| 491 | } | 
|---|
| 492 | } | 
|---|
| 493 | | tIDENT usrcvt tIDENT '('      { /* cjunk */ strip_til_parenthesis(); $$ = NULL; } | 
|---|
| 494 | /* The above rule is inserted here with explicit tIDENT | 
|---|
| 495 | * references to avoid a nasty LALR(2) problem when | 
|---|
| 496 | * considering the 'cjunk' rules with respect to the usertype | 
|---|
| 497 | * resources. | 
|---|
| 498 | * A usertype resource can have two leading identifiers before | 
|---|
| 499 | * it qualifies as shift into usertype rules. However, the | 
|---|
| 500 | * cjunk scanner also has a rule of two leading identifiers. | 
|---|
| 501 | * The problem occurs because the second identifier is at the | 
|---|
| 502 | * second lookahead (hence LALR(2)) seen from the recursion | 
|---|
| 503 | * rule 'resources'. | 
|---|
| 504 | * Thus, the scanner will pick *one* of the rules in preference | 
|---|
| 505 | * of the other (in this case it was 'cjunk') and generates a | 
|---|
| 506 | * syntax error if the trailing context wasn't seen. The | 
|---|
| 507 | * correct action would have been to rollback the stack and | 
|---|
| 508 | * decent into the 'userres' rule, but this cannot be done | 
|---|
| 509 | * because yacc only parses LALR(1). | 
|---|
| 510 | * The problem is prevented from happening by making the decent | 
|---|
| 511 | * into the cjunk-scanning obsolete and explicitly force the | 
|---|
| 512 | * scanner to require no more than 1 lookahead. | 
|---|
| 513 | */ | 
|---|
| 514 | | stringtable { | 
|---|
| 515 | /* Don't do anything, stringtables are converted to | 
|---|
| 516 | * resource_t structures when we are finished parsing and | 
|---|
| 517 | * the final rule of the parser is reduced (see above) | 
|---|
| 518 | */ | 
|---|
| 519 | $$ = NULL; | 
|---|
| 520 | chat("Got STRINGTABLE"); | 
|---|
| 521 | } | 
|---|
| 522 | | tLANGUAGE {want_nl = 1; } expr ',' expr { | 
|---|
| 523 | /* We *NEED* the newline to delimit the expression. | 
|---|
| 524 | * Otherwise, we would not be able to set the next | 
|---|
| 525 | * want_id anymore because of the token-lookahead. | 
|---|
| 526 | * | 
|---|
| 527 | * However, we can test the lookahead-token for | 
|---|
| 528 | * being "non-expression" type, in which case we | 
|---|
| 529 | * continue. Fortunately, tNL is the only token that | 
|---|
| 530 | * will break expression parsing and is implicitely | 
|---|
| 531 | * void, so we just remove it. This scheme makes it | 
|---|
| 532 | * possible to do some (not all) fancy preprocessor | 
|---|
| 533 | * stuff. | 
|---|
| 534 | * BTW, we also need to make sure that the next | 
|---|
| 535 | * reduction of 'resources' above will *not* set | 
|---|
| 536 | * want_id because we already have a lookahead that | 
|---|
| 537 | * cannot be undone. | 
|---|
| 538 | */ | 
|---|
| 539 | if(yychar != YYEMPTY && yychar != tNL) | 
|---|
| 540 | dont_want_id = 1; | 
|---|
| 541 |  | 
|---|
| 542 | if(yychar == tNL) | 
|---|
| 543 | yychar = YYEMPTY;       /* Could use 'yyclearin', but we already need the*/ | 
|---|
| 544 | /* direct access to yychar in rule 'usrcvt' below. */ | 
|---|
| 545 | else if(yychar == tIDENT) | 
|---|
| 546 | yywarning("LANGUAGE statement not delimited with newline; next identifier might be wrong"); | 
|---|
| 547 |  | 
|---|
| 548 | want_nl = 0;    /* We don't want it anymore if we didn't get it */ | 
|---|
| 549 |  | 
|---|
| 550 | if(!win32) | 
|---|
| 551 | yywarning("LANGUAGE not supported in 16-bit mode"); | 
|---|
| 552 | if(currentlanguage) | 
|---|
| 553 | free(currentlanguage); | 
|---|
| 554 | currentlanguage = new_language($3, $5); | 
|---|
| 555 | $$ = NULL; | 
|---|
| 556 | chat("Got LANGUAGE %d,%d (0x%04x)", $3, $5, ($5<<10) + $3); | 
|---|
| 557 | } | 
|---|
| 558 | ; | 
|---|
| 559 |  | 
|---|
| 560 | /* | 
|---|
| 561 | * Remapping of numerical resource types | 
|---|
| 562 | * (see also comment of called function below) | 
|---|
| 563 | */ | 
|---|
| 564 | usrcvt  : /* Empty */   { yychar = rsrcid_to_token(yychar); } | 
|---|
| 565 | ; | 
|---|
| 566 |  | 
|---|
| 567 | /* | 
|---|
| 568 | * Get a valid name/id | 
|---|
| 569 | */ | 
|---|
| 570 | nameid  : expr  { | 
|---|
| 571 | if($1 > 65535 || $1 < -32768) | 
|---|
| 572 | yyerror("Resource's ID out of range (%d)", $1); | 
|---|
| 573 | $$ = new_name_id(); | 
|---|
| 574 | $$->type = name_ord; | 
|---|
| 575 | $$->name.i_name = $1; | 
|---|
| 576 | } | 
|---|
| 577 | | tIDENT { | 
|---|
| 578 | $$ = new_name_id(); | 
|---|
| 579 | $$->type = name_str; | 
|---|
| 580 | $$->name.s_name = $1; | 
|---|
| 581 | } | 
|---|
| 582 | ; | 
|---|
| 583 |  | 
|---|
| 584 | /* | 
|---|
| 585 | * Extra string recognition for CLASS statement in dialogs | 
|---|
| 586 | */ | 
|---|
| 587 | nameid_s: nameid        { $$ = $1; } | 
|---|
| 588 | | tSTRING       { | 
|---|
| 589 | $$ = new_name_id(); | 
|---|
| 590 | $$->type = name_str; | 
|---|
| 591 | $$->name.s_name = $1; | 
|---|
| 592 | } | 
|---|
| 593 | ; | 
|---|
| 594 |  | 
|---|
| 595 | /* get the value for a single resource*/ | 
|---|
| 596 | resource_definition | 
|---|
| 597 | : accelerators  { $$ = new_resource(res_acc, $1, $1->memopt, $1->lvc.language); } | 
|---|
| 598 | | bitmap        { $$ = new_resource(res_bmp, $1, $1->memopt, $1->data->lvc.language); } | 
|---|
| 599 | | cursor { | 
|---|
| 600 | resource_t *rsc; | 
|---|
| 601 | if($1->type == res_anicur) | 
|---|
| 602 | { | 
|---|
| 603 | $$ = rsc = new_resource(res_anicur, $1->u.ani, $1->u.ani->memopt, $1->u.ani->data->lvc.language); | 
|---|
| 604 | } | 
|---|
| 605 | else if($1->type == res_curg) | 
|---|
| 606 | { | 
|---|
| 607 | cursor_t *cur; | 
|---|
| 608 | $$ = rsc = new_resource(res_curg, $1->u.curg, $1->u.curg->memopt, $1->u.curg->lvc.language); | 
|---|
| 609 | for(cur = $1->u.curg->cursorlist; cur; cur = cur->next) | 
|---|
| 610 | { | 
|---|
| 611 | rsc->prev = new_resource(res_cur, cur, $1->u.curg->memopt, $1->u.curg->lvc.language); | 
|---|
| 612 | rsc->prev->next = rsc; | 
|---|
| 613 | rsc = rsc->prev; | 
|---|
| 614 | rsc->name = new_name_id(); | 
|---|
| 615 | rsc->name->type = name_ord; | 
|---|
| 616 | rsc->name->name.i_name = cur->id; | 
|---|
| 617 | } | 
|---|
| 618 | } | 
|---|
| 619 | else | 
|---|
| 620 | internal_error(__FILE__, __LINE__, "Invalid top-level type %d in cursor resource", $1->type); | 
|---|
| 621 | free($1); | 
|---|
| 622 | } | 
|---|
| 623 | | dialog        { $$ = new_resource(res_dlg, $1, $1->memopt, $1->lvc.language); } | 
|---|
| 624 | | dialogex { | 
|---|
| 625 | if(win32) | 
|---|
| 626 | $$ = new_resource(res_dlgex, $1, $1->memopt, $1->lvc.language); | 
|---|
| 627 | else | 
|---|
| 628 | $$ = NULL; | 
|---|
| 629 | } | 
|---|
| 630 | | dlginit       { $$ = new_resource(res_dlginit, $1, $1->memopt, $1->data->lvc.language); } | 
|---|
| 631 | | font          { $$ = new_resource(res_fnt, $1, $1->memopt, $1->data->lvc.language); } | 
|---|
| 632 | | fontdir       { $$ = new_resource(res_fntdir, $1, $1->memopt, $1->data->lvc.language); } | 
|---|
| 633 | | icon { | 
|---|
| 634 | resource_t *rsc; | 
|---|
| 635 | if($1->type == res_aniico) | 
|---|
| 636 | { | 
|---|
| 637 | $$ = rsc = new_resource(res_aniico, $1->u.ani, $1->u.ani->memopt, $1->u.ani->data->lvc.language); | 
|---|
| 638 | } | 
|---|
| 639 | else if($1->type == res_icog) | 
|---|
| 640 | { | 
|---|
| 641 | icon_t *ico; | 
|---|
| 642 | $$ = rsc = new_resource(res_icog, $1->u.icog, $1->u.icog->memopt, $1->u.icog->lvc.language); | 
|---|
| 643 | for(ico = $1->u.icog->iconlist; ico; ico = ico->next) | 
|---|
| 644 | { | 
|---|
| 645 | rsc->prev = new_resource(res_ico, ico, $1->u.icog->memopt, $1->u.icog->lvc.language); | 
|---|
| 646 | rsc->prev->next = rsc; | 
|---|
| 647 | rsc = rsc->prev; | 
|---|
| 648 | rsc->name = new_name_id(); | 
|---|
| 649 | rsc->name->type = name_ord; | 
|---|
| 650 | rsc->name->name.i_name = ico->id; | 
|---|
| 651 | } | 
|---|
| 652 | } | 
|---|
| 653 | else | 
|---|
| 654 | internal_error(__FILE__, __LINE__, "Invalid top-level type %d in icon resource", $1->type); | 
|---|
| 655 | free($1); | 
|---|
| 656 | } | 
|---|
| 657 | | menu          { $$ = new_resource(res_men, $1, $1->memopt, $1->lvc.language); } | 
|---|
| 658 | | menuex { | 
|---|
| 659 | if(win32) | 
|---|
| 660 | $$ = new_resource(res_menex, $1, $1->memopt, $1->lvc.language); | 
|---|
| 661 | else | 
|---|
| 662 | $$ = NULL; | 
|---|
| 663 | } | 
|---|
| 664 | | messagetable  { $$ = new_resource(res_msg, $1, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, dup_language(currentlanguage)); } | 
|---|
| 665 | | rcdata        { $$ = new_resource(res_rdt, $1, $1->memopt, $1->data->lvc.language); } | 
|---|
| 666 | | toolbar       { $$ = new_resource(res_toolbar, $1, $1->memopt, $1->lvc.language); } | 
|---|
| 667 | | userres       { $$ = new_resource(res_usr, $1, $1->memopt, $1->data->lvc.language); } | 
|---|
| 668 | | versioninfo   { $$ = new_resource(res_ver, $1, WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE, $1->lvc.language); } | 
|---|
| 669 | ; | 
|---|
| 670 |  | 
|---|
| 671 |  | 
|---|
| 672 | filename: tFILENAME     { $$ = make_filename($1); } | 
|---|
| 673 | | tIDENT        { $$ = make_filename($1); } | 
|---|
| 674 | | tSTRING       { $$ = make_filename($1); } | 
|---|
| 675 | ; | 
|---|
| 676 |  | 
|---|
| 677 | /* ------------------------------ Bitmap ------------------------------ */ | 
|---|
| 678 | bitmap  : tBITMAP loadmemopts file_raw  { $$ = new_bitmap($3, $2); } | 
|---|
| 679 | ; | 
|---|
| 680 |  | 
|---|
| 681 | /* ------------------------------ Cursor ------------------------------ */ | 
|---|
| 682 | cursor  : tCURSOR loadmemopts file_raw  { | 
|---|
| 683 | $$ = new_ani_any(); | 
|---|
| 684 | if($3->size > 4 && !memcmp($3->data, riff, sizeof(riff))) | 
|---|
| 685 | { | 
|---|
| 686 | $$->type = res_anicur; | 
|---|
| 687 | $$->u.ani = new_ani_curico(res_anicur, $3, $2); | 
|---|
| 688 | } | 
|---|
| 689 | else | 
|---|
| 690 | { | 
|---|
| 691 | $$->type = res_curg; | 
|---|
| 692 | $$->u.curg = new_cursor_group($3, $2); | 
|---|
| 693 | } | 
|---|
| 694 | } | 
|---|
| 695 | ; | 
|---|
| 696 |  | 
|---|
| 697 | /* ------------------------------ Icon ------------------------------ */ | 
|---|
| 698 | icon    : tICON loadmemopts file_raw    { | 
|---|
| 699 | $$ = new_ani_any(); | 
|---|
| 700 | if($3->size > 4 && !memcmp($3->data, riff, sizeof(riff))) | 
|---|
| 701 | { | 
|---|
| 702 | $$->type = res_aniico; | 
|---|
| 703 | $$->u.ani = new_ani_curico(res_aniico, $3, $2); | 
|---|
| 704 | } | 
|---|
| 705 | else | 
|---|
| 706 | { | 
|---|
| 707 | $$->type = res_icog; | 
|---|
| 708 | $$->u.icog = new_icon_group($3, $2); | 
|---|
| 709 | } | 
|---|
| 710 | } | 
|---|
| 711 | ; | 
|---|
| 712 |  | 
|---|
| 713 | /* ------------------------------ Font ------------------------------ */ | 
|---|
| 714 | /* | 
|---|
| 715 | * The reading of raw_data for fonts is a Borland BRC | 
|---|
| 716 | * extension. MS generates an error. However, it is | 
|---|
| 717 | * most logical to support this, considering how wine | 
|---|
| 718 | * enters things in CVS (ascii). | 
|---|
| 719 | */ | 
|---|
| 720 | font    : tFONT loadmemopts file_raw    { $$ = new_font($3, $2); } | 
|---|
| 721 | ; | 
|---|
| 722 |  | 
|---|
| 723 | /* | 
|---|
| 724 | * The fontdir is a Borland BRC extension which only | 
|---|
| 725 | * reads the data as 'raw_data' from the file. | 
|---|
| 726 | * I don't know whether it is interpreted. | 
|---|
| 727 | * The fontdir is generated if it was not present and | 
|---|
| 728 | * fonts are defined in the source. | 
|---|
| 729 | */ | 
|---|
| 730 | fontdir : tFONTDIR loadmemopts file_raw { $$ = new_fontdir($3, $2); } | 
|---|
| 731 | ; | 
|---|
| 732 |  | 
|---|
| 733 | /* ------------------------------ MessageTable ------------------------------ */ | 
|---|
| 734 | /* It might be interesting to implement the MS Message compiler here as well | 
|---|
| 735 | * to get everything in one source. Might be a future project. | 
|---|
| 736 | */ | 
|---|
| 737 | messagetable | 
|---|
| 738 | : tMESSAGETABLE loadmemopts file_raw    { | 
|---|
| 739 | if(!win32) | 
|---|
| 740 | yywarning("MESSAGETABLE not supported in 16-bit mode"); | 
|---|
| 741 | $$ = new_messagetable($3, $2); | 
|---|
| 742 | } | 
|---|
| 743 | ; | 
|---|
| 744 |  | 
|---|
| 745 | /* ------------------------------ RCData ------------------------------ */ | 
|---|
| 746 | rcdata  : tRCDATA loadmemopts file_raw  { $$ = new_rcdata($3, $2); } | 
|---|
| 747 | ; | 
|---|
| 748 |  | 
|---|
| 749 | /* ------------------------------ DLGINIT ------------------------------ */ | 
|---|
| 750 | dlginit : tDLGINIT loadmemopts file_raw { $$ = new_dlginit($3, $2); } | 
|---|
| 751 | ; | 
|---|
| 752 |  | 
|---|
| 753 | /* ------------------------------ UserType ------------------------------ */ | 
|---|
| 754 | userres : usertype loadmemopts file_raw         { | 
|---|
| 755 | #ifdef WORDS_BIGENDIAN | 
|---|
| 756 | if(pedantic && byteorder != WRC_BO_LITTLE) | 
|---|
| 757 | #else | 
|---|
| 758 | if(pedantic && byteorder == WRC_BO_BIG) | 
|---|
| 759 | #endif | 
|---|
| 760 | yywarning("Byteordering is not little-endian and type cannot be interpreted"); | 
|---|
| 761 | $$ = new_user($1, $3, $2); | 
|---|
| 762 | } | 
|---|
| 763 | ; | 
|---|
| 764 |  | 
|---|
| 765 | usertype: tNUMBER { | 
|---|
| 766 | $$ = new_name_id(); | 
|---|
| 767 | $$->type = name_ord; | 
|---|
| 768 | $$->name.i_name = $1; | 
|---|
| 769 | } | 
|---|
| 770 | | tIDENT { | 
|---|
| 771 | $$ = new_name_id(); | 
|---|
| 772 | $$->type = name_str; | 
|---|
| 773 | $$->name.s_name = $1; | 
|---|
| 774 | } | 
|---|
| 775 | ; | 
|---|
| 776 |  | 
|---|
| 777 | /* ------------------------------ Accelerator ------------------------------ */ | 
|---|
| 778 | accelerators | 
|---|
| 779 | : tACCELERATORS loadmemopts opt_lvc tBEGIN events tEND { | 
|---|
| 780 | $$ = new_accelerator(); | 
|---|
| 781 | if($2) | 
|---|
| 782 | { | 
|---|
| 783 | $$->memopt = *($2); | 
|---|
| 784 | free($2); | 
|---|
| 785 | } | 
|---|
| 786 | else | 
|---|
| 787 | { | 
|---|
| 788 | $$->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE; | 
|---|
| 789 | } | 
|---|
| 790 | if(!$5) | 
|---|
| 791 | yyerror("Accelerator table must have at least one entry"); | 
|---|
| 792 | $$->events = get_event_head($5); | 
|---|
| 793 | if($3) | 
|---|
| 794 | { | 
|---|
| 795 | $$->lvc = *($3); | 
|---|
| 796 | free($3); | 
|---|
| 797 | } | 
|---|
| 798 | if(!$$->lvc.language) | 
|---|
| 799 | $$->lvc.language = dup_language(currentlanguage); | 
|---|
| 800 | } | 
|---|
| 801 | ; | 
|---|
| 802 |  | 
|---|
| 803 | events  : /* Empty */                           { $$=NULL; } | 
|---|
| 804 | | events tSTRING ',' expr acc_opt       { $$=add_string_event($2, $4, $5, $1); } | 
|---|
| 805 | | events expr ',' expr acc_opt          { $$=add_event($2, $4, $5, $1); } | 
|---|
| 806 | ; | 
|---|
| 807 |  | 
|---|
| 808 | /* | 
|---|
| 809 | * The empty rule generates a s/r conflict because of {bi,u}nary expr | 
|---|
| 810 | * on - and +. It cannot be solved in any way because it is the same as | 
|---|
| 811 | * the if/then/else problem (LALR(1) problem). The conflict is moved | 
|---|
| 812 | * away by forcing it to be in the expression handling below. | 
|---|
| 813 | */ | 
|---|
| 814 | acc_opt : /* Empty */   { $$ = 0; } | 
|---|
| 815 | | ',' accs      { $$ = $2; } | 
|---|
| 816 | ; | 
|---|
| 817 |  | 
|---|
| 818 | accs    : acc           { $$ = $1; } | 
|---|
| 819 | | accs ',' acc  { $$ = $1 | $3; } | 
|---|
| 820 | ; | 
|---|
| 821 |  | 
|---|
| 822 | acc     : tNOINVERT     { $$ = WRC_AF_NOINVERT; } | 
|---|
| 823 | | tSHIFT        { $$ = WRC_AF_SHIFT; } | 
|---|
| 824 | | tCONTROL      { $$ = WRC_AF_CONTROL; } | 
|---|
| 825 | | tALT          { $$ = WRC_AF_ALT; } | 
|---|
| 826 | | tASCII        { $$ = WRC_AF_ASCII; } | 
|---|
| 827 | | tVIRTKEY      { $$ = WRC_AF_VIRTKEY; } | 
|---|
| 828 | ; | 
|---|
| 829 |  | 
|---|
| 830 | /* ------------------------------ Dialog ------------------------------ */ | 
|---|
| 831 | /* FIXME: Support EXSTYLE in the dialog line itself */ | 
|---|
| 832 | dialog  : tDIALOG loadmemopts expr ',' expr ',' expr ',' expr dlg_attributes | 
|---|
| 833 | tBEGIN  ctrls tEND { | 
|---|
| 834 | if($2) | 
|---|
| 835 | { | 
|---|
| 836 | $10->memopt = *($2); | 
|---|
| 837 | free($2); | 
|---|
| 838 | } | 
|---|
| 839 | else | 
|---|
| 840 | $10->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE; | 
|---|
| 841 | $10->x = $3; | 
|---|
| 842 | $10->y = $5; | 
|---|
| 843 | $10->width = $7; | 
|---|
| 844 | $10->height = $9; | 
|---|
| 845 | $10->controls = get_control_head($12); | 
|---|
| 846 | $$ = $10; | 
|---|
| 847 | if(!$$->gotstyle) | 
|---|
| 848 | { | 
|---|
| 849 | $$->style->or_mask = WS_POPUP; | 
|---|
| 850 | $$->gotstyle = TRUE; | 
|---|
| 851 | } | 
|---|
| 852 | if($$->title) | 
|---|
| 853 | $$->style->or_mask |= WS_CAPTION; | 
|---|
| 854 | if($$->font) | 
|---|
| 855 | $$->style->or_mask |= DS_SETFONT; | 
|---|
| 856 |  | 
|---|
| 857 | $$->style->or_mask &= ~($$->style->and_mask); | 
|---|
| 858 | $$->style->and_mask = 0; | 
|---|
| 859 |  | 
|---|
| 860 | if(!$$->lvc.language) | 
|---|
| 861 | $$->lvc.language = dup_language(currentlanguage); | 
|---|
| 862 | } | 
|---|
| 863 | ; | 
|---|
| 864 |  | 
|---|
| 865 | dlg_attributes | 
|---|
| 866 | : /* Empty */                           { $$=new_dialog(); } | 
|---|
| 867 | | dlg_attributes tSTYLE style           { $$=dialog_style($3,$1); } | 
|---|
| 868 | | dlg_attributes tEXSTYLE style         { $$=dialog_exstyle($3,$1); } | 
|---|
| 869 | | dlg_attributes tCAPTION tSTRING       { $$=dialog_caption($3,$1); } | 
|---|
| 870 | | dlg_attributes opt_font               { $$=dialog_font($2,$1); } | 
|---|
| 871 | | dlg_attributes tCLASS nameid_s        { $$=dialog_class($3,$1); } | 
|---|
| 872 | | dlg_attributes tCPPCLASS nameid_s     { $$=dialog_class($3,$1); } | 
|---|
| 873 | | dlg_attributes tMENU nameid           { $$=dialog_menu($3,$1); } | 
|---|
| 874 | | dlg_attributes opt_language           { $$=dialog_language($2,$1); } | 
|---|
| 875 | | dlg_attributes opt_characts           { $$=dialog_characteristics($2,$1); } | 
|---|
| 876 | | dlg_attributes opt_version            { $$=dialog_version($2,$1); } | 
|---|
| 877 | ; | 
|---|
| 878 |  | 
|---|
| 879 | ctrls   : /* Empty */                           { $$ = NULL; } | 
|---|
| 880 | | ctrls tCONTROL        gen_ctrl        { $$=ins_ctrl(-1, 0, $3, $1); } | 
|---|
| 881 | | ctrls tEDITTEXT       ctrl_desc       { $$=ins_ctrl(CT_EDIT, 0, $3, $1); } | 
|---|
| 882 | | ctrls tLISTBOX        ctrl_desc       { $$=ins_ctrl(CT_LISTBOX, 0, $3, $1); } | 
|---|
| 883 | | ctrls tCOMBOBOX       ctrl_desc       { $$=ins_ctrl(CT_COMBOBOX, 0, $3, $1); } | 
|---|
| 884 | | ctrls tSCROLLBAR      ctrl_desc       { $$=ins_ctrl(CT_SCROLLBAR, 0, $3, $1); } | 
|---|
| 885 | | ctrls tCHECKBOX       lab_ctrl        { $$=ins_ctrl(CT_BUTTON, BS_CHECKBOX, $3, $1); } | 
|---|
| 886 | | ctrls tDEFPUSHBUTTON  lab_ctrl        { $$=ins_ctrl(CT_BUTTON, BS_DEFPUSHBUTTON, $3, $1); } | 
|---|
| 887 | | ctrls tGROUPBOX       lab_ctrl        { $$=ins_ctrl(CT_BUTTON, BS_GROUPBOX, $3, $1);} | 
|---|
| 888 | | ctrls tPUSHBUTTON     lab_ctrl        { $$=ins_ctrl(CT_BUTTON, BS_PUSHBUTTON, $3, $1); } | 
|---|
| 889 | /*      | ctrls tPUSHBOX        lab_ctrl        { $$=ins_ctrl(CT_BUTTON, BS_PUSHBOX, $3, $1); } */ | 
|---|
| 890 | | ctrls tRADIOBUTTON    lab_ctrl        { $$=ins_ctrl(CT_BUTTON, BS_RADIOBUTTON, $3, $1); } | 
|---|
| 891 | | ctrls tAUTO3STATE     lab_ctrl        { $$=ins_ctrl(CT_BUTTON, BS_AUTO3STATE, $3, $1); } | 
|---|
| 892 | | ctrls tSTATE3         lab_ctrl        { $$=ins_ctrl(CT_BUTTON, BS_3STATE, $3, $1); } | 
|---|
| 893 | | ctrls tAUTOCHECKBOX   lab_ctrl        { $$=ins_ctrl(CT_BUTTON, BS_AUTOCHECKBOX, $3, $1); } | 
|---|
| 894 | | ctrls tAUTORADIOBUTTON lab_ctrl       { $$=ins_ctrl(CT_BUTTON, BS_AUTORADIOBUTTON, $3, $1); } | 
|---|
| 895 | | ctrls tLTEXT          lab_ctrl        { $$=ins_ctrl(CT_STATIC, SS_LEFT, $3, $1); } | 
|---|
| 896 | | ctrls tCTEXT          lab_ctrl        { $$=ins_ctrl(CT_STATIC, SS_CENTER, $3, $1); } | 
|---|
| 897 | | ctrls tRTEXT          lab_ctrl        { $$=ins_ctrl(CT_STATIC, SS_RIGHT, $3, $1); } | 
|---|
| 898 | /* special treatment for icons, as the extent is optional */ | 
|---|
| 899 | | ctrls tICON nameid_s opt_comma expr ',' expr ',' expr iconinfo { | 
|---|
| 900 | $10->title = $3; | 
|---|
| 901 | $10->id = $5; | 
|---|
| 902 | $10->x = $7; | 
|---|
| 903 | $10->y = $9; | 
|---|
| 904 | $$ = ins_ctrl(CT_STATIC, SS_ICON, $10, $1); | 
|---|
| 905 | } | 
|---|
| 906 | ; | 
|---|
| 907 |  | 
|---|
| 908 | lab_ctrl | 
|---|
| 909 | : tSTRING opt_comma expr ',' expr ',' expr ',' expr ',' expr optional_style { | 
|---|
| 910 | $$=new_control(); | 
|---|
| 911 | $$->title = new_name_id(); | 
|---|
| 912 | $$->title->type = name_str; | 
|---|
| 913 | $$->title->name.s_name = $1; | 
|---|
| 914 | $$->id = $3; | 
|---|
| 915 | $$->x = $5; | 
|---|
| 916 | $$->y = $7; | 
|---|
| 917 | $$->width = $9; | 
|---|
| 918 | $$->height = $11; | 
|---|
| 919 | if($12) | 
|---|
| 920 | { | 
|---|
| 921 | $$->style = $12; | 
|---|
| 922 | $$->gotstyle = TRUE; | 
|---|
| 923 | } | 
|---|
| 924 | } | 
|---|
| 925 | ; | 
|---|
| 926 |  | 
|---|
| 927 | ctrl_desc | 
|---|
| 928 | : expr ',' expr ',' expr ',' expr ',' expr optional_style { | 
|---|
| 929 | $$ = new_control(); | 
|---|
| 930 | $$->id = $1; | 
|---|
| 931 | $$->x = $3; | 
|---|
| 932 | $$->y = $5; | 
|---|
| 933 | $$->width = $7; | 
|---|
| 934 | $$->height = $9; | 
|---|
| 935 | if($10) | 
|---|
| 936 | { | 
|---|
| 937 | $$->style = $10; | 
|---|
| 938 | $$->gotstyle = TRUE; | 
|---|
| 939 | } | 
|---|
| 940 | } | 
|---|
| 941 | ; | 
|---|
| 942 |  | 
|---|
| 943 | iconinfo: /* Empty */ | 
|---|
| 944 | { $$ = new_control(); } | 
|---|
| 945 |  | 
|---|
| 946 | | ',' expr ',' expr { | 
|---|
| 947 | $$ = new_control(); | 
|---|
| 948 | $$->width = $2; | 
|---|
| 949 | $$->height = $4; | 
|---|
| 950 | } | 
|---|
| 951 | | ',' expr ',' expr ',' style { | 
|---|
| 952 | $$ = new_control(); | 
|---|
| 953 | $$->width = $2; | 
|---|
| 954 | $$->height = $4; | 
|---|
| 955 | $$->style = $6; | 
|---|
| 956 | $$->gotstyle = TRUE; | 
|---|
| 957 | } | 
|---|
| 958 | | ',' expr ',' expr ',' style ',' style { | 
|---|
| 959 | $$ = new_control(); | 
|---|
| 960 | $$->width = $2; | 
|---|
| 961 | $$->height = $4; | 
|---|
| 962 | $$->style = $6; | 
|---|
| 963 | $$->gotstyle = TRUE; | 
|---|
| 964 | $$->exstyle = $8; | 
|---|
| 965 | $$->gotexstyle = TRUE; | 
|---|
| 966 | } | 
|---|
| 967 | ; | 
|---|
| 968 |  | 
|---|
| 969 | gen_ctrl: nameid_s opt_comma expr ',' ctlclass ',' style ',' expr ',' expr ',' expr ',' expr ',' style { | 
|---|
| 970 | $$=new_control(); | 
|---|
| 971 | $$->title = $1; | 
|---|
| 972 | $$->id = $3; | 
|---|
| 973 | $$->ctlclass = convert_ctlclass($5); | 
|---|
| 974 | $$->style = $7; | 
|---|
| 975 | $$->gotstyle = TRUE; | 
|---|
| 976 | $$->x = $9; | 
|---|
| 977 | $$->y = $11; | 
|---|
| 978 | $$->width = $13; | 
|---|
| 979 | $$->height = $15; | 
|---|
| 980 | $$->exstyle = $17; | 
|---|
| 981 | $$->gotexstyle = TRUE; | 
|---|
| 982 | } | 
|---|
| 983 | | nameid_s opt_comma expr ',' ctlclass ',' style ',' expr ',' expr ',' expr ',' expr { | 
|---|
| 984 | $$=new_control(); | 
|---|
| 985 | $$->title = $1; | 
|---|
| 986 | $$->id = $3; | 
|---|
| 987 | $$->ctlclass = convert_ctlclass($5); | 
|---|
| 988 | $$->style = $7; | 
|---|
| 989 | $$->gotstyle = TRUE; | 
|---|
| 990 | $$->x = $9; | 
|---|
| 991 | $$->y = $11; | 
|---|
| 992 | $$->width = $13; | 
|---|
| 993 | $$->height = $15; | 
|---|
| 994 | } | 
|---|
| 995 | ; | 
|---|
| 996 |  | 
|---|
| 997 | opt_font | 
|---|
| 998 | : tFONT expr ',' tSTRING        { $$ = new_font_id($2, $4, 0, 0); } | 
|---|
| 999 | ; | 
|---|
| 1000 |  | 
|---|
| 1001 | /* ------------------------------ style flags ------------------------------ */ | 
|---|
| 1002 | optional_style          /* Abbused once to get optional ExStyle */ | 
|---|
| 1003 | : /* Empty */   { $$ = NULL; } | 
|---|
| 1004 | | ',' style     { $$ = $2; } | 
|---|
| 1005 | ; | 
|---|
| 1006 |  | 
|---|
| 1007 | optional_style_pair | 
|---|
| 1008 | : /* Empty */           { $$ = NULL; } | 
|---|
| 1009 | | ',' style             { $$ = new_style_pair($2, 0); } | 
|---|
| 1010 | | ',' style ',' style   { $$ = new_style_pair($2, $4); } | 
|---|
| 1011 | ; | 
|---|
| 1012 |  | 
|---|
| 1013 | style | 
|---|
| 1014 | : style '|' style       { $$ = new_style($1->or_mask | $3->or_mask, $1->and_mask | $3->and_mask); free($1); free($3);} | 
|---|
| 1015 | | '(' style ')'         { $$ = $2; } | 
|---|
| 1016 | | any_num               { $$ = new_style($1, 0); } | 
|---|
| 1017 | | tNOT any_num          { $$ = new_style(0, $2); } | 
|---|
| 1018 | ; | 
|---|
| 1019 |  | 
|---|
| 1020 | ctlclass | 
|---|
| 1021 | : expr  { | 
|---|
| 1022 | $$ = new_name_id(); | 
|---|
| 1023 | $$->type = name_ord; | 
|---|
| 1024 | $$->name.i_name = $1; | 
|---|
| 1025 | } | 
|---|
| 1026 | | tSTRING { | 
|---|
| 1027 | $$ = new_name_id(); | 
|---|
| 1028 | $$->type = name_str; | 
|---|
| 1029 | $$->name.s_name = $1; | 
|---|
| 1030 | } | 
|---|
| 1031 | ; | 
|---|
| 1032 |  | 
|---|
| 1033 | /* ------------------------------ DialogEx ------------------------------ */ | 
|---|
| 1034 | dialogex: tDIALOGEX loadmemopts expr ',' expr ',' expr ',' expr helpid dlgex_attribs | 
|---|
| 1035 | tBEGIN  exctrls tEND { | 
|---|
| 1036 | if(!win32) | 
|---|
| 1037 | yywarning("DIALOGEX not supported in 16-bit mode"); | 
|---|
| 1038 | if($2) | 
|---|
| 1039 | { | 
|---|
| 1040 | $11->memopt = *($2); | 
|---|
| 1041 | free($2); | 
|---|
| 1042 | } | 
|---|
| 1043 | else | 
|---|
| 1044 | $11->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE; | 
|---|
| 1045 | $11->x = $3; | 
|---|
| 1046 | $11->y = $5; | 
|---|
| 1047 | $11->width = $7; | 
|---|
| 1048 | $11->height = $9; | 
|---|
| 1049 | if($10) | 
|---|
| 1050 | { | 
|---|
| 1051 | $11->helpid = *($10); | 
|---|
| 1052 | $11->gothelpid = TRUE; | 
|---|
| 1053 | free($10); | 
|---|
| 1054 | } | 
|---|
| 1055 | $11->controls = get_control_head($13); | 
|---|
| 1056 | $$ = $11; | 
|---|
| 1057 |  | 
|---|
| 1058 | assert($$->style != NULL); | 
|---|
| 1059 | if(!$$->gotstyle) | 
|---|
| 1060 | { | 
|---|
| 1061 | $$->style->or_mask = WS_POPUP; | 
|---|
| 1062 | $$->gotstyle = TRUE; | 
|---|
| 1063 | } | 
|---|
| 1064 | if($$->title) | 
|---|
| 1065 | $$->style->or_mask |= WS_CAPTION; | 
|---|
| 1066 | if($$->font) | 
|---|
| 1067 | $$->style->or_mask |= DS_SETFONT; | 
|---|
| 1068 |  | 
|---|
| 1069 | $$->style->or_mask &= ~($$->style->and_mask); | 
|---|
| 1070 | $$->style->and_mask = 0; | 
|---|
| 1071 |  | 
|---|
| 1072 | if(!$$->lvc.language) | 
|---|
| 1073 | $$->lvc.language = dup_language(currentlanguage); | 
|---|
| 1074 | } | 
|---|
| 1075 | ; | 
|---|
| 1076 |  | 
|---|
| 1077 | dlgex_attribs | 
|---|
| 1078 | : /* Empty */                           { $$=new_dialogex(); } | 
|---|
| 1079 | | dlgex_attribs tSTYLE style            { $$=dialogex_style($3,$1); } | 
|---|
| 1080 | | dlgex_attribs tEXSTYLE style          { $$=dialogex_exstyle($3,$1); } | 
|---|
| 1081 | | dlgex_attribs tCAPTION tSTRING        { $$=dialogex_caption($3,$1); } | 
|---|
| 1082 | | dlgex_attribs opt_font                { $$=dialogex_font($2,$1); } | 
|---|
| 1083 | | dlgex_attribs opt_exfont              { $$=dialogex_font($2,$1); } | 
|---|
| 1084 | | dlgex_attribs tCLASS nameid_s         { $$=dialogex_class($3,$1); } | 
|---|
| 1085 | | dlgex_attribs tCPPCLASS nameid_s      { $$=dialogex_class($3,$1); } | 
|---|
| 1086 | | dlgex_attribs tMENU nameid            { $$=dialogex_menu($3,$1); } | 
|---|
| 1087 | | dlgex_attribs opt_language            { $$=dialogex_language($2,$1); } | 
|---|
| 1088 | | dlgex_attribs opt_characts            { $$=dialogex_characteristics($2,$1); } | 
|---|
| 1089 | | dlgex_attribs opt_version             { $$=dialogex_version($2,$1); } | 
|---|
| 1090 | ; | 
|---|
| 1091 |  | 
|---|
| 1092 | exctrls : /* Empty */                           { $$ = NULL; } | 
|---|
| 1093 | | exctrls tCONTROL      gen_exctrl      { $$=ins_ctrl(-1, 0, $3, $1); } | 
|---|
| 1094 | | exctrls tEDITTEXT     exctrl_desc     { $$=ins_ctrl(CT_EDIT, 0, $3, $1); } | 
|---|
| 1095 | | exctrls tLISTBOX      exctrl_desc     { $$=ins_ctrl(CT_LISTBOX, 0, $3, $1); } | 
|---|
| 1096 | | exctrls tCOMBOBOX     exctrl_desc     { $$=ins_ctrl(CT_COMBOBOX, 0, $3, $1); } | 
|---|
| 1097 | | exctrls tSCROLLBAR    exctrl_desc     { $$=ins_ctrl(CT_SCROLLBAR, 0, $3, $1); } | 
|---|
| 1098 | | exctrls tCHECKBOX     lab_exctrl      { $$=ins_ctrl(CT_BUTTON, BS_CHECKBOX, $3, $1); } | 
|---|
| 1099 | | exctrls tDEFPUSHBUTTON lab_exctrl     { $$=ins_ctrl(CT_BUTTON, BS_DEFPUSHBUTTON, $3, $1); } | 
|---|
| 1100 | | exctrls tGROUPBOX     lab_exctrl      { $$=ins_ctrl(CT_BUTTON, BS_GROUPBOX, $3, $1);} | 
|---|
| 1101 | | exctrls tPUSHBUTTON   lab_exctrl      { $$=ins_ctrl(CT_BUTTON, BS_PUSHBUTTON, $3, $1); } | 
|---|
| 1102 | /*      | exctrls tPUSHBOX      lab_exctrl      { $$=ins_ctrl(CT_BUTTON, BS_PUSHBOX, $3, $1); } */ | 
|---|
| 1103 | | exctrls tRADIOBUTTON  lab_exctrl      { $$=ins_ctrl(CT_BUTTON, BS_RADIOBUTTON, $3, $1); } | 
|---|
| 1104 | | exctrls tAUTO3STATE   lab_exctrl      { $$=ins_ctrl(CT_BUTTON, BS_AUTO3STATE, $3, $1); } | 
|---|
| 1105 | | exctrls tSTATE3       lab_exctrl      { $$=ins_ctrl(CT_BUTTON, BS_3STATE, $3, $1); } | 
|---|
| 1106 | | exctrls tAUTOCHECKBOX lab_exctrl      { $$=ins_ctrl(CT_BUTTON, BS_AUTOCHECKBOX, $3, $1); } | 
|---|
| 1107 | | exctrls tAUTORADIOBUTTON lab_exctrl   { $$=ins_ctrl(CT_BUTTON, BS_AUTORADIOBUTTON, $3, $1); } | 
|---|
| 1108 | | exctrls tLTEXT        lab_exctrl      { $$=ins_ctrl(CT_STATIC, SS_LEFT, $3, $1); } | 
|---|
| 1109 | | exctrls tCTEXT        lab_exctrl      { $$=ins_ctrl(CT_STATIC, SS_CENTER, $3, $1); } | 
|---|
| 1110 | | exctrls tRTEXT        lab_exctrl      { $$=ins_ctrl(CT_STATIC, SS_RIGHT, $3, $1); } | 
|---|
| 1111 | /* special treatment for icons, as the extent is optional */ | 
|---|
| 1112 | | exctrls tICON nameid_s opt_comma expr ',' expr ',' expr iconinfo { | 
|---|
| 1113 | $10->title = $3; | 
|---|
| 1114 | $10->id = $5; | 
|---|
| 1115 | $10->x = $7; | 
|---|
| 1116 | $10->y = $9; | 
|---|
| 1117 | $$ = ins_ctrl(CT_STATIC, SS_ICON, $10, $1); | 
|---|
| 1118 | } | 
|---|
| 1119 | ; | 
|---|
| 1120 |  | 
|---|
| 1121 | gen_exctrl | 
|---|
| 1122 | : nameid_s opt_comma expr ',' ctlclass ',' style ',' expr ',' expr ',' expr ',' | 
|---|
| 1123 | expr ',' style helpid opt_data { | 
|---|
| 1124 | $$=new_control(); | 
|---|
| 1125 | $$->title = $1; | 
|---|
| 1126 | $$->id = $3; | 
|---|
| 1127 | $$->ctlclass = convert_ctlclass($5); | 
|---|
| 1128 | $$->style = $7; | 
|---|
| 1129 | $$->gotstyle = TRUE; | 
|---|
| 1130 | $$->x = $9; | 
|---|
| 1131 | $$->y = $11; | 
|---|
| 1132 | $$->width = $13; | 
|---|
| 1133 | $$->height = $15; | 
|---|
| 1134 | if($17) | 
|---|
| 1135 | { | 
|---|
| 1136 | $$->exstyle = $17; | 
|---|
| 1137 | $$->gotexstyle = TRUE; | 
|---|
| 1138 | } | 
|---|
| 1139 | if($18) | 
|---|
| 1140 | { | 
|---|
| 1141 | $$->helpid = *($18); | 
|---|
| 1142 | $$->gothelpid = TRUE; | 
|---|
| 1143 | free($18); | 
|---|
| 1144 | } | 
|---|
| 1145 | $$->extra = $19; | 
|---|
| 1146 | } | 
|---|
| 1147 | | nameid_s opt_comma expr ',' ctlclass ',' style ',' expr ',' expr ',' expr ',' expr opt_data { | 
|---|
| 1148 | $$=new_control(); | 
|---|
| 1149 | $$->title = $1; | 
|---|
| 1150 | $$->id = $3; | 
|---|
| 1151 | $$->style = $7; | 
|---|
| 1152 | $$->gotstyle = TRUE; | 
|---|
| 1153 | $$->ctlclass = convert_ctlclass($5); | 
|---|
| 1154 | $$->x = $9; | 
|---|
| 1155 | $$->y = $11; | 
|---|
| 1156 | $$->width = $13; | 
|---|
| 1157 | $$->height = $15; | 
|---|
| 1158 | $$->extra = $16; | 
|---|
| 1159 | } | 
|---|
| 1160 | ; | 
|---|
| 1161 |  | 
|---|
| 1162 | lab_exctrl | 
|---|
| 1163 | : tSTRING opt_comma expr ',' expr ',' expr ',' expr ',' expr optional_style_pair opt_data { | 
|---|
| 1164 | $$=new_control(); | 
|---|
| 1165 | $$->title = new_name_id(); | 
|---|
| 1166 | $$->title->type = name_str; | 
|---|
| 1167 | $$->title->name.s_name = $1; | 
|---|
| 1168 | $$->id = $3; | 
|---|
| 1169 | $$->x = $5; | 
|---|
| 1170 | $$->y = $7; | 
|---|
| 1171 | $$->width = $9; | 
|---|
| 1172 | $$->height = $11; | 
|---|
| 1173 | if($12) | 
|---|
| 1174 | { | 
|---|
| 1175 | $$->style = $12->style; | 
|---|
| 1176 | $$->gotstyle = TRUE; | 
|---|
| 1177 |  | 
|---|
| 1178 | if ($12->exstyle) | 
|---|
| 1179 | { | 
|---|
| 1180 | $$->exstyle = $12->exstyle; | 
|---|
| 1181 | $$->gotexstyle = TRUE; | 
|---|
| 1182 | } | 
|---|
| 1183 | free($12); | 
|---|
| 1184 | } | 
|---|
| 1185 |  | 
|---|
| 1186 | $$->extra = $13; | 
|---|
| 1187 | } | 
|---|
| 1188 | ; | 
|---|
| 1189 |  | 
|---|
| 1190 | exctrl_desc | 
|---|
| 1191 | : expr ',' expr ',' expr ',' expr ',' expr optional_style_pair opt_data { | 
|---|
| 1192 | $$ = new_control(); | 
|---|
| 1193 | $$->id = $1; | 
|---|
| 1194 | $$->x = $3; | 
|---|
| 1195 | $$->y = $5; | 
|---|
| 1196 | $$->width = $7; | 
|---|
| 1197 | $$->height = $9; | 
|---|
| 1198 | if($10) | 
|---|
| 1199 | { | 
|---|
| 1200 | $$->style = $10->style; | 
|---|
| 1201 | $$->gotstyle = TRUE; | 
|---|
| 1202 |  | 
|---|
| 1203 | if ($10->exstyle) | 
|---|
| 1204 | { | 
|---|
| 1205 | $$->exstyle = $10->exstyle; | 
|---|
| 1206 | $$->gotexstyle = TRUE; | 
|---|
| 1207 | } | 
|---|
| 1208 | free($10); | 
|---|
| 1209 | } | 
|---|
| 1210 | $$->extra = $11; | 
|---|
| 1211 | } | 
|---|
| 1212 | ; | 
|---|
| 1213 |  | 
|---|
| 1214 | opt_data: /* Empty */   { $$ = NULL; } | 
|---|
| 1215 | | raw_data      { $$ = $1; } | 
|---|
| 1216 | ; | 
|---|
| 1217 |  | 
|---|
| 1218 | helpid  : /* Empty */   { $$ = NULL; } | 
|---|
| 1219 | | ',' expr      { $$ = new_int($2); } | 
|---|
| 1220 | ; | 
|---|
| 1221 |  | 
|---|
| 1222 | opt_exfont | 
|---|
| 1223 | : tFONT expr ',' tSTRING ',' expr ',' expr  opt_expr { $$ = new_font_id($2, $4, $6, $8); } | 
|---|
| 1224 | ; | 
|---|
| 1225 |  | 
|---|
| 1226 | /* | 
|---|
| 1227 | * FIXME: This odd expression is here to nullify an extra token found | 
|---|
| 1228 | * in some appstudio produced resources which appear to do nothing. | 
|---|
| 1229 | */ | 
|---|
| 1230 | opt_expr: /* Empty */   { $$ = NULL; } | 
|---|
| 1231 | | ',' expr      { $$ = NULL; } | 
|---|
| 1232 | ; | 
|---|
| 1233 |  | 
|---|
| 1234 | /* ------------------------------ Menu ------------------------------ */ | 
|---|
| 1235 | menu    : tMENU loadmemopts opt_lvc menu_body { | 
|---|
| 1236 | if(!$4) | 
|---|
| 1237 | yyerror("Menu must contain items"); | 
|---|
| 1238 | $$ = new_menu(); | 
|---|
| 1239 | if($2) | 
|---|
| 1240 | { | 
|---|
| 1241 | $$->memopt = *($2); | 
|---|
| 1242 | free($2); | 
|---|
| 1243 | } | 
|---|
| 1244 | else | 
|---|
| 1245 | $$->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE; | 
|---|
| 1246 | $$->items = get_item_head($4); | 
|---|
| 1247 | if($3) | 
|---|
| 1248 | { | 
|---|
| 1249 | $$->lvc = *($3); | 
|---|
| 1250 | free($3); | 
|---|
| 1251 | } | 
|---|
| 1252 | if(!$$->lvc.language) | 
|---|
| 1253 | $$->lvc.language = dup_language(currentlanguage); | 
|---|
| 1254 | } | 
|---|
| 1255 | ; | 
|---|
| 1256 |  | 
|---|
| 1257 | menu_body | 
|---|
| 1258 | : tBEGIN item_definitions tEND  { $$ = $2; } | 
|---|
| 1259 | ; | 
|---|
| 1260 |  | 
|---|
| 1261 | item_definitions | 
|---|
| 1262 | : /* Empty */   {$$ = NULL;} | 
|---|
| 1263 | | item_definitions tMENUITEM tSTRING opt_comma expr item_options { | 
|---|
| 1264 | $$=new_menu_item(); | 
|---|
| 1265 | $$->prev = $1; | 
|---|
| 1266 | if($1) | 
|---|
| 1267 | $1->next = $$; | 
|---|
| 1268 | $$->id =  $5; | 
|---|
| 1269 | $$->state = $6; | 
|---|
| 1270 | $$->name = $3; | 
|---|
| 1271 | } | 
|---|
| 1272 | | item_definitions tMENUITEM tSEPARATOR { | 
|---|
| 1273 | $$=new_menu_item(); | 
|---|
| 1274 | $$->prev = $1; | 
|---|
| 1275 | if($1) | 
|---|
| 1276 | $1->next = $$; | 
|---|
| 1277 | } | 
|---|
| 1278 | | item_definitions tPOPUP tSTRING item_options menu_body { | 
|---|
| 1279 | $$ = new_menu_item(); | 
|---|
| 1280 | $$->prev = $1; | 
|---|
| 1281 | if($1) | 
|---|
| 1282 | $1->next = $$; | 
|---|
| 1283 | $$->popup = get_item_head($5); | 
|---|
| 1284 | $$->name = $3; | 
|---|
| 1285 | } | 
|---|
| 1286 | ; | 
|---|
| 1287 |  | 
|---|
| 1288 | /* NOTE: item_options is right recursive because it would introduce | 
|---|
| 1289 | * a shift/reduce conflict on ',' in itemex_options due to the | 
|---|
| 1290 | * empty rule here. The parser is now forced to look beyond the ',' | 
|---|
| 1291 | * before reducing (force shift). | 
|---|
| 1292 | * Right recursion here is not a problem because we cannot expect | 
|---|
| 1293 | * more than 7 parserstack places to be occupied while parsing this | 
|---|
| 1294 | * (who would want to specify a MF_x flag twice?). | 
|---|
| 1295 | */ | 
|---|
| 1296 | item_options | 
|---|
| 1297 | : /* Empty */                           { $$ = 0; } | 
|---|
| 1298 | | ',' tCHECKED          item_options    { $$ = $3 | MF_CHECKED; } | 
|---|
| 1299 | | ',' tGRAYED           item_options    { $$ = $3 | MF_GRAYED; } | 
|---|
| 1300 | | ',' tHELP             item_options    { $$ = $3 | MF_HELP; } | 
|---|
| 1301 | | ',' tINACTIVE         item_options    { $$ = $3 | MF_DISABLED; } | 
|---|
| 1302 | | ',' tMENUBARBREAK     item_options    { $$ = $3 | MF_MENUBARBREAK; } | 
|---|
| 1303 | | ',' tMENUBREAK        item_options    { $$ = $3 | MF_MENUBREAK; } | 
|---|
| 1304 | ; | 
|---|
| 1305 |  | 
|---|
| 1306 | /* ------------------------------ MenuEx ------------------------------ */ | 
|---|
| 1307 | menuex  : tMENUEX loadmemopts opt_lvc menuex_body       { | 
|---|
| 1308 | if(!win32) | 
|---|
| 1309 | yywarning("MENUEX not supported in 16-bit mode"); | 
|---|
| 1310 | if(!$4) | 
|---|
| 1311 | yyerror("MenuEx must contain items"); | 
|---|
| 1312 | $$ = new_menuex(); | 
|---|
| 1313 | if($2) | 
|---|
| 1314 | { | 
|---|
| 1315 | $$->memopt = *($2); | 
|---|
| 1316 | free($2); | 
|---|
| 1317 | } | 
|---|
| 1318 | else | 
|---|
| 1319 | $$->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE | WRC_MO_DISCARDABLE; | 
|---|
| 1320 | $$->items = get_itemex_head($4); | 
|---|
| 1321 | if($3) | 
|---|
| 1322 | { | 
|---|
| 1323 | $$->lvc = *($3); | 
|---|
| 1324 | free($3); | 
|---|
| 1325 | } | 
|---|
| 1326 | if(!$$->lvc.language) | 
|---|
| 1327 | $$->lvc.language = dup_language(currentlanguage); | 
|---|
| 1328 | } | 
|---|
| 1329 | ; | 
|---|
| 1330 |  | 
|---|
| 1331 | menuex_body | 
|---|
| 1332 | : tBEGIN itemex_definitions tEND { $$ = $2; } | 
|---|
| 1333 | ; | 
|---|
| 1334 |  | 
|---|
| 1335 | itemex_definitions | 
|---|
| 1336 | : /* Empty */   {$$ = NULL; } | 
|---|
| 1337 | | itemex_definitions tMENUITEM tSTRING itemex_options { | 
|---|
| 1338 | $$ = new_menuex_item(); | 
|---|
| 1339 | $$->prev = $1; | 
|---|
| 1340 | if($1) | 
|---|
| 1341 | $1->next = $$; | 
|---|
| 1342 | $$->name = $3; | 
|---|
| 1343 | $$->id = $4->id; | 
|---|
| 1344 | $$->type = $4->type; | 
|---|
| 1345 | $$->state = $4->state; | 
|---|
| 1346 | $$->helpid = $4->helpid; | 
|---|
| 1347 | $$->gotid = $4->gotid; | 
|---|
| 1348 | $$->gottype = $4->gottype; | 
|---|
| 1349 | $$->gotstate = $4->gotstate; | 
|---|
| 1350 | $$->gothelpid = $4->gothelpid; | 
|---|
| 1351 | free($4); | 
|---|
| 1352 | } | 
|---|
| 1353 | | itemex_definitions tMENUITEM tSEPARATOR { | 
|---|
| 1354 | $$ = new_menuex_item(); | 
|---|
| 1355 | $$->prev = $1; | 
|---|
| 1356 | if($1) | 
|---|
| 1357 | $1->next = $$; | 
|---|
| 1358 | } | 
|---|
| 1359 | | itemex_definitions tPOPUP tSTRING itemex_p_options menuex_body { | 
|---|
| 1360 | $$ = new_menuex_item(); | 
|---|
| 1361 | $$->prev = $1; | 
|---|
| 1362 | if($1) | 
|---|
| 1363 | $1->next = $$; | 
|---|
| 1364 | $$->popup = get_itemex_head($5); | 
|---|
| 1365 | $$->name = $3; | 
|---|
| 1366 | $$->id = $4->id; | 
|---|
| 1367 | $$->type = $4->type; | 
|---|
| 1368 | $$->state = $4->state; | 
|---|
| 1369 | $$->helpid = $4->helpid; | 
|---|
| 1370 | $$->gotid = $4->gotid; | 
|---|
| 1371 | $$->gottype = $4->gottype; | 
|---|
| 1372 | $$->gotstate = $4->gotstate; | 
|---|
| 1373 | $$->gothelpid = $4->gothelpid; | 
|---|
| 1374 | free($4); | 
|---|
| 1375 | } | 
|---|
| 1376 | ; | 
|---|
| 1377 |  | 
|---|
| 1378 | itemex_options | 
|---|
| 1379 | : /* Empty */                   { $$ = new_itemex_opt(0, 0, 0, 0); } | 
|---|
| 1380 | | ',' expr { | 
|---|
| 1381 | $$ = new_itemex_opt($2, 0, 0, 0); | 
|---|
| 1382 | $$->gotid = TRUE; | 
|---|
| 1383 | } | 
|---|
| 1384 | | ',' e_expr ',' e_expr item_options { | 
|---|
| 1385 | $$ = new_itemex_opt($2 ? *($2) : 0, $4 ? *($4) : 0, $5, 0); | 
|---|
| 1386 | $$->gotid = TRUE; | 
|---|
| 1387 | $$->gottype = TRUE; | 
|---|
| 1388 | $$->gotstate = TRUE; | 
|---|
| 1389 | if($2) free($2); | 
|---|
| 1390 | if($4) free($4); | 
|---|
| 1391 | } | 
|---|
| 1392 | | ',' e_expr ',' e_expr ',' expr { | 
|---|
| 1393 | $$ = new_itemex_opt($2 ? *($2) : 0, $4 ? *($4) : 0, $6, 0); | 
|---|
| 1394 | $$->gotid = TRUE; | 
|---|
| 1395 | $$->gottype = TRUE; | 
|---|
| 1396 | $$->gotstate = TRUE; | 
|---|
| 1397 | if($2) free($2); | 
|---|
| 1398 | if($4) free($4); | 
|---|
| 1399 | } | 
|---|
| 1400 | ; | 
|---|
| 1401 |  | 
|---|
| 1402 | itemex_p_options | 
|---|
| 1403 | : /* Empty */                   { $$ = new_itemex_opt(0, 0, 0, 0); } | 
|---|
| 1404 | | ',' expr { | 
|---|
| 1405 | $$ = new_itemex_opt($2, 0, 0, 0); | 
|---|
| 1406 | $$->gotid = TRUE; | 
|---|
| 1407 | } | 
|---|
| 1408 | | ',' e_expr ',' expr { | 
|---|
| 1409 | $$ = new_itemex_opt($2 ? *($2) : 0, $4, 0, 0); | 
|---|
| 1410 | if($2) free($2); | 
|---|
| 1411 | $$->gotid = TRUE; | 
|---|
| 1412 | $$->gottype = TRUE; | 
|---|
| 1413 | } | 
|---|
| 1414 | | ',' e_expr ',' e_expr ',' expr { | 
|---|
| 1415 | $$ = new_itemex_opt($2 ? *($2) : 0, $4 ? *($4) : 0, $6, 0); | 
|---|
| 1416 | if($2) free($2); | 
|---|
| 1417 | if($4) free($4); | 
|---|
| 1418 | $$->gotid = TRUE; | 
|---|
| 1419 | $$->gottype = TRUE; | 
|---|
| 1420 | $$->gotstate = TRUE; | 
|---|
| 1421 | } | 
|---|
| 1422 | | ',' e_expr ',' e_expr ',' e_expr ',' expr { | 
|---|
| 1423 | $$ = new_itemex_opt($2 ? *($2) : 0, $4 ? *($4) : 0, $6 ? *($6) : 0, $8); | 
|---|
| 1424 | if($2) free($2); | 
|---|
| 1425 | if($4) free($4); | 
|---|
| 1426 | if($6) free($6); | 
|---|
| 1427 | $$->gotid = TRUE; | 
|---|
| 1428 | $$->gottype = TRUE; | 
|---|
| 1429 | $$->gotstate = TRUE; | 
|---|
| 1430 | $$->gothelpid = TRUE; | 
|---|
| 1431 | } | 
|---|
| 1432 | ; | 
|---|
| 1433 |  | 
|---|
| 1434 | /* ------------------------------ StringTable ------------------------------ */ | 
|---|
| 1435 | /* Stringtables are parsed differently than other resources because their | 
|---|
| 1436 | * layout is substantially different from other resources. | 
|---|
| 1437 | * The table is parsed through a _global_ variable 'tagstt' which holds the | 
|---|
| 1438 | * current stringtable descriptor (stringtable_t *) and 'sttres' that holds a | 
|---|
| 1439 | * list of stringtables of different languages. | 
|---|
| 1440 | */ | 
|---|
| 1441 | stringtable | 
|---|
| 1442 | : stt_head tBEGIN strings tEND { | 
|---|
| 1443 | if(!$3) | 
|---|
| 1444 | { | 
|---|
| 1445 | yyerror("Stringtable must have at least one entry"); | 
|---|
| 1446 | } | 
|---|
| 1447 | else | 
|---|
| 1448 | { | 
|---|
| 1449 | stringtable_t *stt; | 
|---|
| 1450 | /* Check if we added to a language table or created | 
|---|
| 1451 | * a new one. | 
|---|
| 1452 | */ | 
|---|
| 1453 | for(stt = sttres; stt; stt = stt->next) | 
|---|
| 1454 | { | 
|---|
| 1455 | if(stt == tagstt) | 
|---|
| 1456 | break; | 
|---|
| 1457 | } | 
|---|
| 1458 | if(!stt) | 
|---|
| 1459 | { | 
|---|
| 1460 | /* It is a new one */ | 
|---|
| 1461 | if(sttres) | 
|---|
| 1462 | { | 
|---|
| 1463 | sttres->prev = tagstt; | 
|---|
| 1464 | tagstt->next = sttres; | 
|---|
| 1465 | sttres = tagstt; | 
|---|
| 1466 | } | 
|---|
| 1467 | else | 
|---|
| 1468 | sttres = tagstt; | 
|---|
| 1469 | } | 
|---|
| 1470 | /* Else were done */ | 
|---|
| 1471 | } | 
|---|
| 1472 | if(tagstt_memopt) | 
|---|
| 1473 | { | 
|---|
| 1474 | free(tagstt_memopt); | 
|---|
| 1475 | tagstt_memopt = NULL; | 
|---|
| 1476 | } | 
|---|
| 1477 |  | 
|---|
| 1478 | $$ = tagstt; | 
|---|
| 1479 | } | 
|---|
| 1480 | ; | 
|---|
| 1481 |  | 
|---|
| 1482 | /* This is to get the language of the currently parsed stringtable */ | 
|---|
| 1483 | stt_head: tSTRINGTABLE loadmemopts opt_lvc { | 
|---|
| 1484 | if((tagstt = find_stringtable($3)) == NULL) | 
|---|
| 1485 | tagstt = new_stringtable($3); | 
|---|
| 1486 | tagstt_memopt = $2; | 
|---|
| 1487 | tagstt_version = $3->version; | 
|---|
| 1488 | tagstt_characts = $3->characts; | 
|---|
| 1489 | if($3) | 
|---|
| 1490 | free($3); | 
|---|
| 1491 | } | 
|---|
| 1492 | ; | 
|---|
| 1493 |  | 
|---|
| 1494 | strings : /* Empty */   { $$ = NULL; } | 
|---|
| 1495 | | strings expr opt_comma tSTRING { | 
|---|
| 1496 | int i; | 
|---|
| 1497 | assert(tagstt != NULL); | 
|---|
| 1498 | if($2 > 65535 || $2 < -32768) | 
|---|
| 1499 | yyerror("Stringtable entry's ID out of range (%d)", $2); | 
|---|
| 1500 | /* Search for the ID */ | 
|---|
| 1501 | for(i = 0; i < tagstt->nentries; i++) | 
|---|
| 1502 | { | 
|---|
| 1503 | if(tagstt->entries[i].id == $2) | 
|---|
| 1504 | yyerror("Stringtable ID %d already in use", $2); | 
|---|
| 1505 | } | 
|---|
| 1506 | /* If we get here, then we have a new unique entry */ | 
|---|
| 1507 | tagstt->nentries++; | 
|---|
| 1508 | tagstt->entries = xrealloc(tagstt->entries, sizeof(tagstt->entries[0]) * tagstt->nentries); | 
|---|
| 1509 | tagstt->entries[tagstt->nentries-1].id = $2; | 
|---|
| 1510 | tagstt->entries[tagstt->nentries-1].str = $4; | 
|---|
| 1511 | if(tagstt_memopt) | 
|---|
| 1512 | tagstt->entries[tagstt->nentries-1].memopt = *tagstt_memopt; | 
|---|
| 1513 | else | 
|---|
| 1514 | tagstt->entries[tagstt->nentries-1].memopt = WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE | WRC_MO_PURE; | 
|---|
| 1515 | tagstt->entries[tagstt->nentries-1].version = tagstt_version; | 
|---|
| 1516 | tagstt->entries[tagstt->nentries-1].characts = tagstt_characts; | 
|---|
| 1517 |  | 
|---|
| 1518 | if(pedantic && !$4->size) | 
|---|
| 1519 | yywarning("Zero length strings make no sense"); | 
|---|
| 1520 | if(!win32 && $4->size > 254) | 
|---|
| 1521 | yyerror("Stringtable entry more than 254 characters"); | 
|---|
| 1522 | if(win32 && $4->size > 65534) /* Hmm..., does this happen? */ | 
|---|
| 1523 | yyerror("Stringtable entry more than 65534 characters (probably something else that went wrong)"); | 
|---|
| 1524 | $$ = tagstt; | 
|---|
| 1525 | } | 
|---|
| 1526 | ; | 
|---|
| 1527 |  | 
|---|
| 1528 | opt_comma       /* There seem to be two ways to specify a stringtable... */ | 
|---|
| 1529 | : /* Empty */ | 
|---|
| 1530 | | ',' | 
|---|
| 1531 | ; | 
|---|
| 1532 |  | 
|---|
| 1533 | /* ------------------------------ VersionInfo ------------------------------ */ | 
|---|
| 1534 | versioninfo | 
|---|
| 1535 | : tVERSIONINFO loadmemopts fix_version tBEGIN ver_blocks tEND { | 
|---|
| 1536 | $$ = $3; | 
|---|
| 1537 | if($2) | 
|---|
| 1538 | { | 
|---|
| 1539 | $$->memopt = *($2); | 
|---|
| 1540 | free($2); | 
|---|
| 1541 | } | 
|---|
| 1542 | else | 
|---|
| 1543 | $$->memopt = WRC_MO_MOVEABLE | (win32 ? WRC_MO_PURE : 0); | 
|---|
| 1544 | $$->blocks = get_ver_block_head($5); | 
|---|
| 1545 | /* Set language; there is no version or characteristics */ | 
|---|
| 1546 | $$->lvc.language = dup_language(currentlanguage); | 
|---|
| 1547 | } | 
|---|
| 1548 | ; | 
|---|
| 1549 |  | 
|---|
| 1550 | fix_version | 
|---|
| 1551 | : /* Empty */                   { $$ = new_versioninfo(); } | 
|---|
| 1552 | | fix_version tFILEVERSION expr ',' expr ',' expr ',' expr { | 
|---|
| 1553 | if($1->gotit.fv) | 
|---|
| 1554 | yyerror("FILEVERSION already defined"); | 
|---|
| 1555 | $$ = $1; | 
|---|
| 1556 | $$->filever_maj1 = $3; | 
|---|
| 1557 | $$->filever_maj2 = $5; | 
|---|
| 1558 | $$->filever_min1 = $7; | 
|---|
| 1559 | $$->filever_min2 = $9; | 
|---|
| 1560 | $$->gotit.fv = 1; | 
|---|
| 1561 | } | 
|---|
| 1562 | | fix_version tPRODUCTVERSION expr ',' expr ',' expr ',' expr { | 
|---|
| 1563 | if($1->gotit.pv) | 
|---|
| 1564 | yyerror("PRODUCTVERSION already defined"); | 
|---|
| 1565 | $$ = $1; | 
|---|
| 1566 | $$->prodver_maj1 = $3; | 
|---|
| 1567 | $$->prodver_maj2 = $5; | 
|---|
| 1568 | $$->prodver_min1 = $7; | 
|---|
| 1569 | $$->prodver_min2 = $9; | 
|---|
| 1570 | $$->gotit.pv = 1; | 
|---|
| 1571 | } | 
|---|
| 1572 | | fix_version tFILEFLAGS expr { | 
|---|
| 1573 | if($1->gotit.ff) | 
|---|
| 1574 | yyerror("FILEFLAGS already defined"); | 
|---|
| 1575 | $$ = $1; | 
|---|
| 1576 | $$->fileflags = $3; | 
|---|
| 1577 | $$->gotit.ff = 1; | 
|---|
| 1578 | } | 
|---|
| 1579 | | fix_version tFILEFLAGSMASK expr { | 
|---|
| 1580 | if($1->gotit.ffm) | 
|---|
| 1581 | yyerror("FILEFLAGSMASK already defined"); | 
|---|
| 1582 | $$ = $1; | 
|---|
| 1583 | $$->fileflagsmask = $3; | 
|---|
| 1584 | $$->gotit.ffm = 1; | 
|---|
| 1585 | } | 
|---|
| 1586 | | fix_version tFILEOS expr { | 
|---|
| 1587 | if($1->gotit.fo) | 
|---|
| 1588 | yyerror("FILEOS already defined"); | 
|---|
| 1589 | $$ = $1; | 
|---|
| 1590 | $$->fileos = $3; | 
|---|
| 1591 | $$->gotit.fo = 1; | 
|---|
| 1592 | } | 
|---|
| 1593 | | fix_version tFILETYPE expr { | 
|---|
| 1594 | if($1->gotit.ft) | 
|---|
| 1595 | yyerror("FILETYPE already defined"); | 
|---|
| 1596 | $$ = $1; | 
|---|
| 1597 | $$->filetype = $3; | 
|---|
| 1598 | $$->gotit.ft = 1; | 
|---|
| 1599 | } | 
|---|
| 1600 | | fix_version tFILESUBTYPE expr { | 
|---|
| 1601 | if($1->gotit.fst) | 
|---|
| 1602 | yyerror("FILESUBTYPE already defined"); | 
|---|
| 1603 | $$ = $1; | 
|---|
| 1604 | $$->filesubtype = $3; | 
|---|
| 1605 | $$->gotit.fst = 1; | 
|---|
| 1606 | } | 
|---|
| 1607 | ; | 
|---|
| 1608 |  | 
|---|
| 1609 | ver_blocks | 
|---|
| 1610 | : /* Empty */                   { $$ = NULL; } | 
|---|
| 1611 | | ver_blocks ver_block { | 
|---|
| 1612 | $$ = $2; | 
|---|
| 1613 | $$->prev = $1; | 
|---|
| 1614 | if($1) | 
|---|
| 1615 | $1->next = $$; | 
|---|
| 1616 | } | 
|---|
| 1617 | ; | 
|---|
| 1618 |  | 
|---|
| 1619 | ver_block | 
|---|
| 1620 | : tBLOCK tSTRING tBEGIN ver_values tEND { | 
|---|
| 1621 | $$ = new_ver_block(); | 
|---|
| 1622 | $$->name = $2; | 
|---|
| 1623 | $$->values = get_ver_value_head($4); | 
|---|
| 1624 | } | 
|---|
| 1625 | ; | 
|---|
| 1626 |  | 
|---|
| 1627 | ver_values | 
|---|
| 1628 | : /* Empty */                   { $$ = NULL; } | 
|---|
| 1629 | | ver_values ver_value { | 
|---|
| 1630 | $$ = $2; | 
|---|
| 1631 | $$->prev = $1; | 
|---|
| 1632 | if($1) | 
|---|
| 1633 | $1->next = $$; | 
|---|
| 1634 | } | 
|---|
| 1635 | ; | 
|---|
| 1636 |  | 
|---|
| 1637 | ver_value | 
|---|
| 1638 | : ver_block { | 
|---|
| 1639 | $$ = new_ver_value(); | 
|---|
| 1640 | $$->type = val_block; | 
|---|
| 1641 | $$->value.block = $1; | 
|---|
| 1642 | } | 
|---|
| 1643 | | tVALUE tSTRING ',' tSTRING { | 
|---|
| 1644 | $$ = new_ver_value(); | 
|---|
| 1645 | $$->type = val_str; | 
|---|
| 1646 | $$->key = $2; | 
|---|
| 1647 | $$->value.str = $4; | 
|---|
| 1648 | } | 
|---|
| 1649 | | tVALUE tSTRING ',' ver_words { | 
|---|
| 1650 | $$ = new_ver_value(); | 
|---|
| 1651 | $$->type = val_words; | 
|---|
| 1652 | $$->key = $2; | 
|---|
| 1653 | $$->value.words = $4; | 
|---|
| 1654 | } | 
|---|
| 1655 | ; | 
|---|
| 1656 |  | 
|---|
| 1657 | ver_words | 
|---|
| 1658 | : expr                  { $$ = new_ver_words($1); } | 
|---|
| 1659 | | ver_words ',' expr    { $$ = add_ver_words($1, $3); } | 
|---|
| 1660 | ; | 
|---|
| 1661 |  | 
|---|
| 1662 | /* ------------------------------ Toolbar ------------------------------ */ | 
|---|
| 1663 | toolbar: tTOOLBAR loadmemopts expr ',' expr opt_lvc tBEGIN toolbar_items tEND { | 
|---|
| 1664 | int nitems; | 
|---|
| 1665 | toolbar_item_t *items = get_tlbr_buttons_head($8, &nitems); | 
|---|
| 1666 | $$ = new_toolbar($3, $5, items, nitems); | 
|---|
| 1667 | if($2) | 
|---|
| 1668 | { | 
|---|
| 1669 | $$->memopt = *($2); | 
|---|
| 1670 | free($2); | 
|---|
| 1671 | } | 
|---|
| 1672 | else | 
|---|
| 1673 | { | 
|---|
| 1674 | $$->memopt = WRC_MO_MOVEABLE | WRC_MO_PURE; | 
|---|
| 1675 | } | 
|---|
| 1676 | if($6) | 
|---|
| 1677 | { | 
|---|
| 1678 | $$->lvc = *($6); | 
|---|
| 1679 | free($6); | 
|---|
| 1680 | } | 
|---|
| 1681 | if(!$$->lvc.language) | 
|---|
| 1682 | { | 
|---|
| 1683 | $$->lvc.language = dup_language(currentlanguage); | 
|---|
| 1684 | } | 
|---|
| 1685 | } | 
|---|
| 1686 | ; | 
|---|
| 1687 |  | 
|---|
| 1688 | toolbar_items | 
|---|
| 1689 | :  /* Empty */                  { $$ = NULL; } | 
|---|
| 1690 | | toolbar_items tBUTTON expr    { | 
|---|
| 1691 | toolbar_item_t *idrec = new_toolbar_item(); | 
|---|
| 1692 | idrec->id = $3; | 
|---|
| 1693 | $$ = ins_tlbr_button($1, idrec); | 
|---|
| 1694 | } | 
|---|
| 1695 | | toolbar_items tSEPARATOR      { | 
|---|
| 1696 | toolbar_item_t *idrec = new_toolbar_item(); | 
|---|
| 1697 | idrec->id = 0; | 
|---|
| 1698 | $$ = ins_tlbr_button($1, idrec); | 
|---|
| 1699 | } | 
|---|
| 1700 | ; | 
|---|
| 1701 |  | 
|---|
| 1702 | /* ------------------------------ Memory options ------------------------------ */ | 
|---|
| 1703 | loadmemopts | 
|---|
| 1704 | : /* Empty */           { $$ = NULL; } | 
|---|
| 1705 | | loadmemopts lamo { | 
|---|
| 1706 | if($1) | 
|---|
| 1707 | { | 
|---|
| 1708 | *($1) |= *($2); | 
|---|
| 1709 | $$ = $1; | 
|---|
| 1710 | free($2); | 
|---|
| 1711 | } | 
|---|
| 1712 | else | 
|---|
| 1713 | $$ = $2; | 
|---|
| 1714 | } | 
|---|
| 1715 | | loadmemopts lama { | 
|---|
| 1716 | if($1) | 
|---|
| 1717 | { | 
|---|
| 1718 | *($1) &= *($2); | 
|---|
| 1719 | $$ = $1; | 
|---|
| 1720 | free($2); | 
|---|
| 1721 | } | 
|---|
| 1722 | else | 
|---|
| 1723 | { | 
|---|
| 1724 | *$2 &= WRC_MO_MOVEABLE | WRC_MO_DISCARDABLE | WRC_MO_PURE; | 
|---|
| 1725 | $$ = $2; | 
|---|
| 1726 | } | 
|---|
| 1727 | } | 
|---|
| 1728 | ; | 
|---|
| 1729 |  | 
|---|
| 1730 | lamo    : tPRELOAD      { $$ = new_int(WRC_MO_PRELOAD); } | 
|---|
| 1731 | | tMOVEABLE     { $$ = new_int(WRC_MO_MOVEABLE); } | 
|---|
| 1732 | | tDISCARDABLE  { $$ = new_int(WRC_MO_DISCARDABLE); } | 
|---|
| 1733 | | tPURE         { $$ = new_int(WRC_MO_PURE); } | 
|---|
| 1734 | ; | 
|---|
| 1735 |  | 
|---|
| 1736 | lama    : tLOADONCALL   { $$ = new_int(~WRC_MO_PRELOAD); } | 
|---|
| 1737 | | tFIXED        { $$ = new_int(~WRC_MO_MOVEABLE); } | 
|---|
| 1738 | | tIMPURE       { $$ = new_int(~WRC_MO_PURE); } | 
|---|
| 1739 | ; | 
|---|
| 1740 |  | 
|---|
| 1741 | /* ------------------------------ Win32 options ------------------------------ */ | 
|---|
| 1742 | opt_lvc : /* Empty */           { $$ = new_lvc(); } | 
|---|
| 1743 | | opt_lvc opt_language { | 
|---|
| 1744 | if(!win32) | 
|---|
| 1745 | yywarning("LANGUAGE not supported in 16-bit mode"); | 
|---|
| 1746 | if($1->language) | 
|---|
| 1747 | yyerror("Language already defined"); | 
|---|
| 1748 | $$ = $1; | 
|---|
| 1749 | $1->language = $2; | 
|---|
| 1750 | } | 
|---|
| 1751 | | opt_lvc opt_characts { | 
|---|
| 1752 | if(!win32) | 
|---|
| 1753 | yywarning("CHARACTERISTICS not supported in 16-bit mode"); | 
|---|
| 1754 | if($1->characts) | 
|---|
| 1755 | yyerror("Characteristics already defined"); | 
|---|
| 1756 | $$ = $1; | 
|---|
| 1757 | $1->characts = $2; | 
|---|
| 1758 | } | 
|---|
| 1759 | | opt_lvc opt_version { | 
|---|
| 1760 | if(!win32) | 
|---|
| 1761 | yywarning("VERSION not supported in 16-bit mode"); | 
|---|
| 1762 | if($1->version) | 
|---|
| 1763 | yyerror("Version already defined"); | 
|---|
| 1764 | $$ = $1; | 
|---|
| 1765 | $1->version = $2; | 
|---|
| 1766 | } | 
|---|
| 1767 | ; | 
|---|
| 1768 |  | 
|---|
| 1769 | /* | 
|---|
| 1770 | * This here is another s/r conflict on {bi,u}nary + and -. | 
|---|
| 1771 | * It is due to the look-ahead which must determine when the | 
|---|
| 1772 | * rule opt_language ends. It could be solved with adding a | 
|---|
| 1773 | * tNL at the end, but that seems unreasonable to do. | 
|---|
| 1774 | * The conflict is now moved to the expression handling below. | 
|---|
| 1775 | */ | 
|---|
| 1776 | opt_language | 
|---|
| 1777 | : tLANGUAGE expr ',' expr       { $$ = new_language($2, $4); } | 
|---|
| 1778 | ; | 
|---|
| 1779 |  | 
|---|
| 1780 | opt_characts | 
|---|
| 1781 | : tCHARACTERISTICS expr         { $$ = new_characts($2); } | 
|---|
| 1782 | ; | 
|---|
| 1783 |  | 
|---|
| 1784 | opt_version | 
|---|
| 1785 | : tVERSION expr                 { $$ = new_version($2); } | 
|---|
| 1786 | ; | 
|---|
| 1787 |  | 
|---|
| 1788 | /* ------------------------------ Raw data handling ------------------------------ */ | 
|---|
| 1789 | raw_data: opt_lvc tBEGIN raw_elements tEND { | 
|---|
| 1790 | if($1) | 
|---|
| 1791 | { | 
|---|
| 1792 | $3->lvc = *($1); | 
|---|
| 1793 | free($1); | 
|---|
| 1794 | } | 
|---|
| 1795 |  | 
|---|
| 1796 | if(!$3->lvc.language) | 
|---|
| 1797 | $3->lvc.language = dup_language(currentlanguage); | 
|---|
| 1798 |  | 
|---|
| 1799 | $$ = $3; | 
|---|
| 1800 | } | 
|---|
| 1801 | ; | 
|---|
| 1802 |  | 
|---|
| 1803 | raw_elements | 
|---|
| 1804 | : tRAWDATA                      { $$ = $1; } | 
|---|
| 1805 | | tNUMBER                       { $$ = int2raw_data($1); } | 
|---|
| 1806 | | tLNUMBER                      { $$ = long2raw_data($1); } | 
|---|
| 1807 | | tSTRING                       { $$ = str2raw_data($1); } | 
|---|
| 1808 | | raw_elements opt_comma tRAWDATA { $$ = merge_raw_data($1, $3); free($3->data); free($3); } | 
|---|
| 1809 | | raw_elements opt_comma tNUMBER  { $$ = merge_raw_data_int($1, $3); } | 
|---|
| 1810 | | raw_elements opt_comma tLNUMBER { $$ = merge_raw_data_long($1, $3); } | 
|---|
| 1811 | | raw_elements opt_comma tSTRING  { $$ = merge_raw_data_str($1, $3); } | 
|---|
| 1812 | ; | 
|---|
| 1813 |  | 
|---|
| 1814 | /* File data or raw data */ | 
|---|
| 1815 | file_raw: filename      { | 
|---|
| 1816 | $$ = load_file($1); | 
|---|
| 1817 | $$->lvc.language = dup_language(currentlanguage); | 
|---|
| 1818 | } | 
|---|
| 1819 | | raw_data      { $$ = $1; } | 
|---|
| 1820 | ; | 
|---|
| 1821 |  | 
|---|
| 1822 | /* ------------------------------ Win32 expressions ------------------------------ */ | 
|---|
| 1823 | /* All win16 numbers are also handled here. This is inconsistent with MS' | 
|---|
| 1824 | * resource compiler, but what the heck, its just handy to have. | 
|---|
| 1825 | */ | 
|---|
| 1826 | e_expr  : /* Empty */   { $$ = 0; } | 
|---|
| 1827 | | expr          { $$ = new_int($1); } | 
|---|
| 1828 | ; | 
|---|
| 1829 |  | 
|---|
| 1830 | /* This rule moves ALL s/r conflicts on {bi,u}nary - and + to here */ | 
|---|
| 1831 | expr    : xpr   { $$ = ($1); } | 
|---|
| 1832 | ; | 
|---|
| 1833 |  | 
|---|
| 1834 | xpr     : xpr '+' xpr   { $$ = ($1) + ($3); } | 
|---|
| 1835 | | xpr '-' xpr   { $$ = ($1) - ($3); } | 
|---|
| 1836 | | xpr '|' xpr   { $$ = ($1) | ($3); } | 
|---|
| 1837 | | xpr '&' xpr   { $$ = ($1) & ($3); } | 
|---|
| 1838 | | xpr '*' xpr   { $$ = ($1) * ($3); } | 
|---|
| 1839 | | xpr '/' xpr   { $$ = ($1) / ($3); } | 
|---|
| 1840 | | xpr '^' xpr   { $$ = ($1) ^ ($3); } | 
|---|
| 1841 | | '~' xpr       { $$ = ~($2); } | 
|---|
| 1842 | | '-' xpr %prec pUPM    { $$ = -($2); } | 
|---|
| 1843 | | '+' xpr %prec pUPM    { $$ = $2; } | 
|---|
| 1844 | | '(' xpr ')'   { $$ = $2; } | 
|---|
| 1845 | | any_num       { $$ = $1; } | 
|---|
| 1846 | | tNOT any_num  { $$ = ~($2); } | 
|---|
| 1847 | ; | 
|---|
| 1848 |  | 
|---|
| 1849 | any_num : tNUMBER       { $$ = $1; } | 
|---|
| 1850 | | tLNUMBER      { $$ = $1; } | 
|---|
| 1851 | ; | 
|---|
| 1852 |  | 
|---|
| 1853 | %% | 
|---|
| 1854 | /* Dialog specific functions */ | 
|---|
| 1855 | static dialog_t *dialog_style(style_t * st, dialog_t *dlg) | 
|---|
| 1856 | { | 
|---|
| 1857 | assert(dlg != NULL); | 
|---|
| 1858 | if(dlg->style == NULL) | 
|---|
| 1859 | { | 
|---|
| 1860 | dlg->style = new_style(0,0); | 
|---|
| 1861 | } | 
|---|
| 1862 |  | 
|---|
| 1863 | if(dlg->gotstyle) | 
|---|
| 1864 | { | 
|---|
| 1865 | yywarning("Style already defined, or-ing together"); | 
|---|
| 1866 | } | 
|---|
| 1867 | else | 
|---|
| 1868 | { | 
|---|
| 1869 | dlg->style->or_mask = 0; | 
|---|
| 1870 | dlg->style->and_mask = 0; | 
|---|
| 1871 | } | 
|---|
| 1872 | dlg->style->or_mask |= st->or_mask; | 
|---|
| 1873 | dlg->style->and_mask |= st->and_mask; | 
|---|
| 1874 | dlg->gotstyle = TRUE; | 
|---|
| 1875 | free(st); | 
|---|
| 1876 | return dlg; | 
|---|
| 1877 | } | 
|---|
| 1878 |  | 
|---|
| 1879 | static dialog_t *dialog_exstyle(style_t *st, dialog_t *dlg) | 
|---|
| 1880 | { | 
|---|
| 1881 | assert(dlg != NULL); | 
|---|
| 1882 | if(dlg->exstyle == NULL) | 
|---|
| 1883 | { | 
|---|
| 1884 | dlg->exstyle = new_style(0,0); | 
|---|
| 1885 | } | 
|---|
| 1886 |  | 
|---|
| 1887 | if(dlg->gotexstyle) | 
|---|
| 1888 | { | 
|---|
| 1889 | yywarning("ExStyle already defined, or-ing together"); | 
|---|
| 1890 | } | 
|---|
| 1891 | else | 
|---|
| 1892 | { | 
|---|
| 1893 | dlg->exstyle->or_mask = 0; | 
|---|
| 1894 | dlg->exstyle->and_mask = 0; | 
|---|
| 1895 | } | 
|---|
| 1896 | dlg->exstyle->or_mask |= st->or_mask; | 
|---|
| 1897 | dlg->exstyle->and_mask |= st->and_mask; | 
|---|
| 1898 | dlg->gotexstyle = TRUE; | 
|---|
| 1899 | free(st); | 
|---|
| 1900 | return dlg; | 
|---|
| 1901 | } | 
|---|
| 1902 |  | 
|---|
| 1903 | static dialog_t *dialog_caption(string_t *s, dialog_t *dlg) | 
|---|
| 1904 | { | 
|---|
| 1905 | assert(dlg != NULL); | 
|---|
| 1906 | if(dlg->title) | 
|---|
| 1907 | yyerror("Caption already defined"); | 
|---|
| 1908 | dlg->title = s; | 
|---|
| 1909 | return dlg; | 
|---|
| 1910 | } | 
|---|
| 1911 |  | 
|---|
| 1912 | static dialog_t *dialog_font(font_id_t *f, dialog_t *dlg) | 
|---|
| 1913 | { | 
|---|
| 1914 | assert(dlg != NULL); | 
|---|
| 1915 | if(dlg->font) | 
|---|
| 1916 | yyerror("Font already defined"); | 
|---|
| 1917 | dlg->font = f; | 
|---|
| 1918 | return dlg; | 
|---|
| 1919 | } | 
|---|
| 1920 |  | 
|---|
| 1921 | static dialog_t *dialog_class(name_id_t *n, dialog_t *dlg) | 
|---|
| 1922 | { | 
|---|
| 1923 | assert(dlg != NULL); | 
|---|
| 1924 | if(dlg->dlgclass) | 
|---|
| 1925 | yyerror("Class already defined"); | 
|---|
| 1926 | dlg->dlgclass = n; | 
|---|
| 1927 | return dlg; | 
|---|
| 1928 | } | 
|---|
| 1929 |  | 
|---|
| 1930 | static dialog_t *dialog_menu(name_id_t *m, dialog_t *dlg) | 
|---|
| 1931 | { | 
|---|
| 1932 | assert(dlg != NULL); | 
|---|
| 1933 | if(dlg->menu) | 
|---|
| 1934 | yyerror("Menu already defined"); | 
|---|
| 1935 | dlg->menu = m; | 
|---|
| 1936 | return dlg; | 
|---|
| 1937 | } | 
|---|
| 1938 |  | 
|---|
| 1939 | static dialog_t *dialog_language(language_t *l, dialog_t *dlg) | 
|---|
| 1940 | { | 
|---|
| 1941 | assert(dlg != NULL); | 
|---|
| 1942 | if(dlg->lvc.language) | 
|---|
| 1943 | yyerror("Language already defined"); | 
|---|
| 1944 | dlg->lvc.language = l; | 
|---|
| 1945 | return dlg; | 
|---|
| 1946 | } | 
|---|
| 1947 |  | 
|---|
| 1948 | static dialog_t *dialog_characteristics(characts_t *c, dialog_t *dlg) | 
|---|
| 1949 | { | 
|---|
| 1950 | assert(dlg != NULL); | 
|---|
| 1951 | if(dlg->lvc.characts) | 
|---|
| 1952 | yyerror("Characteristics already defined"); | 
|---|
| 1953 | dlg->lvc.characts = c; | 
|---|
| 1954 | return dlg; | 
|---|
| 1955 | } | 
|---|
| 1956 |  | 
|---|
| 1957 | static dialog_t *dialog_version(version_t *v, dialog_t *dlg) | 
|---|
| 1958 | { | 
|---|
| 1959 | assert(dlg != NULL); | 
|---|
| 1960 | if(dlg->lvc.version) | 
|---|
| 1961 | yyerror("Version already defined"); | 
|---|
| 1962 | dlg->lvc.version = v; | 
|---|
| 1963 | return dlg; | 
|---|
| 1964 | } | 
|---|
| 1965 |  | 
|---|
| 1966 | /* Controls specific functions */ | 
|---|
| 1967 | static control_t *ins_ctrl(int type, int special_style, control_t *ctrl, control_t *prev) | 
|---|
| 1968 | { | 
|---|
| 1969 | /* Hm... this seems to be jammed in at all time... */ | 
|---|
| 1970 | int defaultstyle = WS_CHILD | WS_VISIBLE; | 
|---|
| 1971 |  | 
|---|
| 1972 | assert(ctrl != NULL); | 
|---|
| 1973 | ctrl->prev = prev; | 
|---|
| 1974 |  | 
|---|
| 1975 | if(prev) | 
|---|
| 1976 | prev->next = ctrl; | 
|---|
| 1977 |  | 
|---|
| 1978 | if(type != -1) | 
|---|
| 1979 | { | 
|---|
| 1980 | ctrl->ctlclass = new_name_id(); | 
|---|
| 1981 | ctrl->ctlclass->type = name_ord; | 
|---|
| 1982 | ctrl->ctlclass->name.i_name = type; | 
|---|
| 1983 | } | 
|---|
| 1984 |  | 
|---|
| 1985 | switch(type) | 
|---|
| 1986 | { | 
|---|
| 1987 | case CT_BUTTON: | 
|---|
| 1988 | if(special_style != BS_GROUPBOX && special_style != BS_RADIOBUTTON) | 
|---|
| 1989 | defaultstyle |= WS_TABSTOP; | 
|---|
| 1990 | break; | 
|---|
| 1991 | case CT_EDIT: | 
|---|
| 1992 | defaultstyle |= WS_TABSTOP | WS_BORDER; | 
|---|
| 1993 | break; | 
|---|
| 1994 | case CT_LISTBOX: | 
|---|
| 1995 | defaultstyle |= LBS_NOTIFY | WS_BORDER; | 
|---|
| 1996 | break; | 
|---|
| 1997 | case CT_COMBOBOX: | 
|---|
| 1998 | defaultstyle |= CBS_SIMPLE; | 
|---|
| 1999 | break; | 
|---|
| 2000 | case CT_STATIC: | 
|---|
| 2001 | if(special_style == SS_CENTER || special_style == SS_LEFT || special_style == SS_RIGHT) | 
|---|
| 2002 | defaultstyle |= WS_GROUP; | 
|---|
| 2003 | break; | 
|---|
| 2004 | } | 
|---|
| 2005 |  | 
|---|
| 2006 | if(!ctrl->gotstyle)     /* Handle default style setting */ | 
|---|
| 2007 | { | 
|---|
| 2008 | switch(type) | 
|---|
| 2009 | { | 
|---|
| 2010 | case CT_EDIT: | 
|---|
| 2011 | defaultstyle |= ES_LEFT; | 
|---|
| 2012 | break; | 
|---|
| 2013 | case CT_LISTBOX: | 
|---|
| 2014 | defaultstyle |= LBS_NOTIFY; | 
|---|
| 2015 | break; | 
|---|
| 2016 | case CT_COMBOBOX: | 
|---|
| 2017 | defaultstyle |= CBS_SIMPLE | WS_TABSTOP; | 
|---|
| 2018 | break; | 
|---|
| 2019 | case CT_SCROLLBAR: | 
|---|
| 2020 | defaultstyle |= SBS_HORZ; | 
|---|
| 2021 | break; | 
|---|
| 2022 | case CT_BUTTON: | 
|---|
| 2023 | switch(special_style) | 
|---|
| 2024 | { | 
|---|
| 2025 | case BS_CHECKBOX: | 
|---|
| 2026 | case BS_DEFPUSHBUTTON: | 
|---|
| 2027 | case BS_PUSHBUTTON: | 
|---|
| 2028 | case BS_GROUPBOX: | 
|---|
| 2029 | /*                      case BS_PUSHBOX:        */ | 
|---|
| 2030 | case BS_AUTORADIOBUTTON: | 
|---|
| 2031 | case BS_AUTO3STATE: | 
|---|
| 2032 | case BS_3STATE: | 
|---|
| 2033 | case BS_AUTOCHECKBOX: | 
|---|
| 2034 | defaultstyle |= WS_TABSTOP; | 
|---|
| 2035 | break; | 
|---|
| 2036 | default: | 
|---|
| 2037 | yywarning("Unknown default button control-style 0x%08x", special_style); | 
|---|
| 2038 | case BS_RADIOBUTTON: | 
|---|
| 2039 | break; | 
|---|
| 2040 | } | 
|---|
| 2041 | break; | 
|---|
| 2042 |  | 
|---|
| 2043 | case CT_STATIC: | 
|---|
| 2044 | switch(special_style) | 
|---|
| 2045 | { | 
|---|
| 2046 | case SS_LEFT: | 
|---|
| 2047 | case SS_RIGHT: | 
|---|
| 2048 | case SS_CENTER: | 
|---|
| 2049 | defaultstyle |= WS_GROUP; | 
|---|
| 2050 | break; | 
|---|
| 2051 | case SS_ICON:   /* Special case */ | 
|---|
| 2052 | break; | 
|---|
| 2053 | default: | 
|---|
| 2054 | yywarning("Unknown default static control-style 0x%08x", special_style); | 
|---|
| 2055 | break; | 
|---|
| 2056 | } | 
|---|
| 2057 | break; | 
|---|
| 2058 | case -1:        /* Generic control */ | 
|---|
| 2059 | goto byebye; | 
|---|
| 2060 |  | 
|---|
| 2061 | default: | 
|---|
| 2062 | yyerror("Internal error (report this): Got weird control type 0x%08x", type); | 
|---|
| 2063 | } | 
|---|
| 2064 | } | 
|---|
| 2065 |  | 
|---|
| 2066 | /* The SS_ICON flag is always forced in for icon controls */ | 
|---|
| 2067 | if(type == CT_STATIC && special_style == SS_ICON) | 
|---|
| 2068 | defaultstyle |= SS_ICON; | 
|---|
| 2069 |  | 
|---|
| 2070 | if (!ctrl->gotstyle) | 
|---|
| 2071 | ctrl->style = new_style(0,0); | 
|---|
| 2072 |  | 
|---|
| 2073 | /* combine all styles */ | 
|---|
| 2074 | ctrl->style->or_mask = ctrl->style->or_mask | defaultstyle | special_style; | 
|---|
| 2075 | ctrl->gotstyle = TRUE; | 
|---|
| 2076 | byebye: | 
|---|
| 2077 | /* combine with NOT mask */ | 
|---|
| 2078 | if (ctrl->gotstyle) | 
|---|
| 2079 | { | 
|---|
| 2080 | ctrl->style->or_mask &= ~(ctrl->style->and_mask); | 
|---|
| 2081 | ctrl->style->and_mask = 0; | 
|---|
| 2082 | } | 
|---|
| 2083 | if (ctrl->gotexstyle) | 
|---|
| 2084 | { | 
|---|
| 2085 | ctrl->exstyle->or_mask &= ~(ctrl->exstyle->and_mask); | 
|---|
| 2086 | ctrl->exstyle->and_mask = 0; | 
|---|
| 2087 | } | 
|---|
| 2088 | return ctrl; | 
|---|
| 2089 | } | 
|---|
| 2090 |  | 
|---|
| 2091 | static name_id_t *convert_ctlclass(name_id_t *cls) | 
|---|
| 2092 | { | 
|---|
| 2093 | char *cc = NULL; | 
|---|
| 2094 | int iclass; | 
|---|
| 2095 |  | 
|---|
| 2096 | if(cls->type == name_ord) | 
|---|
| 2097 | return cls; | 
|---|
| 2098 | assert(cls->type == name_str); | 
|---|
| 2099 | if(cls->type == str_unicode) | 
|---|
| 2100 | { | 
|---|
| 2101 | yyerror("Don't yet support unicode class comparison"); | 
|---|
| 2102 | } | 
|---|
| 2103 | else | 
|---|
| 2104 | cc = cls->name.s_name->str.cstr; | 
|---|
| 2105 |  | 
|---|
| 2106 | if(!strcasecmp("BUTTON", cc)) | 
|---|
| 2107 | iclass = CT_BUTTON; | 
|---|
| 2108 | else if(!strcasecmp("COMBOBOX", cc)) | 
|---|
| 2109 | iclass = CT_COMBOBOX; | 
|---|
| 2110 | else if(!strcasecmp("LISTBOX", cc)) | 
|---|
| 2111 | iclass = CT_LISTBOX; | 
|---|
| 2112 | else if(!strcasecmp("EDIT", cc)) | 
|---|
| 2113 | iclass = CT_EDIT; | 
|---|
| 2114 | else if(!strcasecmp("STATIC", cc)) | 
|---|
| 2115 | iclass = CT_STATIC; | 
|---|
| 2116 | else if(!strcasecmp("SCROLLBAR", cc)) | 
|---|
| 2117 | iclass = CT_SCROLLBAR; | 
|---|
| 2118 | else | 
|---|
| 2119 | return cls;     /* No default, return user controlclass */ | 
|---|
| 2120 |  | 
|---|
| 2121 | free(cls->name.s_name->str.cstr); | 
|---|
| 2122 | free(cls->name.s_name); | 
|---|
| 2123 | cls->type = name_ord; | 
|---|
| 2124 | cls->name.i_name = iclass; | 
|---|
| 2125 | return cls; | 
|---|
| 2126 | } | 
|---|
| 2127 |  | 
|---|
| 2128 | /* DialogEx specific functions */ | 
|---|
| 2129 | static dialogex_t *dialogex_style(style_t * st, dialogex_t *dlg) | 
|---|
| 2130 | { | 
|---|
| 2131 | assert(dlg != NULL); | 
|---|
| 2132 | if(dlg->style == NULL) | 
|---|
| 2133 | { | 
|---|
| 2134 | dlg->style = new_style(0,0); | 
|---|
| 2135 | } | 
|---|
| 2136 |  | 
|---|
| 2137 | if(dlg->gotstyle) | 
|---|
| 2138 | { | 
|---|
| 2139 | yywarning("Style already defined, or-ing together"); | 
|---|
| 2140 | } | 
|---|
| 2141 | else | 
|---|
| 2142 | { | 
|---|
| 2143 | dlg->style->or_mask = 0; | 
|---|
| 2144 | dlg->style->and_mask = 0; | 
|---|
| 2145 | } | 
|---|
| 2146 | dlg->style->or_mask |= st->or_mask; | 
|---|
| 2147 | dlg->style->and_mask |= st->and_mask; | 
|---|
| 2148 | dlg->gotstyle = TRUE; | 
|---|
| 2149 | free(st); | 
|---|
| 2150 | return dlg; | 
|---|
| 2151 | } | 
|---|
| 2152 |  | 
|---|
| 2153 | static dialogex_t *dialogex_exstyle(style_t * st, dialogex_t *dlg) | 
|---|
| 2154 | { | 
|---|
| 2155 | assert(dlg != NULL); | 
|---|
| 2156 | if(dlg->exstyle == NULL) | 
|---|
| 2157 | { | 
|---|
| 2158 | dlg->exstyle = new_style(0,0); | 
|---|
| 2159 | } | 
|---|
| 2160 |  | 
|---|
| 2161 | if(dlg->gotexstyle) | 
|---|
| 2162 | { | 
|---|
| 2163 | yywarning("ExStyle already defined, or-ing together"); | 
|---|
| 2164 | } | 
|---|
| 2165 | else | 
|---|
| 2166 | { | 
|---|
| 2167 | dlg->exstyle->or_mask = 0; | 
|---|
| 2168 | dlg->exstyle->and_mask = 0; | 
|---|
| 2169 | } | 
|---|
| 2170 | dlg->exstyle->or_mask |= st->or_mask; | 
|---|
| 2171 | dlg->exstyle->and_mask |= st->and_mask; | 
|---|
| 2172 | dlg->gotexstyle = TRUE; | 
|---|
| 2173 | free(st); | 
|---|
| 2174 | return dlg; | 
|---|
| 2175 | } | 
|---|
| 2176 |  | 
|---|
| 2177 | static dialogex_t *dialogex_caption(string_t *s, dialogex_t *dlg) | 
|---|
| 2178 | { | 
|---|
| 2179 | assert(dlg != NULL); | 
|---|
| 2180 | if(dlg->title) | 
|---|
| 2181 | yyerror("Caption already defined"); | 
|---|
| 2182 | dlg->title = s; | 
|---|
| 2183 | return dlg; | 
|---|
| 2184 | } | 
|---|
| 2185 |  | 
|---|
| 2186 | static dialogex_t *dialogex_font(font_id_t *f, dialogex_t *dlg) | 
|---|
| 2187 | { | 
|---|
| 2188 | assert(dlg != NULL); | 
|---|
| 2189 | if(dlg->font) | 
|---|
| 2190 | yyerror("Font already defined"); | 
|---|
| 2191 | dlg->font = f; | 
|---|
| 2192 | return dlg; | 
|---|
| 2193 | } | 
|---|
| 2194 |  | 
|---|
| 2195 | static dialogex_t *dialogex_class(name_id_t *n, dialogex_t *dlg) | 
|---|
| 2196 | { | 
|---|
| 2197 | assert(dlg != NULL); | 
|---|
| 2198 | if(dlg->dlgclass) | 
|---|
| 2199 | yyerror("Class already defined"); | 
|---|
| 2200 | dlg->dlgclass = n; | 
|---|
| 2201 | return dlg; | 
|---|
| 2202 | } | 
|---|
| 2203 |  | 
|---|
| 2204 | static dialogex_t *dialogex_menu(name_id_t *m, dialogex_t *dlg) | 
|---|
| 2205 | { | 
|---|
| 2206 | assert(dlg != NULL); | 
|---|
| 2207 | if(dlg->menu) | 
|---|
| 2208 | yyerror("Menu already defined"); | 
|---|
| 2209 | dlg->menu = m; | 
|---|
| 2210 | return dlg; | 
|---|
| 2211 | } | 
|---|
| 2212 |  | 
|---|
| 2213 | static dialogex_t *dialogex_language(language_t *l, dialogex_t *dlg) | 
|---|
| 2214 | { | 
|---|
| 2215 | assert(dlg != NULL); | 
|---|
| 2216 | if(dlg->lvc.language) | 
|---|
| 2217 | yyerror("Language already defined"); | 
|---|
| 2218 | dlg->lvc.language = l; | 
|---|
| 2219 | return dlg; | 
|---|
| 2220 | } | 
|---|
| 2221 |  | 
|---|
| 2222 | static dialogex_t *dialogex_characteristics(characts_t *c, dialogex_t *dlg) | 
|---|
| 2223 | { | 
|---|
| 2224 | assert(dlg != NULL); | 
|---|
| 2225 | if(dlg->lvc.characts) | 
|---|
| 2226 | yyerror("Characteristics already defined"); | 
|---|
| 2227 | dlg->lvc.characts = c; | 
|---|
| 2228 | return dlg; | 
|---|
| 2229 | } | 
|---|
| 2230 |  | 
|---|
| 2231 | static dialogex_t *dialogex_version(version_t *v, dialogex_t *dlg) | 
|---|
| 2232 | { | 
|---|
| 2233 | assert(dlg != NULL); | 
|---|
| 2234 | if(dlg->lvc.version) | 
|---|
| 2235 | yyerror("Version already defined"); | 
|---|
| 2236 | dlg->lvc.version = v; | 
|---|
| 2237 | return dlg; | 
|---|
| 2238 | } | 
|---|
| 2239 |  | 
|---|
| 2240 | /* Accelerator specific functions */ | 
|---|
| 2241 | static event_t *add_event(int key, int id, int flags, event_t *prev) | 
|---|
| 2242 | { | 
|---|
| 2243 | event_t *ev = new_event(); | 
|---|
| 2244 |  | 
|---|
| 2245 | if((flags & (WRC_AF_VIRTKEY | WRC_AF_ASCII)) == (WRC_AF_VIRTKEY | WRC_AF_ASCII)) | 
|---|
| 2246 | yyerror("Cannot use both ASCII and VIRTKEY"); | 
|---|
| 2247 |  | 
|---|
| 2248 | ev->key = key; | 
|---|
| 2249 | ev->id = id; | 
|---|
| 2250 | ev->flags = flags & ~WRC_AF_ASCII; | 
|---|
| 2251 | ev->prev = prev; | 
|---|
| 2252 | if(prev) | 
|---|
| 2253 | prev->next = ev; | 
|---|
| 2254 | return ev; | 
|---|
| 2255 | } | 
|---|
| 2256 |  | 
|---|
| 2257 | static event_t *add_string_event(string_t *key, int id, int flags, event_t *prev) | 
|---|
| 2258 | { | 
|---|
| 2259 | int keycode = 0; | 
|---|
| 2260 | event_t *ev = new_event(); | 
|---|
| 2261 |  | 
|---|
| 2262 | if(key->type != str_char) | 
|---|
| 2263 | yyerror("Key code must be an ascii string"); | 
|---|
| 2264 |  | 
|---|
| 2265 | if((flags & WRC_AF_VIRTKEY) && (!isupper(key->str.cstr[0] & 0xff) && !isdigit(key->str.cstr[0] & 0xff))) | 
|---|
| 2266 | yyerror("VIRTKEY code is not equal to ascii value"); | 
|---|
| 2267 |  | 
|---|
| 2268 | if(key->str.cstr[0] == '^' && (flags & WRC_AF_CONTROL) != 0) | 
|---|
| 2269 | { | 
|---|
| 2270 | yyerror("Cannot use both '^' and CONTROL modifier"); | 
|---|
| 2271 | } | 
|---|
| 2272 | else if(key->str.cstr[0] == '^') | 
|---|
| 2273 | { | 
|---|
| 2274 | keycode = toupper(key->str.cstr[1]) - '@'; | 
|---|
| 2275 | if(keycode >= ' ') | 
|---|
| 2276 | yyerror("Control-code out of range"); | 
|---|
| 2277 | } | 
|---|
| 2278 | else | 
|---|
| 2279 | keycode = key->str.cstr[0]; | 
|---|
| 2280 | ev->key = keycode; | 
|---|
| 2281 | ev->id = id; | 
|---|
| 2282 | ev->flags = flags & ~WRC_AF_ASCII; | 
|---|
| 2283 | ev->prev = prev; | 
|---|
| 2284 | if(prev) | 
|---|
| 2285 | prev->next = ev; | 
|---|
| 2286 | return ev; | 
|---|
| 2287 | } | 
|---|
| 2288 |  | 
|---|
| 2289 | /* MenuEx specific functions */ | 
|---|
| 2290 | static itemex_opt_t *new_itemex_opt(int id, int type, int state, int helpid) | 
|---|
| 2291 | { | 
|---|
| 2292 | itemex_opt_t *opt = (itemex_opt_t *)xmalloc(sizeof(itemex_opt_t)); | 
|---|
| 2293 | opt->id = id; | 
|---|
| 2294 | opt->type = type; | 
|---|
| 2295 | opt->state = state; | 
|---|
| 2296 | opt->helpid = helpid; | 
|---|
| 2297 | return opt; | 
|---|
| 2298 | } | 
|---|
| 2299 |  | 
|---|
| 2300 | /* Raw data functions */ | 
|---|
| 2301 | static raw_data_t *load_file(string_t *name) | 
|---|
| 2302 | { | 
|---|
| 2303 | FILE *fp; | 
|---|
| 2304 | raw_data_t *rd; | 
|---|
| 2305 | if(name->type != str_char) | 
|---|
| 2306 | yyerror("Filename must be ASCII string"); | 
|---|
| 2307 |  | 
|---|
| 2308 | fp = open_include(name->str.cstr, 1, NULL); | 
|---|
| 2309 | if(!fp) | 
|---|
| 2310 | yyerror("Cannot open file %s", name->str.cstr); | 
|---|
| 2311 | rd = new_raw_data(); | 
|---|
| 2312 | fseek(fp, 0, SEEK_END); | 
|---|
| 2313 | rd->size = ftell(fp); | 
|---|
| 2314 | fseek(fp, 0, SEEK_SET); | 
|---|
| 2315 | rd->data = (char *)xmalloc(rd->size); | 
|---|
| 2316 | fread(rd->data, rd->size, 1, fp); | 
|---|
| 2317 | fclose(fp); | 
|---|
| 2318 | return rd; | 
|---|
| 2319 | } | 
|---|
| 2320 |  | 
|---|
| 2321 | static raw_data_t *int2raw_data(int i) | 
|---|
| 2322 | { | 
|---|
| 2323 | raw_data_t *rd; | 
|---|
| 2324 |  | 
|---|
| 2325 | if((int)((short)i) != i) | 
|---|
| 2326 | yywarning("Integer constant out of 16bit range (%d), truncated to %d\n", i, (short)i); | 
|---|
| 2327 |  | 
|---|
| 2328 | rd = new_raw_data(); | 
|---|
| 2329 | rd->size = sizeof(short); | 
|---|
| 2330 | rd->data = (char *)xmalloc(rd->size); | 
|---|
| 2331 | switch(byteorder) | 
|---|
| 2332 | { | 
|---|
| 2333 | #ifdef WORDS_BIGENDIAN | 
|---|
| 2334 | default: | 
|---|
| 2335 | #endif | 
|---|
| 2336 | case WRC_BO_BIG: | 
|---|
| 2337 | rd->data[0] = HIBYTE(i); | 
|---|
| 2338 | rd->data[1] = LOBYTE(i); | 
|---|
| 2339 | break; | 
|---|
| 2340 |  | 
|---|
| 2341 | #ifndef WORDS_BIGENDIAN | 
|---|
| 2342 | default: | 
|---|
| 2343 | #endif | 
|---|
| 2344 | case WRC_BO_LITTLE: | 
|---|
| 2345 | rd->data[1] = HIBYTE(i); | 
|---|
| 2346 | rd->data[0] = LOBYTE(i); | 
|---|
| 2347 | break; | 
|---|
| 2348 | } | 
|---|
| 2349 | return rd; | 
|---|
| 2350 | } | 
|---|
| 2351 |  | 
|---|
| 2352 | static raw_data_t *long2raw_data(int i) | 
|---|
| 2353 | { | 
|---|
| 2354 | raw_data_t *rd; | 
|---|
| 2355 | rd = new_raw_data(); | 
|---|
| 2356 | rd->size = sizeof(int); | 
|---|
| 2357 | rd->data = (char *)xmalloc(rd->size); | 
|---|
| 2358 | switch(byteorder) | 
|---|
| 2359 | { | 
|---|
| 2360 | #ifdef WORDS_BIGENDIAN | 
|---|
| 2361 | default: | 
|---|
| 2362 | #endif | 
|---|
| 2363 | case WRC_BO_BIG: | 
|---|
| 2364 | rd->data[0] = HIBYTE(HIWORD(i)); | 
|---|
| 2365 | rd->data[1] = LOBYTE(HIWORD(i)); | 
|---|
| 2366 | rd->data[2] = HIBYTE(LOWORD(i)); | 
|---|
| 2367 | rd->data[3] = LOBYTE(LOWORD(i)); | 
|---|
| 2368 | break; | 
|---|
| 2369 |  | 
|---|
| 2370 | #ifndef WORDS_BIGENDIAN | 
|---|
| 2371 | default: | 
|---|
| 2372 | #endif | 
|---|
| 2373 | case WRC_BO_LITTLE: | 
|---|
| 2374 | rd->data[3] = HIBYTE(HIWORD(i)); | 
|---|
| 2375 | rd->data[2] = LOBYTE(HIWORD(i)); | 
|---|
| 2376 | rd->data[1] = HIBYTE(LOWORD(i)); | 
|---|
| 2377 | rd->data[0] = LOBYTE(LOWORD(i)); | 
|---|
| 2378 | break; | 
|---|
| 2379 | } | 
|---|
| 2380 | return rd; | 
|---|
| 2381 | } | 
|---|
| 2382 |  | 
|---|
| 2383 | static raw_data_t *str2raw_data(string_t *str) | 
|---|
| 2384 | { | 
|---|
| 2385 | raw_data_t *rd; | 
|---|
| 2386 | rd = new_raw_data(); | 
|---|
| 2387 | rd->size = str->size * (str->type == str_char ? 1 : 2); | 
|---|
| 2388 | rd->data = (char *)xmalloc(rd->size); | 
|---|
| 2389 | if(str->type == str_char) | 
|---|
| 2390 | memcpy(rd->data, str->str.cstr, rd->size); | 
|---|
| 2391 | else if(str->type == str_unicode) | 
|---|
| 2392 | { | 
|---|
| 2393 | int i; | 
|---|
| 2394 | switch(byteorder) | 
|---|
| 2395 | { | 
|---|
| 2396 | #ifdef WORDS_BIGENDIAN | 
|---|
| 2397 | default: | 
|---|
| 2398 | #endif | 
|---|
| 2399 | case WRC_BO_BIG: | 
|---|
| 2400 | for(i = 0; i < str->size; i++) | 
|---|
| 2401 | { | 
|---|
| 2402 | rd->data[2*i + 0] = HIBYTE((WORD)str->str.wstr[i]); | 
|---|
| 2403 | rd->data[2*i + 1] = LOBYTE((WORD)str->str.wstr[i]); | 
|---|
| 2404 | } | 
|---|
| 2405 | break; | 
|---|
| 2406 | #ifndef WORDS_BIGENDIAN | 
|---|
| 2407 | default: | 
|---|
| 2408 | #endif | 
|---|
| 2409 | case WRC_BO_LITTLE: | 
|---|
| 2410 | for(i = 0; i < str->size; i++) | 
|---|
| 2411 | { | 
|---|
| 2412 | rd->data[2*i + 1] = HIBYTE((WORD)str->str.wstr[i]); | 
|---|
| 2413 | rd->data[2*i + 0] = LOBYTE((WORD)str->str.wstr[i]); | 
|---|
| 2414 | } | 
|---|
| 2415 | break; | 
|---|
| 2416 | } | 
|---|
| 2417 | } | 
|---|
| 2418 | else | 
|---|
| 2419 | internal_error(__FILE__, __LINE__, "Invalid stringtype"); | 
|---|
| 2420 | return rd; | 
|---|
| 2421 | } | 
|---|
| 2422 |  | 
|---|
| 2423 | static raw_data_t *merge_raw_data(raw_data_t *r1, raw_data_t *r2) | 
|---|
| 2424 | { | 
|---|
| 2425 | r1->data = xrealloc(r1->data, r1->size + r2->size); | 
|---|
| 2426 | memcpy(r1->data + r1->size, r2->data, r2->size); | 
|---|
| 2427 | r1->size += r2->size; | 
|---|
| 2428 | return r1; | 
|---|
| 2429 | } | 
|---|
| 2430 |  | 
|---|
| 2431 | static raw_data_t *merge_raw_data_int(raw_data_t *r1, int i) | 
|---|
| 2432 | { | 
|---|
| 2433 | raw_data_t *t = int2raw_data(i); | 
|---|
| 2434 | merge_raw_data(r1, t); | 
|---|
| 2435 | free(t->data); | 
|---|
| 2436 | free(t); | 
|---|
| 2437 | return r1; | 
|---|
| 2438 | } | 
|---|
| 2439 |  | 
|---|
| 2440 | static raw_data_t *merge_raw_data_long(raw_data_t *r1, int i) | 
|---|
| 2441 | { | 
|---|
| 2442 | raw_data_t *t = long2raw_data(i); | 
|---|
| 2443 | merge_raw_data(r1, t); | 
|---|
| 2444 | free(t->data); | 
|---|
| 2445 | free(t); | 
|---|
| 2446 | return r1; | 
|---|
| 2447 | } | 
|---|
| 2448 |  | 
|---|
| 2449 | static raw_data_t *merge_raw_data_str(raw_data_t *r1, string_t *str) | 
|---|
| 2450 | { | 
|---|
| 2451 | raw_data_t *t = str2raw_data(str); | 
|---|
| 2452 | merge_raw_data(r1, t); | 
|---|
| 2453 | free(t->data); | 
|---|
| 2454 | free(t); | 
|---|
| 2455 | return r1; | 
|---|
| 2456 | } | 
|---|
| 2457 |  | 
|---|
| 2458 | /* Function the go back in a list to get the head */ | 
|---|
| 2459 | static menu_item_t *get_item_head(menu_item_t *p) | 
|---|
| 2460 | { | 
|---|
| 2461 | if(!p) | 
|---|
| 2462 | return NULL; | 
|---|
| 2463 | while(p->prev) | 
|---|
| 2464 | p = p->prev; | 
|---|
| 2465 | return p; | 
|---|
| 2466 | } | 
|---|
| 2467 |  | 
|---|
| 2468 | static menuex_item_t *get_itemex_head(menuex_item_t *p) | 
|---|
| 2469 | { | 
|---|
| 2470 | if(!p) | 
|---|
| 2471 | return NULL; | 
|---|
| 2472 | while(p->prev) | 
|---|
| 2473 | p = p->prev; | 
|---|
| 2474 | return p; | 
|---|
| 2475 | } | 
|---|
| 2476 |  | 
|---|
| 2477 | static resource_t *get_resource_head(resource_t *p) | 
|---|
| 2478 | { | 
|---|
| 2479 | if(!p) | 
|---|
| 2480 | return NULL; | 
|---|
| 2481 | while(p->prev) | 
|---|
| 2482 | p = p->prev; | 
|---|
| 2483 | return p; | 
|---|
| 2484 | } | 
|---|
| 2485 |  | 
|---|
| 2486 | static ver_block_t *get_ver_block_head(ver_block_t *p) | 
|---|
| 2487 | { | 
|---|
| 2488 | if(!p) | 
|---|
| 2489 | return NULL; | 
|---|
| 2490 | while(p->prev) | 
|---|
| 2491 | p = p->prev; | 
|---|
| 2492 | return p; | 
|---|
| 2493 | } | 
|---|
| 2494 |  | 
|---|
| 2495 | static ver_value_t *get_ver_value_head(ver_value_t *p) | 
|---|
| 2496 | { | 
|---|
| 2497 | if(!p) | 
|---|
| 2498 | return NULL; | 
|---|
| 2499 | while(p->prev) | 
|---|
| 2500 | p = p->prev; | 
|---|
| 2501 | return p; | 
|---|
| 2502 | } | 
|---|
| 2503 |  | 
|---|
| 2504 | static control_t *get_control_head(control_t *p) | 
|---|
| 2505 | { | 
|---|
| 2506 | if(!p) | 
|---|
| 2507 | return NULL; | 
|---|
| 2508 | while(p->prev) | 
|---|
| 2509 | p = p->prev; | 
|---|
| 2510 | return p; | 
|---|
| 2511 | } | 
|---|
| 2512 |  | 
|---|
| 2513 | static event_t *get_event_head(event_t *p) | 
|---|
| 2514 | { | 
|---|
| 2515 | if(!p) | 
|---|
| 2516 | return NULL; | 
|---|
| 2517 | while(p->prev) | 
|---|
| 2518 | p = p->prev; | 
|---|
| 2519 | return p; | 
|---|
| 2520 | } | 
|---|
| 2521 |  | 
|---|
| 2522 | /* Find a stringtable with given language */ | 
|---|
| 2523 | static stringtable_t *find_stringtable(lvc_t *lvc) | 
|---|
| 2524 | { | 
|---|
| 2525 | stringtable_t *stt; | 
|---|
| 2526 |  | 
|---|
| 2527 | assert(lvc != NULL); | 
|---|
| 2528 |  | 
|---|
| 2529 | if(!lvc->language) | 
|---|
| 2530 | lvc->language = dup_language(currentlanguage); | 
|---|
| 2531 |  | 
|---|
| 2532 | for(stt = sttres; stt; stt = stt->next) | 
|---|
| 2533 | { | 
|---|
| 2534 | if(stt->lvc.language->id == lvc->language->id | 
|---|
| 2535 | && stt->lvc.language->sub == lvc->language->sub) | 
|---|
| 2536 | { | 
|---|
| 2537 | /* Found a table with the same language */ | 
|---|
| 2538 | /* The version and characteristics are now handled | 
|---|
| 2539 | * in the generation of the individual stringtables. | 
|---|
| 2540 | * This enables localized analysis. | 
|---|
| 2541 | if((stt->lvc.version && lvc->version && *(stt->lvc.version) != *(lvc->version)) | 
|---|
| 2542 | || (!stt->lvc.version && lvc->version) | 
|---|
| 2543 | || (stt->lvc.version && !lvc->version)) | 
|---|
| 2544 | yywarning("Stringtable's versions are not the same, using first definition"); | 
|---|
| 2545 |  | 
|---|
| 2546 | if((stt->lvc.characts && lvc->characts && *(stt->lvc.characts) != *(lvc->characts)) | 
|---|
| 2547 | || (!stt->lvc.characts && lvc->characts) | 
|---|
| 2548 | || (stt->lvc.characts && !lvc->characts)) | 
|---|
| 2549 | yywarning("Stringtable's characteristics are not the same, using first definition"); | 
|---|
| 2550 | */ | 
|---|
| 2551 | return stt; | 
|---|
| 2552 | } | 
|---|
| 2553 | } | 
|---|
| 2554 | return NULL; | 
|---|
| 2555 | } | 
|---|
| 2556 |  | 
|---|
| 2557 | /* qsort sorting function for string table entries */ | 
|---|
| 2558 | #define STE(p)  ((stt_entry_t *)(p)) | 
|---|
| 2559 | static int sort_stt_entry(const void *e1, const void *e2) | 
|---|
| 2560 | { | 
|---|
| 2561 | return STE(e1)->id - STE(e2)->id; | 
|---|
| 2562 | } | 
|---|
| 2563 | #undef STE | 
|---|
| 2564 |  | 
|---|
| 2565 | static resource_t *build_stt_resources(stringtable_t *stthead) | 
|---|
| 2566 | { | 
|---|
| 2567 | stringtable_t *stt; | 
|---|
| 2568 | stringtable_t *newstt; | 
|---|
| 2569 | resource_t *rsc; | 
|---|
| 2570 | resource_t *rsclist = NULL; | 
|---|
| 2571 | resource_t *rsctail = NULL; | 
|---|
| 2572 | int i; | 
|---|
| 2573 | int j; | 
|---|
| 2574 | DWORD andsum; | 
|---|
| 2575 | DWORD orsum; | 
|---|
| 2576 | characts_t *characts; | 
|---|
| 2577 | version_t *version; | 
|---|
| 2578 |  | 
|---|
| 2579 | if(!stthead) | 
|---|
| 2580 | return NULL; | 
|---|
| 2581 |  | 
|---|
| 2582 | /* For all languages defined */ | 
|---|
| 2583 | for(stt = stthead; stt; stt = stt->next) | 
|---|
| 2584 | { | 
|---|
| 2585 | assert(stt->nentries > 0); | 
|---|
| 2586 |  | 
|---|
| 2587 | /* Sort the entries */ | 
|---|
| 2588 | if(stt->nentries > 1) | 
|---|
| 2589 | qsort(stt->entries, stt->nentries, sizeof(stt->entries[0]), sort_stt_entry); | 
|---|
| 2590 |  | 
|---|
| 2591 | for(i = 0; i < stt->nentries; ) | 
|---|
| 2592 | { | 
|---|
| 2593 | newstt = new_stringtable(&stt->lvc); | 
|---|
| 2594 | newstt->entries = (stt_entry_t *)xmalloc(16 * sizeof(stt_entry_t)); | 
|---|
| 2595 | newstt->nentries = 16; | 
|---|
| 2596 | newstt->idbase = stt->entries[i].id & ~0xf; | 
|---|
| 2597 | for(j = 0; j < 16 && i < stt->nentries; j++) | 
|---|
| 2598 | { | 
|---|
| 2599 | if(stt->entries[i].id - newstt->idbase == j) | 
|---|
| 2600 | { | 
|---|
| 2601 | newstt->entries[j] = stt->entries[i]; | 
|---|
| 2602 | i++; | 
|---|
| 2603 | } | 
|---|
| 2604 | } | 
|---|
| 2605 | andsum = ~0; | 
|---|
| 2606 | orsum = 0; | 
|---|
| 2607 | characts = NULL; | 
|---|
| 2608 | version = NULL; | 
|---|
| 2609 | /* Check individual memory options and get | 
|---|
| 2610 | * the first characteristics/version | 
|---|
| 2611 | */ | 
|---|
| 2612 | for(j = 0; j < 16; j++) | 
|---|
| 2613 | { | 
|---|
| 2614 | if(!newstt->entries[j].str) | 
|---|
| 2615 | continue; | 
|---|
| 2616 | andsum &= newstt->entries[j].memopt; | 
|---|
| 2617 | orsum |= newstt->entries[j].memopt; | 
|---|
| 2618 | if(!characts) | 
|---|
| 2619 | characts = newstt->entries[j].characts; | 
|---|
| 2620 | if(!version) | 
|---|
| 2621 | version = newstt->entries[j].version; | 
|---|
| 2622 | } | 
|---|
| 2623 | if(andsum != orsum) | 
|---|
| 2624 | { | 
|---|
| 2625 | warning("Stringtable's memory options are not equal (idbase: %d)", newstt->idbase); | 
|---|
| 2626 | } | 
|---|
| 2627 | /* Check version and characteristics */ | 
|---|
| 2628 | for(j = 0; j < 16; j++) | 
|---|
| 2629 | { | 
|---|
| 2630 | if(characts | 
|---|
| 2631 | && newstt->entries[j].characts | 
|---|
| 2632 | && *newstt->entries[j].characts != *characts) | 
|---|
| 2633 | warning("Stringtable's characteristics are not the same (idbase: %d)", newstt->idbase); | 
|---|
| 2634 | if(version | 
|---|
| 2635 | && newstt->entries[j].version | 
|---|
| 2636 | && *newstt->entries[j].version != *version) | 
|---|
| 2637 | warning("Stringtable's versions are not the same (idbase: %d)", newstt->idbase); | 
|---|
| 2638 | } | 
|---|
| 2639 | rsc = new_resource(res_stt, newstt, newstt->memopt, newstt->lvc.language); | 
|---|
| 2640 | rsc->name = new_name_id(); | 
|---|
| 2641 | rsc->name->type = name_ord; | 
|---|
| 2642 | rsc->name->name.i_name = (newstt->idbase >> 4) + 1; | 
|---|
| 2643 | rsc->memopt = andsum; /* Set to least common denominator */ | 
|---|
| 2644 | newstt->memopt = andsum; | 
|---|
| 2645 | newstt->lvc.characts = characts; | 
|---|
| 2646 | newstt->lvc.version = version; | 
|---|
| 2647 | if(!rsclist) | 
|---|
| 2648 | { | 
|---|
| 2649 | rsclist = rsc; | 
|---|
| 2650 | rsctail = rsc; | 
|---|
| 2651 | } | 
|---|
| 2652 | else | 
|---|
| 2653 | { | 
|---|
| 2654 | rsctail->next = rsc; | 
|---|
| 2655 | rsc->prev = rsctail; | 
|---|
| 2656 | rsctail = rsc; | 
|---|
| 2657 | } | 
|---|
| 2658 | } | 
|---|
| 2659 | } | 
|---|
| 2660 | return rsclist; | 
|---|
| 2661 | } | 
|---|
| 2662 |  | 
|---|
| 2663 |  | 
|---|
| 2664 | static toolbar_item_t *ins_tlbr_button(toolbar_item_t *prev, toolbar_item_t *idrec) | 
|---|
| 2665 | { | 
|---|
| 2666 | idrec->prev = prev; | 
|---|
| 2667 | if(prev) | 
|---|
| 2668 | prev->next = idrec; | 
|---|
| 2669 |  | 
|---|
| 2670 | return idrec; | 
|---|
| 2671 | } | 
|---|
| 2672 |  | 
|---|
| 2673 | static toolbar_item_t *get_tlbr_buttons_head(toolbar_item_t *p, int *nitems) | 
|---|
| 2674 | { | 
|---|
| 2675 | if(!p) | 
|---|
| 2676 | { | 
|---|
| 2677 | *nitems = 0; | 
|---|
| 2678 | return NULL; | 
|---|
| 2679 | } | 
|---|
| 2680 |  | 
|---|
| 2681 | *nitems = 1; | 
|---|
| 2682 |  | 
|---|
| 2683 | while(p->prev) | 
|---|
| 2684 | { | 
|---|
| 2685 | (*nitems)++; | 
|---|
| 2686 | p = p->prev; | 
|---|
| 2687 | } | 
|---|
| 2688 |  | 
|---|
| 2689 | return p; | 
|---|
| 2690 | } | 
|---|
| 2691 |  | 
|---|
| 2692 | static string_t *make_filename(string_t *str) | 
|---|
| 2693 | { | 
|---|
| 2694 | char *cptr; | 
|---|
| 2695 |  | 
|---|
| 2696 | if(str->type != str_char) | 
|---|
| 2697 | yyerror("Cannot handle UNICODE filenames"); | 
|---|
| 2698 |  | 
|---|
| 2699 | /* Remove escaped backslash and convert to forward */ | 
|---|
| 2700 | cptr = str->str.cstr; | 
|---|
| 2701 | for(cptr = str->str.cstr; (cptr = strchr(cptr, '\\')) != NULL; cptr++) | 
|---|
| 2702 | { | 
|---|
| 2703 | if(cptr[1] == '\\') | 
|---|
| 2704 | { | 
|---|
| 2705 | memmove(cptr, cptr+1, strlen(cptr)); | 
|---|
| 2706 | str->size--; | 
|---|
| 2707 | } | 
|---|
| 2708 | *cptr = '/'; | 
|---|
| 2709 | } | 
|---|
| 2710 |  | 
|---|
| 2711 | /* Convert to lower case. Seems to be reasonable to do */ | 
|---|
| 2712 | for(cptr = str->str.cstr; !leave_case && *cptr; cptr++) | 
|---|
| 2713 | { | 
|---|
| 2714 | *cptr = tolower(*cptr); | 
|---|
| 2715 | } | 
|---|
| 2716 | return str; | 
|---|
| 2717 | } | 
|---|
| 2718 |  | 
|---|
| 2719 | /* | 
|---|
| 2720 | * Process all resources to extract fonts and build | 
|---|
| 2721 | * a fontdir resource. | 
|---|
| 2722 | * | 
|---|
| 2723 | * Note: MS' resource compiler (build 1472) does not | 
|---|
| 2724 | * handle font resources with different languages. | 
|---|
| 2725 | * The fontdir is generated in the last active language | 
|---|
| 2726 | * and font identifiers must be unique across the entire | 
|---|
| 2727 | * source. | 
|---|
| 2728 | * This is not logical considering the localization | 
|---|
| 2729 | * constraints of all other resource types. MS has, | 
|---|
| 2730 | * most probably, never testet localized fonts. However, | 
|---|
| 2731 | * using fontresources is rare, so it might not occur | 
|---|
| 2732 | * in normal applications. | 
|---|
| 2733 | * Wine does require better localization because a lot | 
|---|
| 2734 | * of languages are coded into the same executable. | 
|---|
| 2735 | * Therefore, I will generate fontdirs for *each* | 
|---|
| 2736 | * localized set of fonts. | 
|---|
| 2737 | */ | 
|---|
| 2738 | static resource_t *build_fontdir(resource_t **fnt, int nfnt) | 
|---|
| 2739 | { | 
|---|
| 2740 | static int once = 0; | 
|---|
| 2741 | if(!once) | 
|---|
| 2742 | { | 
|---|
| 2743 | warning("Need to parse fonts, not yet implemented (fnt: %p, nfnt: %d)", fnt, nfnt); | 
|---|
| 2744 | once++; | 
|---|
| 2745 | } | 
|---|
| 2746 | return NULL; | 
|---|
| 2747 | } | 
|---|
| 2748 |  | 
|---|
| 2749 | static resource_t *build_fontdirs(resource_t *tail) | 
|---|
| 2750 | { | 
|---|
| 2751 | resource_t *rsc; | 
|---|
| 2752 | resource_t *lst = NULL; | 
|---|
| 2753 | resource_t **fnt = NULL;        /* List of all fonts */ | 
|---|
| 2754 | int nfnt = 0; | 
|---|
| 2755 | resource_t **fnd = NULL;        /* List of all fontdirs */ | 
|---|
| 2756 | int nfnd = 0; | 
|---|
| 2757 | resource_t **lanfnt = NULL; | 
|---|
| 2758 | int nlanfnt = 0; | 
|---|
| 2759 | int i; | 
|---|
| 2760 | name_id_t nid; | 
|---|
| 2761 | string_t str; | 
|---|
| 2762 | int fntleft; | 
|---|
| 2763 |  | 
|---|
| 2764 | nid.type = name_str; | 
|---|
| 2765 | nid.name.s_name = &str; | 
|---|
| 2766 | str.type = str_char; | 
|---|
| 2767 | str.str.cstr = "FONTDIR"; | 
|---|
| 2768 | str.size = 7; | 
|---|
| 2769 |  | 
|---|
| 2770 | /* Extract all fonts and fontdirs */ | 
|---|
| 2771 | for(rsc = tail; rsc; rsc = rsc->prev) | 
|---|
| 2772 | { | 
|---|
| 2773 | if(rsc->type == res_fnt) | 
|---|
| 2774 | { | 
|---|
| 2775 | nfnt++; | 
|---|
| 2776 | fnt = xrealloc(fnt, nfnt * sizeof(*fnt)); | 
|---|
| 2777 | fnt[nfnt-1] = rsc; | 
|---|
| 2778 | } | 
|---|
| 2779 | else if(rsc->type == res_fntdir) | 
|---|
| 2780 | { | 
|---|
| 2781 | nfnd++; | 
|---|
| 2782 | fnd = xrealloc(fnd, nfnd * sizeof(*fnd)); | 
|---|
| 2783 | fnd[nfnd-1] = rsc; | 
|---|
| 2784 | } | 
|---|
| 2785 | } | 
|---|
| 2786 |  | 
|---|
| 2787 | /* Verify the name of the present fontdirs */ | 
|---|
| 2788 | for(i = 0; i < nfnd; i++) | 
|---|
| 2789 | { | 
|---|
| 2790 | if(compare_name_id(&nid, fnd[i]->name)) | 
|---|
| 2791 | { | 
|---|
| 2792 | warning("User supplied FONTDIR entry has an invalid name '%s', ignored", | 
|---|
| 2793 | get_nameid_str(fnd[i]->name)); | 
|---|
| 2794 | fnd[i] = NULL; | 
|---|
| 2795 | } | 
|---|
| 2796 | } | 
|---|
| 2797 |  | 
|---|
| 2798 | /* Sanity check */ | 
|---|
| 2799 | if(nfnt == 0) | 
|---|
| 2800 | { | 
|---|
| 2801 | if(nfnd != 0) | 
|---|
| 2802 | warning("Found %d FONTDIR entries without any fonts present", nfnd); | 
|---|
| 2803 | goto clean; | 
|---|
| 2804 | } | 
|---|
| 2805 |  | 
|---|
| 2806 | /* Copy space */ | 
|---|
| 2807 | lanfnt = xmalloc(nfnt * sizeof(*lanfnt)); | 
|---|
| 2808 |  | 
|---|
| 2809 | /* Get all fonts covered by fontdirs */ | 
|---|
| 2810 | for(i = 0; i < nfnd; i++) | 
|---|
| 2811 | { | 
|---|
| 2812 | int j; | 
|---|
| 2813 | WORD cnt; | 
|---|
| 2814 | int isswapped = 0; | 
|---|
| 2815 |  | 
|---|
| 2816 | if(!fnd[i]) | 
|---|
| 2817 | continue; | 
|---|
| 2818 | for(j = 0; j < nfnt; j++) | 
|---|
| 2819 | { | 
|---|
| 2820 | if(!fnt[j]) | 
|---|
| 2821 | continue; | 
|---|
| 2822 | if(fnt[j]->lan->id == fnd[i]->lan->id && fnt[j]->lan->sub == fnd[i]->lan->sub) | 
|---|
| 2823 | { | 
|---|
| 2824 | lanfnt[nlanfnt] = fnt[j]; | 
|---|
| 2825 | nlanfnt++; | 
|---|
| 2826 | fnt[j] = NULL; | 
|---|
| 2827 | } | 
|---|
| 2828 | } | 
|---|
| 2829 |  | 
|---|
| 2830 | cnt = *(WORD *)fnd[i]->res.fnd->data->data; | 
|---|
| 2831 | if(nlanfnt == cnt) | 
|---|
| 2832 | isswapped = 0; | 
|---|
| 2833 | else if(nlanfnt == BYTESWAP_WORD(cnt)) | 
|---|
| 2834 | isswapped = 1; | 
|---|
| 2835 | else | 
|---|
| 2836 | error("FONTDIR for language %d,%d has wrong count (%d, expected %d)", | 
|---|
| 2837 | fnd[i]->lan->id, fnd[i]->lan->sub, cnt, nlanfnt); | 
|---|
| 2838 | #ifdef WORDS_BIGENDIAN | 
|---|
| 2839 | if((byteorder == WRC_BO_LITTLE && !isswapped) || (byteorder != WRC_BO_LITTLE && isswapped)) | 
|---|
| 2840 | #else | 
|---|
| 2841 | if((byteorder == WRC_BO_BIG && !isswapped) || (byteorder != WRC_BO_BIG && isswapped)) | 
|---|
| 2842 | #endif | 
|---|
| 2843 | { | 
|---|
| 2844 | internal_error(__FILE__, __LINE__, "User supplied FONTDIR needs byteswapping"); | 
|---|
| 2845 | } | 
|---|
| 2846 | } | 
|---|
| 2847 |  | 
|---|
| 2848 | /* We now have fonts left where we need to make a fontdir resource */ | 
|---|
| 2849 | for(i = fntleft = 0; i < nfnt; i++) | 
|---|
| 2850 | { | 
|---|
| 2851 | if(fnt[i]) | 
|---|
| 2852 | fntleft++; | 
|---|
| 2853 | } | 
|---|
| 2854 | while(fntleft) | 
|---|
| 2855 | { | 
|---|
| 2856 | /* Get fonts of same language in lanfnt[] */ | 
|---|
| 2857 | for(i = nlanfnt = 0; i < nfnt; i++) | 
|---|
| 2858 | { | 
|---|
| 2859 | if(fnt[i]) | 
|---|
| 2860 | { | 
|---|
| 2861 | if(!nlanfnt) | 
|---|
| 2862 | { | 
|---|
| 2863 | addlanfnt: | 
|---|
| 2864 | lanfnt[nlanfnt] = fnt[i]; | 
|---|
| 2865 | nlanfnt++; | 
|---|
| 2866 | fnt[i] = NULL; | 
|---|
| 2867 | fntleft--; | 
|---|
| 2868 | } | 
|---|
| 2869 | else if(fnt[i]->lan->id == lanfnt[0]->lan->id && fnt[i]->lan->sub == lanfnt[0]->lan->sub) | 
|---|
| 2870 | goto addlanfnt; | 
|---|
| 2871 | } | 
|---|
| 2872 | } | 
|---|
| 2873 | /* and build a fontdir */ | 
|---|
| 2874 | rsc = build_fontdir(lanfnt, nlanfnt); | 
|---|
| 2875 | if(rsc) | 
|---|
| 2876 | { | 
|---|
| 2877 | if(lst) | 
|---|
| 2878 | { | 
|---|
| 2879 | lst->next = rsc; | 
|---|
| 2880 | rsc->prev = lst; | 
|---|
| 2881 | } | 
|---|
| 2882 | lst = rsc; | 
|---|
| 2883 | } | 
|---|
| 2884 | } | 
|---|
| 2885 |  | 
|---|
| 2886 | free(lanfnt); | 
|---|
| 2887 | clean: | 
|---|
| 2888 | if(fnt) | 
|---|
| 2889 | free(fnt); | 
|---|
| 2890 | if(fnd) | 
|---|
| 2891 | free(fnd); | 
|---|
| 2892 | return lst; | 
|---|
| 2893 | } | 
|---|
| 2894 |  | 
|---|
| 2895 | /* | 
|---|
| 2896 | * This gets invoked to determine whether the next resource | 
|---|
| 2897 | * is to be of a standard-type (e.g. bitmaps etc.), or should | 
|---|
| 2898 | * be a user-type resource. This function is required because | 
|---|
| 2899 | * there is the _possibility_ of a lookahead token in the | 
|---|
| 2900 | * parser, which is generated from the "expr" state in the | 
|---|
| 2901 | * "nameid" parsing. | 
|---|
| 2902 | * | 
|---|
| 2903 | * The general resource format is: | 
|---|
| 2904 | * <identifier> <type> <flags> <resourcebody> | 
|---|
| 2905 | * | 
|---|
| 2906 | * The <identifier> can either be tIDENT or "expr". The latter | 
|---|
| 2907 | * will always generate a lookahead, which is the <type> of the | 
|---|
| 2908 | * resource to parse. Otherwise, we need to get a new token from | 
|---|
| 2909 | * the scanner to determine the next step. | 
|---|
| 2910 | * | 
|---|
| 2911 | * The problem arrises when <type> is numerical. This case should | 
|---|
| 2912 | * map onto default resource-types and be parsed as such instead | 
|---|
| 2913 | * of being mapped onto user-type resources. | 
|---|
| 2914 | * | 
|---|
| 2915 | * The trick lies in the fact that yacc (bison) doesn't care about | 
|---|
| 2916 | * intermediate changes of the lookahead while reducing a rule. We | 
|---|
| 2917 | * simply replace the lookahead with a token that will result in | 
|---|
| 2918 | * a shift to the appropriate rule for the specific resource-type. | 
|---|
| 2919 | */ | 
|---|
| 2920 | static int rsrcid_to_token(int lookahead) | 
|---|
| 2921 | { | 
|---|
| 2922 | int token; | 
|---|
| 2923 | char *type = "?"; | 
|---|
| 2924 |  | 
|---|
| 2925 | /* Get a token if we don't have one yet */ | 
|---|
| 2926 | if(lookahead == YYEMPTY) | 
|---|
| 2927 | lookahead = YYLEX; | 
|---|
| 2928 |  | 
|---|
| 2929 | /* Only numbers are possibly interesting */ | 
|---|
| 2930 | switch(lookahead) | 
|---|
| 2931 | { | 
|---|
| 2932 | case tNUMBER: | 
|---|
| 2933 | case tLNUMBER: | 
|---|
| 2934 | break; | 
|---|
| 2935 | default: | 
|---|
| 2936 | return lookahead; | 
|---|
| 2937 | } | 
|---|
| 2938 |  | 
|---|
| 2939 | token = lookahead; | 
|---|
| 2940 |  | 
|---|
| 2941 | switch(yylval.num) | 
|---|
| 2942 | { | 
|---|
| 2943 | case WRC_RT_CURSOR: | 
|---|
| 2944 | type = "CURSOR"; | 
|---|
| 2945 | token = tCURSOR; | 
|---|
| 2946 | break; | 
|---|
| 2947 | case WRC_RT_ICON: | 
|---|
| 2948 | type = "ICON"; | 
|---|
| 2949 | token = tICON; | 
|---|
| 2950 | break; | 
|---|
| 2951 | case WRC_RT_BITMAP: | 
|---|
| 2952 | type = "BITMAP"; | 
|---|
| 2953 | token = tBITMAP; | 
|---|
| 2954 | break; | 
|---|
| 2955 | case WRC_RT_FONT: | 
|---|
| 2956 | type = "FONT"; | 
|---|
| 2957 | token = tFONT; | 
|---|
| 2958 | break; | 
|---|
| 2959 | case WRC_RT_FONTDIR: | 
|---|
| 2960 | type = "FONTDIR"; | 
|---|
| 2961 | token = tFONTDIR; | 
|---|
| 2962 | break; | 
|---|
| 2963 | case WRC_RT_RCDATA: | 
|---|
| 2964 | type = "RCDATA"; | 
|---|
| 2965 | token = tRCDATA; | 
|---|
| 2966 | break; | 
|---|
| 2967 | case WRC_RT_MESSAGETABLE: | 
|---|
| 2968 | type = "MESSAGETABLE"; | 
|---|
| 2969 | token = tMESSAGETABLE; | 
|---|
| 2970 | break; | 
|---|
| 2971 | case WRC_RT_DLGINIT: | 
|---|
| 2972 | type = "DLGINIT"; | 
|---|
| 2973 | token = tDLGINIT; | 
|---|
| 2974 | break; | 
|---|
| 2975 | case WRC_RT_ACCELERATOR: | 
|---|
| 2976 | type = "ACCELERATOR"; | 
|---|
| 2977 | token = tACCELERATORS; | 
|---|
| 2978 | break; | 
|---|
| 2979 | case WRC_RT_MENU: | 
|---|
| 2980 | type = "MENU"; | 
|---|
| 2981 | token = tMENU; | 
|---|
| 2982 | break; | 
|---|
| 2983 | case WRC_RT_DIALOG: | 
|---|
| 2984 | type = "DIALOG"; | 
|---|
| 2985 | token = tDIALOG; | 
|---|
| 2986 | break; | 
|---|
| 2987 | case WRC_RT_VERSION: | 
|---|
| 2988 | type = "VERSION"; | 
|---|
| 2989 | token = tVERSIONINFO; | 
|---|
| 2990 | break; | 
|---|
| 2991 | case WRC_RT_TOOLBAR: | 
|---|
| 2992 | type = "TOOLBAR"; | 
|---|
| 2993 | token = tTOOLBAR; | 
|---|
| 2994 | break; | 
|---|
| 2995 |  | 
|---|
| 2996 | case WRC_RT_STRING: | 
|---|
| 2997 | type = "STRINGTABLE"; | 
|---|
| 2998 | break; | 
|---|
| 2999 |  | 
|---|
| 3000 | case WRC_RT_ANICURSOR: | 
|---|
| 3001 | case WRC_RT_ANIICON: | 
|---|
| 3002 | case WRC_RT_GROUP_CURSOR: | 
|---|
| 3003 | case WRC_RT_GROUP_ICON: | 
|---|
| 3004 | yywarning("Usertype uses reserved type-ID %d, which is auto-generated", yylval.num); | 
|---|
| 3005 | return lookahead; | 
|---|
| 3006 |  | 
|---|
| 3007 | case WRC_RT_DLGINCLUDE: | 
|---|
| 3008 | case WRC_RT_PLUGPLAY: | 
|---|
| 3009 | case WRC_RT_VXD: | 
|---|
| 3010 | case WRC_RT_HTML: | 
|---|
| 3011 | yywarning("Usertype uses reserved type-ID %d, which is not supported by wrc", yylval.num); | 
|---|
| 3012 | default: | 
|---|
| 3013 | return lookahead; | 
|---|
| 3014 | } | 
|---|
| 3015 |  | 
|---|
| 3016 | if(remap) | 
|---|
| 3017 | return token; | 
|---|
| 3018 | else | 
|---|
| 3019 | yywarning("Usertype uses reserved type-ID %d, which is used by %s", yylval.num, type); | 
|---|
| 3020 | return lookahead; | 
|---|
| 3021 | } | 
|---|
| 3022 |  | 
|---|