5 * Resource compiler lexical analyser
7 * Portable Windows Library
9 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
11 * The contents of this file are subject to the Mozilla Public License
12 * Version 1.0 (the "License"); you may not use this file except in
13 * compliance with the License. You may obtain a copy of the License at
14 * http://www.mozilla.org/MPL/
16 * Software distributed under the License is distributed on an "AS IS"
17 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
18 * the License for the specific language governing rights and limitations
21 * The Original Code is Portable Windows Library.
23 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
25 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
26 * All Rights Reserved.
28 * Contributor(s): ______________________________________.
31 * Revision 1.28 2002/12/02 02:40:05 robertj
32 * Changed due to compiler compatibility.
34 * Revision 1.27 2002/11/25 22:44:24 robertj
35 * Fixed MSVC v5 compatibility
37 * Revision 1.26 2002/04/26 05:38:09 robertj
38 * Removed assumption that GetAt() on a dictionary will automatically convert
39 * the index to a POrdinalyKey. This breaks the PCollection semantics for
40 * GetAt() which is to get based on the ordinal position not the hashed position.
42 * Revision 1.25 2001/02/22 06:26:42 robertj
43 * Fixed warning from flex.
45 * Revision 1.24 1999/10/29 11:44:25 robertj
46 * Fixed #ifdef conditional around the wrong way.
48 * Revision 1.24 1999/10/29 11:44:25 robertj
49 * Fixed #ifdef conditional around the wrong way.
51 * Revision 1.23 1999/10/19 07:08:23 robertj
52 * Added #ifdef/#ifndef condition compile functionality
54 * Revision 1.22 1999/02/06 08:45:33 robertj
57 * Revision 1.21 1998/09/26 01:24:15 robertj
58 * Added open source license
60 * Revision 1.20 1998/09/26 00:40:27 robertj
61 * Fixed linkage mismatch of lex function.
63 * Revision 1.19 1998/09/14 13:48:05 robertj
64 * Allowed suppression of some warnings.
66 * Revision 1.18 1997/12/12 08:44:25 robertj
67 * Update to currect version of PWLIB
69 * Revision 1.17 1996/01/23 13:32:45 robertj
70 * More changes for editor
72 * Revision 1.16 1995/12/23 03:53:39 robertj
73 * Added extra collections for editor use.
75 * Revision 1.15 1995/12/10 12:12:05 robertj
76 * Changes to support graphical resource file editor.
78 * Revision 1.14 1995/08/24 12:48:13 robertj
79 * Added general control type for arbitrary dialog controls.
81 * Revision 1.13 1995/07/31 12:30:13 robertj
82 * Changed all generated resource IDs to be in the same "number space". This
83 * is to avoid problems with IDs being used for more than one type of resource
84 * eg a menu item and an image for a toolbar.
85 * Fixed the generated #line commands to include a relative path instead of an
88 * Revision 1.12 1995/01/27 11:25:43 robertj
89 * Added pattern resource.
91 * Revision 1.11 1994/12/12 13:14:04 robertj
92 * Changed RealEdit to FloatEdit.
94 * Revision 1.10 1994/12/05 11:38:01 robertj
95 * Added #line to generated code.
97 * Revision 1.9 1994/10/23 06:07:12 robertj
98 * Shortened OS error assert.
100 * Revision 1.8 1994/07/02 03:28:52 robertj
101 * Fixed accidentaly removed header keyword.
102 * Fixed comment parsing problem.
104 * Revision 1.6 1994/04/20 12:47:01 robertj
105 * *** empty log message ***
107 * Revision 1.5 1994/04/01 14:29:16 robertj
108 * New format PRC file
110 * Revision 1.4 1993/08/20 21:31:56 robertj
111 * Included ctype for unix compatibility.
113 * Revision 1.3 1993/07/16 12:48:13 robertj
114 * Added slash star style comments.
115 * General formatting.
117 * Revision 1.2 1993/07/15 04:38:31 robertj
118 * Rationalised lex.h, parse.h and main.h out of existance.
119 * Fixed literal string so can have embedded \" characters.
121 * Revision 1.1 1993/07/03 06:01:44 robertj
124 * Revision 1.2 1993/06/24 19:48:57 craigs
125 * Added support for hash comments
127 * Revision 1.1 1993/06/24 19:23:17 craigs
134 #include "pr_gramm.h"
140 extern int yyparse();
142 extern ResourceFile * current_file;
143 extern ostream * inline_src;
144 extern ostream * inline_hdr;
147 ///////////////////////////////////////////
149 // handling for "include" files
152 PDECLARE_CLASS(LexState, PObject)
154 LexState(const PFilePath & fn)
155 : filename(fn) { line_number = 1; }
157 Comparison Compare(const PObject & obj) const
158 { return filename.Compare(((const LexState &)obj).filename); }
160 YY_BUFFER_STATE yy_state;
161 unsigned line_number;
166 PSTACK(LexStack, LexState);
168 static LexStack LexFile;
170 static int in_define;
171 static int in_multiline_comment;
173 PStringArray IncludePath;
176 ResourceFile::ResourceFile(PFile & prcfile, BOOL suppress,
177 const PString & predefinedSymbols)
179 nextResourceId = 10000;
180 fatals = warnings = 0;
181 suppressInfoWarnings = suppress;
183 PStringArray symbols = predefinedSymbols.Lines();
184 for (PINDEX i = 0; i < symbols.GetSize(); i++)
185 defineDict.SetAt(symbols[i], new DefineValue(1, FALSE));
187 inline_src = &src_inline;
188 inline_hdr = &hdr_inline;
190 for (PINDEX type = 0; type < ResourceList::NumResTypes; type++) {
191 resources[type].type = (ResourceList::ResTypes)type;
192 resources[type].DisallowDeleteObjects();
195 resourceDict[ResourceList::StringRes] = &stringDict;
196 resourceDict[ResourceList::MenubarRes] = &menubarDict;
197 resourceDict[ResourceList::LayoutRes] = &dialogDict;
198 resourceDict[ResourceList::IconRes] = &iconDict;
199 resourceDict[ResourceList::CursorRes] = &cursorDict;
200 resourceDict[ResourceList::PatternRes] = &patternDict;
201 resourceDict[ResourceList::ImageRes] = &imageDict;
202 resourceDict[ResourceList::DataRes] = &dataDict;
207 LexFile.Push(new LexState(prcfile.GetFilePath()));
209 yyin = _fdopen(prcfile.GetHandle(), "r");
215 ostream & operator<<(ostream & out, const StdError & e)
217 if (e.e == Info && current_file->suppressInfoWarnings) {
218 static PStringStream dummy;
223 out << e.l.filename << '(' << e.l.number << ") : ";
225 current_file->fatals++;
229 current_file->warnings++;
236 void LineNumber::Set()
238 if (LexFile.IsEmpty()) {
243 filename = LexFile.Top().filename;
244 number = LexFile.Top().line_number;
249 extern "C" int yywrap()
257 %option never-interactive
259 %x hash_include hash_inline_src hash_inline_hdr comment_lines conditional_compilation
264 [Dd][Ee][Ff][Pp][Uu][Ss][Hh][Bb][Uu][Tt][Tt][Oo][Nn] { return DEFPUSHBUTTON; }
266 [Aa][Cc][Cc][Ee][Ll][Ee][Rr][Aa][Tt][Oo][Rr][Ss] { return ACCELERATORS; }
268 [Pp][Aa][Ss][Ss][Ww][Oo][Rr][Dd][Bb][Oo][Xx] { return PASSWORDBOX; }
270 [Mm][Oo][Dd][Aa][Ll][Dd][Ii][Aa][Ll][Oo][Gg] { return MODALDIALOG; }
272 [Rr][Aa][Dd][Ii][Oo][Bb][Uu][Tt][Tt][Oo][Nn] { return RADIOBUTTON; }
274 [Mm][Uu][Ll][Tt][Ii][Ss][Ee][Ll][Ee][Cc][Tt] { return MULTISELECT; }
276 [Mm][Uu][Ll][Tt][Ii][Cc][Oo][Ll][Uu][Mm][Nn] { return MULTICOLUMN; }
278 [Ss][Tt][Rr][Ii][Nn][Gg][Ll][Ii][Ss][Tt] { return STRINGLIST; }
280 [Pp][Uu][Ss][Hh][Bb][Uu][Tt][Tt][Oo][Nn] { return PUSHBUTTON; }
282 [Ss][Tt][Aa][Tt][Ii][Cc][Ii][Cc][Oo][Nn] { return STATICICON; }
284 [Cc][Ee][Nn][Tt][Rr][Ee][Tt][Ee][Xx][Tt] { return CENTRETEXT; }
285 [Cc][Ee][Nn][Tt][Ee][Rr][Tt][Ee][Xx][Tt] { return CENTRETEXT; }
287 [Hh][Ss][Cc][Rr][Oo][Ll][Ll][Bb][Aa][Rr] { return HSCROLLBAR; }
289 [Vv][Ss][Cc][Rr][Oo][Ll][Ll][Bb][Aa][Rr] { return VSCROLLBAR; }
291 [Tt][Ee][Xx][Tt][Ee][Dd][Ii][Tt][Oo][Rr] { return TEXTEDITOR; }
293 [Dd][Ii][Mm][Ee][Nn][Ss][Ii][Oo][Nn][Ss] { return DIMENSIONS; }
294 [Dd][Ii][Mm] { return DIMENSIONS; }
296 [Rr][Ii][Gg][Hh][Tt][Tt][Ee][Xx][Tt] { return RIGHTTEXT; }
298 [Ss][Tt][Aa][Tt][Ii][Cc][Bb][Oo][Xx] { return STATICBOX; }
300 [Ss][Ee][Pp][Aa][Rr][Aa][Tt][Oo][Rr] { return SEPARATOR; }
302 [Cc][Hh][Oo][Ii][Cc][Ee][Bb][Oo][Xx] { return CHOICEBOX; }
304 [Ff][Ll][Oo][Aa][Tt][Ee][Dd][Ii][Tt] { return FLOATEDIT; }
306 [Cc][Hh][Ee][Cc][Kk]3[Ww][Aa][Yy] { return CHECK3WAY; }
308 [Cc][Hh][Ee][Cc][Kk][Bb][Oo][Xx] { return CHECKBOX; }
310 [Ll][Ee][Ff][Tt][Tt][Ee][Xx][Tt] { return LEFTTEXT; }
312 [Pp][Oo][Ss][Ii][Tt][Ii][Oo][Nn] { return POSITION; }
313 [Pp][Oo][Ss] { return POSITION; }
315 [Cc][Oo][Mm][Bb][Oo][Bb][Oo][Xx] { return COMBOBOX; }
317 [Rr][Ee][Ss][Oo][Uu][Rr][Cc][Ee] { return RESOURCE; }
319 [Oo][Pp][Tt][Ii][Oo][Nn][Ss] { return OPTIONS; }
321 [Ee][Dd][Ii][Tt][Bb][Oo][Xx] { return EDITBOX; }
323 [Ii][Nn][Tt][Ee][Dd][Ii][Tt] { return INTEDIT; }
325 [Ll][Ii][Ss][Tt][Bb][Oo][Xx] { return LISTBOX; }
327 [Mm][Ee][Nn][Uu][Bb][Aa][Rr] { return MENUBAR; }
329 [Pp][Aa][Tt][Tt][Ee][Rr][Nn] { return PATTERN_token; }
331 [Hh][Oo][Tt][Ss][Pp][Oo][Tt] { return HOTSPOT; }
333 [Aa][Nn][Dd][Mm][Aa][Ss][Kk] { return ANDMASK; }
335 [Xx][Oo][Rr][Mm][Aa][Ss][Kk] { return XORMASK; }
338 [Cc][Oo][Ll][Oo][Uu][Rr][Ss] { return COLOURS; }
339 [Cc][Oo][Ll][Oo][Rr][Ss] { return COLOURS; }
341 [Dd][Ee][Ff][Aa][Uu][Ll][Tt] { return DEFAULT; }
343 [Cc][Oo][Nn][Tt][Rr][Oo][Ll] { return CONTROL; }
345 [Hh][Ee][Aa][Dd][Ee][Rr] { return HEADER; }
347 [Ww][Ii][Nn][Dd][Oo][Ww] { return WINDOW; }
349 [Nn][Oo][Tt][Ii][Ff][Yy] { return NOTIFY; }
351 [Ll][Aa][Yy][Oo][Uu][Tt] { return LAYOUT; }
353 [Ss][Tt][Rr][Ii][Nn][Gg] { return STRING; }
355 [Dd][Ii][Aa][Ll][Oo][Gg] { return DIALOG; }
357 [Ss][Oo][Rr][Tt][Ee][Dd] { return SORTED; }
359 [Cc][Uu][Rr][Ss][Oo][Rr] { return CURSOR; }
361 [Pp][Ii][Xx][Ee][Ll][Ss] { return PIXELS; }
363 [Cc][Aa][Nn][Cc][Ee][Ll] { return CANCEL; }
365 [Ll][Ii][Mm][Ii][Tt][Ss] { return LIMITS; }
367 [Tt][Ii][Tt][Ll][Ee] { return TITLE; }
369 [Ii][Mm][Aa][Gg][Ee] { return IMAGE; }
371 [Bb][Ee][Gg][Ii][Nn] { return BEGIN_token; }
373 [Vv][Aa][Ll][Uu][Ee] { return VALUE; }
375 [Cc][Ll][Aa][Ss][Ss] { return CLASS; }
377 [Ff][Ii][Ee][Ll][Dd] { return FIELD; }
379 [Ff][Oo][Nn][Tt] { return FONT; }
381 [Mm][Ee][Nn][Uu] { return MENU; }
383 [Ii][Cc][Oo][Nn] { return ICON; }
385 [Ii][Tt][Ee][Mm] { return ITEM; }
387 [Hh][Ee][Ll][Pp] { return HELP; }
389 [Ee][Nn][Dd] { return END; }
391 [Ii][Dd] { return ID; }
393 [Oo][Kk] { return OK; }
396 ^"#inline"[ \t]+"src".* {
397 BEGIN(hash_inline_src);
398 *inline_src << LineNumber();
401 <hash_inline_src>^"#inline"[ \t]+"end".* { BEGIN(0); }
403 <hash_inline_src>^[^\n]* { *inline_src << yytext; }
405 <hash_inline_src>\n {
406 LexFile.Top().line_number++;
411 ^"#inline"[ \t]+"hdr".* {
412 BEGIN(hash_inline_hdr);
413 *inline_hdr << LineNumber();
416 <hash_inline_hdr>^"#inline"[ \t]+"end".* { BEGIN(0); }
418 <hash_inline_hdr>^[^\n]* { *inline_hdr << yytext; }
420 <hash_inline_hdr>\n {
421 LexFile.Top().line_number++;
426 ^\#include { BEGIN(hash_include); }
428 <hash_include>[ \t] { }
430 <hash_include>[^ \t\n]* {
431 PString text(yytext);
432 PINDEX end = P_MAX_INDEX;
433 PINDEX start = text.FindOneOf("\"<");
434 if (start != P_MAX_INDEX)
435 end = text.Find(text[start] == '"' ? '"' : '>', start+1);
436 if (start == P_MAX_INDEX || end == P_MAX_INDEX)
437 PError << StdError(Warning) << "badly formed include.\n";
439 PString fname = text(start+1, end-1);
442 if (text[start] == '"')
443 file = fopen(fname, "r");
445 for (PINDEX i = 0; file == NULL && i < IncludePath.GetSize(); i++) {
446 if (PDirectory::Change(IncludePath[i]))
447 file = fopen(fname, "r");
449 PError << StdError(Warning) << "invalid path \""
450 << IncludePath[i] << "\".\n";
452 PAssertOS(LexFile.Top().dir.Change());
456 PError << StdError(Warning)
457 << "include file " << fname << " not found.\n";
459 LexFile.Top().yy_state = YY_CURRENT_BUFFER;
460 LexFile.Push(new LexState(fname));
462 yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE));
469 delete LexFile.Pop();
470 if (LexFile.IsEmpty())
473 yy_switch_to_buffer(LexFile.Top().yy_state);
474 PAssertOS(LexFile.Top().dir.Change());
485 ^\#ifdef[ \t]+[^ \t\n]* {
486 PString text(yytext);
487 if (!current_file->IsNameDefined(text.Mid(text.Find(' ')).Trim()))
488 BEGIN(conditional_compilation);
491 ^\#ifndef[ \t]+[^ \t\n]* {
492 PString text(yytext);
493 if (current_file->IsNameDefined(text.Mid(text.Find(' ')).Trim()))
494 BEGIN(conditional_compilation);
497 <conditional_compilation>^\#endif.*\n {
501 <conditional_compilation>\n {
502 LexFile.Top().line_number++;
505 <conditional_compilation>. { }
512 in_multiline_comment = FALSE;
513 BEGIN(comment_lines);
517 in_multiline_comment = TRUE;
518 BEGIN(comment_lines);
521 <comment_lines>"*/" {
522 if (in_multiline_comment)
527 LexFile.Top().line_number++;
528 if (!in_multiline_comment)
561 \"([^\"\n]|(\\\"))*\" {
562 yylval.sval = new PString(yytext);
566 "0x"[0-9a-fA-F][0-9a-fA-F]* {
567 yylval.ival = strtol(yytext+2, NULL, 16);
572 yylval.ival = strtol(yytext, NULL, 8);
577 yylval.ival = strtol(yytext, NULL, 10);
581 [a-zA-Z_][a-zA-Z0-9_]* {
582 PString name = yytext;
584 !current_file->defineDict.Contains(name) ||
585 !current_file->defineDict[name].IsString()) {
586 yylval.sval = new PString(name);
590 yylval.sval = new PString(current_file->defineDict[name].AsString());
598 LexFile.Top().line_number++;
605 . { PError << StdError(Warning) << "unknown token " << yytext << endl; }