xref: /haiku/src/bin/rc/parser.y (revision 239222b2369c39dc52df52b0a7cdd6cc0a91bc92)
1 /*
2  * Copyright (c) 2003 Matthijs Hollemans
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 %{
24 
25 #include <Message.h>
26 
27 #include <map>
28 #include <string.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 
32 #include "rdef.h"
33 #include "compile.h"
34 #include "private.h"
35 
36 using namespace std;
37 
38 #define YYERROR_VERBOSE
39 
40 static void yyerror(const char*);
41 
42 struct ident_compare_t {  // allows the maps to compare identifier names
43 	bool
44 	operator()(const char* s1, const char* s2) const
45 	{
46 		return strcmp(s1, s2) < 0;
47 	}
48 };
49 
50 typedef std::map<const char*, int32, ident_compare_t> sym_tab_t;
51 typedef sym_tab_t::iterator sym_iter_t;
52 
53 typedef std::map<const char*, type_t, ident_compare_t> type_tab_t;
54 typedef type_tab_t::iterator type_iter_t;
55 
56 typedef std::map<const char*, define_t, ident_compare_t> define_tab_t;
57 typedef define_tab_t::iterator define_iter_t;
58 
59 
60 static sym_tab_t symbol_table;  // symbol table for enums
61 static int32 enum_cnt;          // counter for enum symbols without id
62 static type_tab_t type_table;  // symbol table for data types
63 static define_tab_t define_table;  // symbol table for defines
64 
65 
66 static void add_user_type(res_id_t, type_code, const char*, list_t);
67 static void add_symbol(const char*, int32);
68 static int32 get_symbol(const char*);
69 
70 static bool is_type(const char* name);
71 static define_t get_define(const char* name);
72 
73 static data_t make_data(size_t, type_t);
74 static data_t make_bool(bool);
75 static data_t make_int(uint64);
76 static data_t make_float(double);
77 
78 static data_t import_data(char*);
79 static data_t resize_data(data_t, size_t);
80 
81 static BMessage* make_msg(list_t);
82 static data_t flatten_msg(BMessage*);
83 
84 static data_t make_default(type_t);
85 static data_t make_type(char* name, list_t);
86 
87 static list_t make_field_list(field_t);
88 static list_t concat_field_list(list_t, field_t);
89 static list_t make_data_list(data_t);
90 static list_t concat_data_list(list_t, data_t);
91 static data_t concat_data(data_t, data_t);
92 
93 static data_t cast(type_t, data_t);
94 
95 static data_t unary_expr(data_t, char);
96 static data_t binary_expr(data_t, data_t, char);
97 
98 static void add_resource(res_id_t, type_code, data_t);
99 
100 
101 //------------------------------------------------------------------------------
102 %}
103 
104 %expect 15
105 
106 %union {
107 	bool b;
108 	uint64 i;
109 	double f;
110 	char* I;
111 	type_code t;
112 	res_id_t id;
113 	data_t d;
114 	list_t l;
115 	field_t F;
116 	type_t T;
117 }
118 
119 %token ENUM RESOURCE ARCHIVE ARRAY MESSAGE RTYPE IMPORT
120 
121 %token <b> BOOL
122 %token <i> INTEGER
123 %token <f> FLOAT
124 %token <d> STRING RAW
125 %token <I> IDENT
126 %token <t> TYPECODE
127 
128 %type <i> integer
129 %type <f> float
130 %type <id> id
131 %type <d> archive array arrayfields data expr message msgfield
132 %type <d> type typefield type_or_define
133 %type <l> msgfields typefields typedeffields
134 %type <F> typedeffield
135 %type <T> datatype typecast
136 
137 %left '|'
138 %left '^'
139 %left '&'
140 %left '+' '-'
141 %left '*' '/' '%'
142 %right FLIP
143 
144 %%
145 
146 script
147 	: /* empty */
148 	| script enum
149 	| script typedef
150 	| script resource
151 	;
152 
153 enum
154 	: enumstart '{' '}' ';'
155 	| enumstart '{' symbols '}' ';'
156 	| enumstart '{' symbols ',' '}' ';'
157 	;
158 
159 enumstart
160 	: ENUM { enum_cnt = 0; }
161 	;
162 
163 symbols
164 	: symbols ',' symboldef
165 	| symboldef
166 	;
167 
168 symboldef
169 	: IDENT
170 		{
171 			add_symbol($1, enum_cnt);
172 			++enum_cnt;
173 		}
174 	| IDENT '=' integer
175 		{
176 			int32 id = (int32) $3;
177 			add_symbol($1, id);
178 			enum_cnt = id + 1;
179 		}
180 	;
181 
182 typedef
183 	: RTYPE id TYPECODE IDENT '{' typedeffields '}' ';'
184 		{
185 			add_user_type($2, $3, $4, $6);
186 		}
187 	| RTYPE id IDENT '{' typedeffields '}' ';'
188 		{
189 			add_user_type($2, B_RAW_TYPE, $3, $5);
190 		}
191 	;
192 
193 typedeffields
194 	: typedeffields ',' typedeffield { $$ = concat_field_list($1, $3); }
195 	| typedeffield                   { $$ = make_field_list($1); }
196 	;
197 
198 typedeffield
199 	: datatype IDENT
200 		{
201 			$$.type   = $1;
202 			$$.name   = $2;
203 			$$.resize = 0;
204 			$$.data   = make_default($1);
205 		}
206 	| datatype IDENT '=' expr
207 		{
208 			$$.type   = $1;
209 			$$.name   = $2;
210 			$$.resize = 0;
211 			$$.data   = cast($1, $4);
212 		}
213 	| datatype IDENT '[' INTEGER ']'
214 		{
215 			$$.type   = $1;
216 			$$.name   = $2;
217 			$$.resize = (size_t) $4;
218 			$$.data   = resize_data(make_default($1), $$.resize);
219 		}
220 	| datatype IDENT '[' INTEGER ']' '=' expr
221 		{
222 			$$.type   = $1;
223 			$$.name   = $2;
224 			$$.resize = (size_t) $4;
225 			$$.data   = resize_data(cast($1, $7), $$.resize);
226 		}
227 	;
228 
229 resource
230 	: RESOURCE id expr ';'
231 		{
232 			add_resource($2, $3.type.code, $3);
233 		}
234 	| RESOURCE id TYPECODE expr ';'
235 		{
236 			add_resource($2, $3, $4);
237 		}
238 	| RESOURCE id '(' TYPECODE ')' expr ';'
239 		{
240 			add_resource($2, $4, $6);
241 		}
242 	;
243 
244 id
245 	: /* empty */
246 		{
247 			$$.has_id = false; $$.has_name = false; $$.name = NULL;
248 		}
249 	| '(' ')'
250 		{
251 			$$.has_id = false; $$.has_name = false; $$.name = NULL;
252 		}
253 	| '(' integer ')'
254 		{
255 			$$.has_id = true; $$.id = (int32) $2;
256 			$$.has_name = false; $$.name = NULL;
257 		}
258 	| '(' integer ',' STRING ')'
259 		{
260 			$$.has_id = true; $$.id = (int32) $2;
261 			$$.has_name = true; $$.name = (char*) $4.ptr;
262 		}
263 	| '(' IDENT ')'
264 		{
265 			$$.has_id = true; $$.id = get_symbol($2);
266 
267 			if (flags & RDEF_AUTO_NAMES)
268 			{
269 				$$.has_name = true; $$.name = $2;
270 			}
271 			else
272 			{
273 				$$.has_name = false; $$.name = NULL;
274 				free_mem($2);
275 			}
276 		}
277 	| '(' IDENT ',' STRING ')'
278 		{
279 			$$.has_id = true; $$.id = get_symbol($2);
280 			$$.has_name = true; $$.name = (char*) $4.ptr;
281 			free_mem($2);
282 		}
283 	| '(' STRING ')'
284 		{
285 			$$.has_id = false;
286 			$$.has_name = true; $$.name = (char*) $2.ptr;
287 		}
288 	;
289 
290 array
291 	: ARRAY '{' arrayfields '}' { $$ = $3; }
292 	| ARRAY '{' '}'             { $$ = make_data(0, get_type("raw")); }
293 	| ARRAY                     { $$ = make_data(0, get_type("raw")); }
294 	| ARRAY IMPORT STRING       { $$ = import_data((char*) $3.ptr); }
295 	| IMPORT STRING             { $$ = import_data((char*) $2.ptr); }
296 	;
297 
298 arrayfields
299 	: arrayfields ',' expr { $$ = concat_data($1, $3); }
300 	| expr                 { $$ = $1; $$.type = get_type("raw"); }
301 	;
302 
303 message
304 	: MESSAGE '(' integer ')' '{' msgfields '}'
305 		{
306 			BMessage* msg = make_msg($6);
307 			msg->what = (int32) $3;
308 			$$ = flatten_msg(msg);
309 		}
310 	| MESSAGE '(' integer ')' '{' '}'
311 		{
312 			BMessage* msg = new BMessage;
313 			msg->what = (int32) $3;
314 			$$ = flatten_msg(msg);
315 		}
316 	| MESSAGE '(' integer ')'
317 		{
318 			BMessage* msg = new BMessage;
319 			msg->what = (int32) $3;
320 			$$ = flatten_msg(msg);
321 		}
322 	| MESSAGE '{' msgfields '}' { $$ = flatten_msg(make_msg($3)); }
323 	| MESSAGE '{' '}'           { $$ = flatten_msg(new BMessage); }
324 	| MESSAGE                   { $$ = flatten_msg(new BMessage); }
325 	;
326 
327 msgfields
328 	: msgfields ',' msgfield { $$ = concat_data_list($1, $3); }
329 	| msgfield               { $$ = make_data_list($1); }
330 	;
331 
332 msgfield
333 	: STRING '=' expr
334 		{
335 			$$ = $3;
336 			$$.name = (char*) $1.ptr;
337 		}
338 	| datatype STRING '=' expr
339 		{
340 			$$ = cast($1, $4);
341 			$$.name = (char*) $2.ptr;
342 		}
343 	| TYPECODE STRING '=' expr
344 		{
345 			$$ = $4;
346 			$$.type.code = $1;
347 			$$.name = (char*) $2.ptr;
348 		}
349 	| TYPECODE datatype STRING '=' expr
350 		{
351 			$$ = cast($2, $5);
352 			$$.type.code = $1;
353 			$$.name = (char*) $3.ptr;
354 		}
355 	;
356 
357 archive
358 	: ARCHIVE IDENT '{' msgfields '}'
359 		{
360 			BMessage* msg = make_msg($4);
361 			msg->AddString("class", $2);
362 			free_mem($2);
363 			$$ = flatten_msg(msg);
364 		}
365 	| ARCHIVE '(' STRING ')' IDENT '{' msgfields '}'
366 		{
367 			BMessage* msg = make_msg($7);
368 			msg->AddString("class", $5);
369 			msg->AddString("add_on", (char*) $3.ptr);
370 			free_mem($5);
371 			free_mem($3.ptr);
372 			$$ = flatten_msg(msg);
373 		}
374 	| ARCHIVE '(' ',' integer ')' IDENT '{' msgfields '}'
375 		{
376 			BMessage* msg = make_msg($8);
377 			msg->what = (int32) $4;
378 			msg->AddString("class", $6);
379 			free_mem($6);
380 			$$ = flatten_msg(msg);
381 		}
382 	| ARCHIVE '(' STRING ',' integer ')' IDENT '{' msgfields '}'
383 		{
384 			BMessage* msg = make_msg($9);
385 			msg->what = (int32) $5;
386 			msg->AddString("class", $7);
387 			msg->AddString("add_on", (char*) $3.ptr);
388 			free_mem($7);
389 			free_mem($3.ptr);
390 			$$ = flatten_msg(msg);
391 		}
392 	;
393 
394 type
395 	: IDENT '{' typefields '}' { $$ = make_type($1, $3); }
396 	| IDENT '{' '}'
397 		{
398 			list_t list; list.count = 0; list.items = NULL;
399 			$$ = make_type($1, list);
400 		}
401 	| IDENT expr
402 		{
403 			$$ = make_type($1, make_data_list($2));
404 		}
405 	| type_or_define { $$ = $1; }
406 	;
407 
408 type_or_define
409 	: IDENT
410 		{
411 			if (is_type($1))
412 			{
413 				list_t list; list.count = 0; list.items = NULL;
414 				$$ = make_type($1, list);
415 			}
416 			else
417 			{
418 				define_t define = get_define($1);
419 				$$ = cast(get_type("int32"), make_int(define.value));
420 				free_mem($1);
421 			}
422 		}
423 	;
424 
425 typefields
426 	: typefields ',' typefield { $$ = concat_data_list($1, $3); }
427 	| typefield                { $$ = make_data_list($1); }
428 	;
429 
430 typefield
431 	: IDENT '=' expr { $$ = $3; $$.name = $1; }
432 	| expr           { $$ = $1; }
433 	;
434 
435 expr
436 	: expr '+' expr         { $$ = binary_expr($1, $3, '+'); }
437 	| expr '-' expr         { $$ = binary_expr($1, $3, '-'); }
438 	| expr '*' expr         { $$ = binary_expr($1, $3, '*'); }
439 	| expr '/' expr         { $$ = binary_expr($1, $3, '/'); }
440 	| expr '%' expr         { $$ = binary_expr($1, $3, '%'); }
441 	| expr '|' expr         { $$ = binary_expr($1, $3, '|'); }
442 	| expr '^' expr         { $$ = binary_expr($1, $3, '^'); }
443 	| expr '&' expr         { $$ = binary_expr($1, $3, '&'); }
444 	| '~' expr %prec FLIP   { $$ = unary_expr($2, '~'); }
445 	| data                  { $$ = $1; }
446 	;
447 
448 data
449 	: BOOL                  { $$ = cast(get_type("bool"), make_bool($1)); }
450 	| integer               { $$ = cast(get_type("int32"), make_int($1)); }
451 	| float                 { $$ = cast(get_type("float"), make_float($1)); }
452 	| STRING                { $$ = cast($1.type, $1); }
453 	| RAW                   { $$ = cast($1.type, $1); }
454 	| array                 { $$ = cast($1.type, $1); }
455 	| message               { $$ = cast($1.type, $1); }
456 	| archive               { $$ = cast($1.type, $1); }
457 	| type                  { $$ = cast($1.type, $1); }
458 	| '(' expr ')'          { $$ = $2; }
459 	| typecast BOOL         { $$ = cast($1, make_bool($2)); }
460 	| typecast integer      { $$ = cast($1, make_int($2)); }
461 	| typecast float        { $$ = cast($1, make_float($2)); }
462 	| typecast STRING       { $$ = cast($1, $2); }
463 	| typecast RAW          { $$ = cast($1, $2); }
464 	| typecast array        { $$ = cast($1, $2); }
465 	| typecast message      { $$ = cast($1, $2); }
466 	| typecast archive      { $$ = cast($1, $2); }
467 	| typecast type         { $$ = cast($1, $2); }
468 	| typecast '(' expr ')' { $$ = cast($1, $3); }
469 	;
470 
471 typecast
472 	: '(' ARRAY ')'         { $$ = get_type("raw"); }
473 	| '(' MESSAGE ')'       { $$ = get_type("message"); }
474 	| '(' ARCHIVE IDENT ')' { $$ = get_type("message"); free_mem($3); }
475 	| '(' IDENT ')'         { $$ = get_type($2); free_mem($2); }
476 	;
477 
478 datatype
479 	: ARRAY         { $$ = get_type("raw"); }
480 	| MESSAGE       { $$ = get_type("message"); }
481 	| ARCHIVE IDENT { $$ = get_type("message"); free_mem($2); }
482 	| IDENT         { $$ = get_type($1); free_mem($1); }
483 	;
484 
485 integer
486 	: INTEGER     { $$ = $1; }
487 	| '-' INTEGER { $$ = -($2); }
488 	;
489 
490 float
491 	: FLOAT       { $$ = $1; }
492 	| '-' FLOAT   { $$ = -($2); }
493 	;
494 
495 %%
496 //------------------------------------------------------------------------------
497 
498 
499 void
500 yyerror(const char* msg)
501 {
502 	// This function is called by the parser when it encounters
503 	// an error, after which it aborts parsing and returns from
504 	// yyparse(). We never call yyerror() directly.
505 
506 	rdef_err = RDEF_COMPILE_ERR;
507 	rdef_err_line = yylineno;
508 	strcpy(rdef_err_file, lexfile);
509 	strcpy(rdef_err_msg, msg);
510 }
511 
512 
513 void
514 add_symbol(const char* name, int32 id)
515 {
516 	if (symbol_table.find(name) != symbol_table.end())
517 		abort_compile(RDEF_COMPILE_ERR, "duplicate symbol %s", name);
518 
519 	symbol_table.insert(make_pair(name, id));
520 }
521 
522 
523 int32
524 get_symbol(const char* name)
525 {
526 	sym_iter_t i = symbol_table.find(name);
527 
528 	if (i == symbol_table.end())
529 		abort_compile(RDEF_COMPILE_ERR, "unknown symbol %s", name);
530 
531 	return i->second;
532 }
533 
534 
535 static void
536 add_builtin_type(type_code code, const char* name)
537 {
538 	type_t type;
539 	type.code     = code;
540 	type.name     = name;
541 	type.count    = 0;
542 	type.fields   = NULL;
543 	type.def_id   = 1;
544 	type.def_name = NULL;
545 
546 	type_table.insert(make_pair(name, type));
547 }
548 
549 
550 void
551 add_user_type(res_id_t id, type_code code, const char* name, list_t list)
552 {
553 	if (type_table.find(name) != type_table.end())
554 		abort_compile(RDEF_COMPILE_ERR, "duplicate type %s", name);
555 
556 	type_t type;
557 	type.code     = code;
558 	type.name     = name;
559 	type.count    = list.count;
560 	type.fields   = (field_t*) list.items;
561 	type.def_id   = 1;
562 	type.def_name = NULL;
563 
564 	if (id.has_id)
565 		type.def_id = id.id;
566 
567 	if (id.has_name)
568 		type.def_name = id.name;
569 
570 	type_table.insert(make_pair(name, type));
571 }
572 
573 
574 static bool
575 is_builtin_type(type_t type)
576 {
577 	return type.count == 0;
578 }
579 
580 
581 static bool
582 same_type(type_t type1, type_t type2)
583 {
584 	return type1.name == type2.name;  // no need for strcmp
585 }
586 
587 
588 type_t
589 get_type(const char* name)
590 {
591 	type_iter_t i = type_table.find(name);
592 
593 	if (i == type_table.end())
594 		abort_compile(RDEF_COMPILE_ERR, "unknown type %s", name);
595 
596 	return i->second;
597 }
598 
599 
600 bool
601 is_type(const char* name)
602 {
603 	return type_table.find(name) != type_table.end();
604 }
605 
606 
607 define_t
608 get_define(const char* name)
609 {
610 	define_iter_t i = define_table.find(name);
611 
612 	if (i == define_table.end())
613 		abort_compile(RDEF_COMPILE_ERR, "unknown define %s", name);
614 
615 	return i->second;
616 }
617 
618 
619 data_t
620 make_data(size_t size, type_t type)
621 {
622 	data_t out;
623 	out.type = type;
624 	out.name = NULL;
625 	out.size = size;
626 	out.ptr  = alloc_mem(size);
627 	return out;
628 }
629 
630 
631 data_t
632 make_bool(bool b)
633 {
634 	data_t out = make_data(sizeof(bool), get_type("bool"));
635 	*((bool*)out.ptr) = b;
636 	return out;
637 }
638 
639 
640 data_t
641 make_int(uint64 i)
642 {
643 	data_t out = make_data(sizeof(uint64), get_type("uint64"));
644 	*((uint64*)out.ptr) = i;
645 	return out;
646 }
647 
648 
649 data_t
650 make_float(double f)
651 {
652 	data_t out = make_data(sizeof(double), get_type("double"));
653 	*((double*)out.ptr) = f;
654 	return out;
655 }
656 
657 
658 data_t
659 import_data(char* filename)
660 {
661 	data_t out;
662 	out.type = get_type("raw");
663 	out.name = NULL;
664 
665 	char tmpname[B_PATH_NAME_LENGTH];
666 	if (open_file_from_include_dir(filename, tmpname)) {
667 		BFile file(tmpname, B_READ_ONLY);
668 		if (file.InitCheck() == B_OK) {
669 			off_t size;
670 			if (file.GetSize(&size) == B_OK) {
671 				out.size = (size_t) size;
672 				out.ptr  = alloc_mem(size);
673 
674 				if (file.Read(out.ptr, out.size) == (ssize_t) out.size) {
675 					free_mem(filename);
676 					return out;
677 				}
678 			}
679 		}
680 	}
681 
682 	abort_compile(RDEF_COMPILE_ERR, "cannot import %s", filename);
683 	return out;
684 }
685 
686 
687 data_t
688 resize_data(data_t data, size_t newSize)
689 {
690 	if (newSize == 0) {
691 		abort_compile(RDEF_COMPILE_ERR, "invalid size %lu", newSize);
692 	} else if (data.size != newSize) {
693 		void* newBuffer = alloc_mem(newSize);
694 
695 		memset(newBuffer, 0, newSize);
696 		memcpy(newBuffer, data.ptr, min(data.size, newSize));
697 
698 		if (data.type.code == B_STRING_TYPE)
699 			((char*)newBuffer)[newSize - 1] = '\0';
700 
701 		free_mem(data.ptr);
702 		data.ptr  = newBuffer;
703 		data.size = newSize;
704 	}
705 
706 	return data;
707 }
708 
709 
710 BMessage*
711 make_msg(list_t list)
712 {
713 	BMessage* msg = new BMessage;
714 
715 	for (int32 t = 0; t < list.count; ++t) {
716 		data_t data = ((data_t*)list.items)[t];
717 		msg->AddData(data.name, data.type.code, data.ptr, data.size, false);
718 		free_mem(data.name);
719 		free_mem(data.ptr);
720 	}
721 
722 	free_mem(list.items);
723 	return msg;
724 }
725 
726 
727 data_t
728 flatten_msg(BMessage* msg)
729 {
730 #ifndef B_BEOS_VERSION_DANO
731 	data_t out = make_data(msg->FlattenedSize(), get_type("message"));
732 	msg->Flatten((char*)out.ptr, out.size);
733 #else
734 	data_t out = make_data(msg->FlattenedSize(B_MESSAGE_VERSION_1),
735 		get_type("message"));
736 	msg->Flatten(B_MESSAGE_VERSION_1, (char*)out.ptr, out.size);
737 #endif
738 	delete msg;
739 	return out;
740 }
741 
742 
743 data_t
744 make_default(type_t type)
745 {
746 	data_t out;
747 
748 	if (is_builtin_type(type)) {
749 		switch (type.code) {
750 			case B_BOOL_TYPE:
751 				out = make_data(sizeof(bool), type);
752 				*((bool*)out.ptr) = false;
753 				break;
754 
755 			case B_INT8_TYPE:
756 			case B_UINT8_TYPE:
757 				out = make_data(sizeof(uint8), type);
758 				*((uint8*)out.ptr) = 0;
759 				break;
760 
761 			case B_INT16_TYPE:
762 			case B_UINT16_TYPE:
763 				out = make_data(sizeof(uint16), type);
764 				*((uint16*)out.ptr) = 0;
765 				break;
766 
767 			case B_INT32_TYPE:
768 			case B_UINT32_TYPE:
769 			case B_SIZE_T_TYPE:
770 			case B_SSIZE_T_TYPE:
771 			case B_TIME_TYPE:
772 				out = make_data(sizeof(uint32), type);
773 				*((uint32*)out.ptr) = 0;
774 				break;
775 
776 			case B_INT64_TYPE:
777 			case B_UINT64_TYPE:
778 			case B_OFF_T_TYPE:
779 				out = make_data(sizeof(uint64), type);
780 				*((uint64*)out.ptr) = 0;
781 				break;
782 
783 			case B_FLOAT_TYPE:
784 				out = make_data(sizeof(float), type);
785 				*((float*)out.ptr) = 0.0f;
786 				break;
787 
788 			case B_DOUBLE_TYPE:
789 				out = make_data(sizeof(double), type);
790 				*((double*)out.ptr) = 0.0;
791 				break;
792 
793 			case B_STRING_TYPE:
794 				out = make_data(sizeof(char), type);
795 				*((char*)out.ptr) = '\0';
796 				break;
797 
798 			case B_RAW_TYPE:
799 				out = make_data(0, type);
800 				break;
801 
802 			case B_MESSAGE_TYPE:
803 				out = flatten_msg(new BMessage);
804 				break;
805 		}
806 	} else {
807 		// For user-defined types, we copy the default values of the fields
808 		// into a new data_t object. There is no need to call resize_data()
809 		// here, because the default values were already resized to their
810 		// proper length when we added them to the type.
811 
812 		size_t size = 0;
813 		for (int32 t = 0; t < type.count; ++t) {
814 			size += type.fields[t].data.size;
815 		}
816 
817 		out = make_data(size, type);
818 
819 		uint8* ptr = (uint8*) out.ptr;
820 		for (int32 t = 0; t < type.count; ++t) {
821 			data_t field_data = type.fields[t].data;
822 			memcpy(ptr, field_data.ptr, field_data.size);
823 			ptr += field_data.size;
824 		}
825 	}
826 
827 	return out;
828 }
829 
830 
831 static data_t*
832 fill_slots(type_t type, list_t list)
833 {
834 	data_t* slots = (data_t*)alloc_mem(type.count * sizeof(data_t));
835 	memset(slots, 0, type.count * sizeof(data_t));
836 
837 	for (int32 t = 0; t < list.count; ++t) {
838 		data_t data = ((data_t*)list.items)[t];
839 
840 		if (data.name == NULL) {
841 			bool found = false;
842 			for (int32 k = 0; k < type.count; ++k) {
843 				if (slots[k].ptr == NULL) {
844 					slots[k] = cast(type.fields[k].type, data);
845 					found = true;
846 					break;
847 				}
848 			}
849 
850 			if (!found)
851 				abort_compile(RDEF_COMPILE_ERR, "too many fields");
852 		} else {
853 			// named field
854 			bool found = false;
855 			for (int32 k = 0; k < type.count; ++k) {
856 				if (strcmp(type.fields[k].name, data.name) == 0) {
857 					if (slots[k].ptr != NULL)
858 						free_mem(slots[k].ptr);
859 
860 					slots[k] = cast(type.fields[k].type, data);
861 					free_mem(data.name);
862 					found = true;
863 					break;
864 				}
865 			}
866 
867 			if (!found)
868 				abort_compile(RDEF_COMPILE_ERR, "unknown field %s", data.name);
869 		}
870 	}
871 
872 	return slots;
873 }
874 
875 
876 static data_t
877 convert_slots(type_t type, data_t* slots)
878 {
879 	size_t size = 0;
880 	for (int32 k = 0; k < type.count; ++k) {
881 		if (slots[k].ptr == NULL) {
882 			// default value
883 			size += type.fields[k].data.size;
884 		} else if (type.fields[k].resize != 0)
885 			size += type.fields[k].resize;
886 		else
887 			size += slots[k].size;
888 	}
889 
890 	data_t out = make_data(size, type);
891 	uint8* ptr = (uint8*) out.ptr;
892 
893 	for (int32 k = 0; k < type.count; ++k) {
894 		if (slots[k].ptr == NULL) {
895 			// default value
896 			memcpy(ptr, type.fields[k].data.ptr, type.fields[k].data.size);
897 			ptr += type.fields[k].data.size;
898 		} else if (type.fields[k].resize != 0) {
899 			data_t temp = resize_data(slots[k], type.fields[k].resize);
900 			memcpy(ptr, temp.ptr, temp.size);
901 			ptr += temp.size;
902 			free_mem(temp.ptr);
903 		} else {
904 			memcpy(ptr, slots[k].ptr, slots[k].size);
905 			ptr += slots[k].size;
906 			free_mem(slots[k].ptr);
907 		}
908 	}
909 
910 	free_mem(slots);
911 	return out;
912 }
913 
914 
915 data_t
916 make_type(char* name, list_t list)
917 {
918 	// Some explanation is in order. The "list" contains zero or more data_t
919 	// items. Each of these items corresponds to a data field that the user
920 	// specified, but not necessarily to a field from the type definition.
921 	// So here we have to figure out which data item goes where. It is fairly
922 	// obvious where names items should go, but for items without a name we
923 	// simply use the first available slot. For any fields that the user did
924 	// not fill in we use the default value from the type definition. This
925 	// algorithm allows for variable size fields, such as strings and arrays.
926 
927 	type_t type = get_type(name);
928 
929 	data_t* slots = fill_slots(type, list);
930 	data_t out = convert_slots(type, slots);
931 
932 	free_mem(name);
933 	free_mem(list.items);
934 	return out;
935 }
936 
937 
938 list_t
939 make_field_list(field_t field)
940 {
941 	list_t out;
942 	out.count = 1;
943 	out.items = alloc_mem(sizeof(field_t));
944 	*((field_t*)out.items) = field;
945 	return out;
946 }
947 
948 
949 list_t
950 concat_field_list(list_t list, field_t field)
951 {
952 	list_t out;
953 	out.count = list.count + 1;
954 	out.items = alloc_mem(out.count * sizeof(field_t));
955 
956 	memcpy(out.items, list.items, list.count * sizeof(field_t));
957 	memcpy((field_t*)out.items + list.count, &field, sizeof(field_t));
958 
959 	free_mem(list.items);
960 	return out;
961 }
962 
963 
964 list_t
965 make_data_list(data_t data)
966 {
967 	list_t out;
968 	out.count = 1;
969 	out.items = alloc_mem(sizeof(data_t));
970 	*((data_t*)out.items) = data;
971 	return out;
972 }
973 
974 
975 list_t
976 concat_data_list(list_t list, data_t data)
977 {
978 	list_t out;
979 	out.count = list.count + 1;
980 	out.items = (data_t*)alloc_mem(out.count * sizeof(data_t));
981 
982 	memcpy(out.items, list.items, list.count * sizeof(data_t));
983 	memcpy((data_t*)out.items + list.count, &data, sizeof(data_t));
984 
985 	free_mem(list.items);
986 	return out;
987 }
988 
989 
990 data_t
991 concat_data(data_t data1, data_t data2)
992 {
993 	data_t out = make_data(data1.size + data2.size, get_type("raw"));
994 
995 	memcpy(out.ptr, data1.ptr, data1.size);
996 	memcpy((uint8*)out.ptr + data1.size, data2.ptr, data2.size);
997 
998 	free_mem(data1.ptr);
999 	free_mem(data2.ptr);
1000 	return out;
1001 }
1002 
1003 
1004 static data_t
1005 cast_to_uint8(type_t new_type, data_t data)
1006 {
1007 	data_t out = make_data(sizeof(uint8), new_type);
1008 
1009 	switch (data.type.code) {
1010 		case B_INT8_TYPE:
1011 		case B_UINT8_TYPE:
1012 			*((uint8*)out.ptr) = *(uint8*)data.ptr;
1013 			break;
1014 
1015 		case B_INT16_TYPE:
1016 		case B_UINT16_TYPE:
1017 			*((uint8*)out.ptr) = (uint8)*(uint16*)data.ptr;
1018 			break;
1019 
1020 		case B_INT32_TYPE:
1021 		case B_UINT32_TYPE:
1022 		case B_SIZE_T_TYPE:
1023 		case B_SSIZE_T_TYPE:
1024 		case B_TIME_TYPE:
1025 			*((uint8*)out.ptr) = (uint8)*(uint32*)data.ptr;
1026 			break;
1027 
1028 		case B_INT64_TYPE:
1029 		case B_UINT64_TYPE:
1030 		case B_OFF_T_TYPE:
1031 			*((uint8*)out.ptr) = (uint8)*(uint64*)data.ptr;
1032 			break;
1033 
1034 		default:
1035 			abort_compile(RDEF_COMPILE_ERR, "cannot cast to this type");
1036 	}
1037 
1038 	free_mem(data.ptr);
1039 	return out;
1040 }
1041 
1042 
1043 static data_t
1044 cast_to_uint16(type_t new_type, data_t data)
1045 {
1046 	data_t out = make_data(sizeof(uint16), new_type);
1047 
1048 	switch (data.type.code) {
1049 		case B_INT8_TYPE:
1050 		case B_UINT8_TYPE:
1051 			*((uint16*)out.ptr) = (uint16)*(uint8*)data.ptr;
1052 			break;
1053 
1054 		case B_INT16_TYPE:
1055 		case B_UINT16_TYPE:
1056 			*((uint16*)out.ptr) = *(uint16*)data.ptr;
1057 			break;
1058 
1059 		case B_INT32_TYPE:
1060 		case B_UINT32_TYPE:
1061 		case B_SIZE_T_TYPE:
1062 		case B_SSIZE_T_TYPE:
1063 		case B_TIME_TYPE:
1064 			*((uint16*)out.ptr) = (uint16)*(uint32*)data.ptr;
1065 			break;
1066 
1067 		case B_INT64_TYPE:
1068 		case B_UINT64_TYPE:
1069 		case B_OFF_T_TYPE:
1070 			*((uint16*)out.ptr) = (uint16)*(uint64*)data.ptr;
1071 			break;
1072 
1073 		default:
1074 			abort_compile(RDEF_COMPILE_ERR, "cannot cast to this type");
1075 	}
1076 
1077 	free_mem(data.ptr);
1078 	return out;
1079 }
1080 
1081 
1082 static data_t
1083 cast_to_uint32(type_t new_type, data_t data)
1084 {
1085 	data_t out = make_data(sizeof(uint32), new_type);
1086 
1087 	switch (data.type.code) {
1088 		case B_INT8_TYPE:
1089 		case B_UINT8_TYPE:
1090 			*((uint32*)out.ptr) = (uint32)*(uint8*)data.ptr;
1091 			break;
1092 
1093 		case B_INT16_TYPE:
1094 		case B_UINT16_TYPE:
1095 			*((uint32*)out.ptr) = (uint32)*(uint16*)data.ptr;
1096 			break;
1097 
1098 		case B_INT32_TYPE:
1099 		case B_UINT32_TYPE:
1100 		case B_SIZE_T_TYPE:
1101 		case B_SSIZE_T_TYPE:
1102 		case B_TIME_TYPE:
1103 			*((uint32*)out.ptr) = *(uint32*)data.ptr;
1104 			break;
1105 
1106 		case B_INT64_TYPE:
1107 		case B_UINT64_TYPE:
1108 		case B_OFF_T_TYPE:
1109 			*((uint32*)out.ptr) = (uint32)*(uint64*)data.ptr;
1110 			break;
1111 
1112 		default:
1113 			abort_compile(RDEF_COMPILE_ERR, "cannot cast to this type");
1114 	}
1115 
1116 	free_mem(data.ptr);
1117 	return out;
1118 }
1119 
1120 
1121 static data_t
1122 cast_to_uint64(type_t new_type, data_t data)
1123 {
1124 	data_t out = make_data(sizeof(uint64), new_type);
1125 
1126 	switch (data.type.code) {
1127 		case B_INT8_TYPE:
1128 		case B_UINT8_TYPE:
1129 			*((uint64*)out.ptr) = (uint64)*(uint8*)data.ptr;
1130 			break;
1131 
1132 		case B_INT16_TYPE:
1133 		case B_UINT16_TYPE:
1134 			*((uint64*)out.ptr) = (uint64)*(uint16*)data.ptr;
1135 			break;
1136 
1137 		case B_INT32_TYPE:
1138 		case B_UINT32_TYPE:
1139 		case B_SIZE_T_TYPE:
1140 		case B_SSIZE_T_TYPE:
1141 		case B_TIME_TYPE:
1142 			*((uint64*)out.ptr) = (uint64)*(uint32*)data.ptr;
1143 			break;
1144 
1145 		case B_INT64_TYPE:
1146 		case B_UINT64_TYPE:
1147 		case B_OFF_T_TYPE:
1148 			*((uint64*)out.ptr) = *(uint64*)data.ptr;
1149 			break;
1150 
1151 		default:
1152 			abort_compile(RDEF_COMPILE_ERR, "cannot cast to this type");
1153 	}
1154 
1155 	free_mem(data.ptr);
1156 	return out;
1157 }
1158 
1159 
1160 static data_t
1161 cast_to_float(type_t new_type, data_t data)
1162 {
1163 	data_t out = make_data(sizeof(float), new_type);
1164 
1165 	switch (data.type.code) {
1166 		case B_INT8_TYPE:
1167 		case B_UINT8_TYPE:
1168 			*((float*)out.ptr) = (float)*((uint8*)data.ptr);
1169 			break;
1170 
1171 		case B_INT16_TYPE:
1172 		case B_UINT16_TYPE:
1173 			*((float*)out.ptr) = (float)*((uint16*)data.ptr);
1174 			break;
1175 
1176 		case B_INT32_TYPE:
1177 		case B_UINT32_TYPE:
1178 		case B_SIZE_T_TYPE:
1179 		case B_SSIZE_T_TYPE:
1180 		case B_TIME_TYPE:
1181 			*((float*)out.ptr) = (float)*((uint32*)data.ptr);
1182 			break;
1183 
1184 		case B_INT64_TYPE:
1185 		case B_UINT64_TYPE:
1186 		case B_OFF_T_TYPE:
1187 			*((float*)out.ptr) = (float)*((uint64*)data.ptr);
1188 			break;
1189 
1190 		case B_DOUBLE_TYPE:
1191 			*((float*)out.ptr) = (float)*((double*)data.ptr);
1192 			break;
1193 
1194 		default:
1195 			abort_compile(RDEF_COMPILE_ERR, "cannot cast to this type");
1196 	}
1197 
1198 	free_mem(data.ptr);
1199 	return out;
1200 }
1201 
1202 
1203 static data_t
1204 cast_to_double(type_t new_type, data_t data)
1205 {
1206 	data_t out = make_data(sizeof(double), new_type);
1207 
1208 	switch (data.type.code) {
1209 		case B_INT8_TYPE:
1210 		case B_UINT8_TYPE:
1211 			*((double*)out.ptr) = (double)*((uint8*)data.ptr);
1212 			break;
1213 
1214 		case B_INT16_TYPE:
1215 		case B_UINT16_TYPE:
1216 			*((double*)out.ptr) = (double)*((uint16*)data.ptr);
1217 			break;
1218 
1219 		case B_INT32_TYPE:
1220 		case B_UINT32_TYPE:
1221 		case B_SIZE_T_TYPE:
1222 		case B_SSIZE_T_TYPE:
1223 		case B_TIME_TYPE:
1224 			*((double*)out.ptr) = (double)*((uint32*)data.ptr);
1225 			break;
1226 
1227 		case B_INT64_TYPE:
1228 		case B_UINT64_TYPE:
1229 		case B_OFF_T_TYPE:
1230 			*((double*)out.ptr) = (double)*((uint64*)data.ptr);
1231 			break;
1232 
1233 		case B_FLOAT_TYPE:
1234 			*((double*)out.ptr) = (double)*((float*)data.ptr);
1235 			break;
1236 
1237 		default:
1238 			abort_compile(RDEF_COMPILE_ERR, "cannot cast to this type");
1239 	}
1240 
1241 	free_mem(data.ptr);
1242 	return out;
1243 }
1244 
1245 
1246 data_t
1247 cast(type_t newType, data_t data)
1248 {
1249 	if (same_type(newType, data.type)) {
1250 		// you can't cast bool, string,
1251 		// message, or user-defined type
1252 		// to another type, only to same
1253 		return data;
1254 	}
1255 
1256 	if (is_builtin_type(newType)) {
1257 		switch (newType.code) {
1258 			case B_INT8_TYPE:
1259 			case B_UINT8_TYPE:
1260 				return cast_to_uint8(newType, data);
1261 
1262 			case B_INT16_TYPE:
1263 			case B_UINT16_TYPE:
1264 				return cast_to_uint16(newType, data);
1265 
1266 			case B_INT32_TYPE:
1267 			case B_UINT32_TYPE:
1268 			case B_SIZE_T_TYPE:
1269 			case B_SSIZE_T_TYPE:
1270 			case B_TIME_TYPE:
1271 				return cast_to_uint32(newType, data);
1272 
1273 			case B_INT64_TYPE:
1274 			case B_UINT64_TYPE:
1275 			case B_OFF_T_TYPE:
1276 				return cast_to_uint64(newType, data);
1277 
1278 			case B_FLOAT_TYPE:
1279 				return cast_to_float(newType, data);
1280 
1281 			case B_DOUBLE_TYPE:
1282 				return cast_to_double(newType, data);
1283 
1284 			case B_RAW_TYPE:
1285 				// you can always cast anything to raw
1286 				data.type = newType;
1287 				return data;
1288 		}
1289 	}
1290 
1291 	abort_compile(RDEF_COMPILE_ERR, "cannot cast to this type");
1292 	return data;
1293 }
1294 
1295 
1296 data_t
1297 unary_expr(data_t data, char oper)
1298 {
1299 	data_t op = cast_to_uint32(get_type("int32"), data);
1300 	int32 i = *((int32*)op.ptr);
1301 	data_t out;
1302 
1303 	switch (oper) {
1304 		case '~':
1305 			out = make_int(~i);
1306 			break;
1307 	}
1308 
1309 	free_mem(op.ptr);
1310 
1311 	return cast(get_type("int32"), out);
1312 }
1313 
1314 
1315 data_t
1316 binary_expr(data_t data1, data_t data2, char oper)
1317 {
1318 	data_t op1 = cast_to_uint32(get_type("int32"), data1);
1319 	data_t op2 = cast_to_uint32(get_type("int32"), data2);
1320 	int32 i1 = *((int32*) op1.ptr);
1321 	int32 i2 = *((int32*) op2.ptr);
1322 	data_t out;
1323 
1324 	switch (oper) {
1325 		case '+':
1326 			out = make_int(i1 + i2);
1327 			break;
1328 		case '-':
1329 			out = make_int(i1 - i2);
1330 			break;
1331 		case '*':
1332 			out = make_int(i1 * i2);
1333 			break;
1334 
1335 		case '/':
1336 			if (i2 == 0)
1337 				abort_compile(RDEF_COMPILE_ERR, "division by zero");
1338 			else
1339 				 out = make_int(i1 / i2);
1340 			break;
1341 
1342 		case '%':
1343 			if (i2 == 0)
1344 				abort_compile(RDEF_COMPILE_ERR, "division by zero");
1345 			else
1346 				out = make_int(i1 % i2);
1347 			break;
1348 
1349 		case '|':
1350 			out = make_int(i1 | i2);
1351 			break;
1352 		case '^':
1353 			out = make_int(i1 ^ i2);
1354 			break;
1355 		case '&':
1356 			out = make_int(i1 & i2);
1357 			break;
1358 	}
1359 
1360 	free_mem(op1.ptr);
1361 	free_mem(op2.ptr);
1362 
1363 	return cast(get_type("int32"), out);
1364 }
1365 
1366 
1367 void
1368 add_resource(res_id_t id, type_code code, data_t data)
1369 {
1370 	if (!id.has_id)
1371 		id.id = data.type.def_id;
1372 
1373 	if (!id.has_name)
1374 		id.name = (char*)data.type.def_name;
1375 
1376 	if (!(flags & RDEF_MERGE_RESOURCES) && rsrc.HasResource(code, id.id))
1377 		abort_compile(RDEF_COMPILE_ERR, "duplicate resource");
1378 
1379 	status_t err = rsrc.AddResource(code, id.id, data.ptr, data.size, id.name);
1380 	if (err != B_OK) {
1381 		rdef_err = RDEF_WRITE_ERR;
1382 		rdef_err_line = 0;
1383 		strcpy(rdef_err_file, rsrc_file);
1384 		sprintf(rdef_err_msg, "cannot add resource (%s)", strerror(err));
1385 		abort_compile();
1386 	}
1387 
1388 	if (id.has_name)
1389 		free_mem(id.name);
1390 
1391 	free_mem(data.ptr);
1392 }
1393 
1394 
1395 static void
1396 add_point_type()
1397 {
1398 	field_t* fields  = (field_t*)alloc_mem(2 * sizeof(field_t));
1399 	fields[0].type   = get_type("float");
1400 	fields[0].name   = "x";
1401 	fields[0].resize = 0;
1402 	fields[0].data   = make_default(fields[0].type);
1403 	fields[1].type   = get_type("float");
1404 	fields[1].name   = "y";
1405 	fields[1].resize = 0;
1406 	fields[1].data   = make_default(fields[1].type);
1407 
1408 	type_t type;
1409 	type.code     = B_POINT_TYPE;
1410 	type.name     = "point";
1411 	type.fields   = fields;
1412 	type.count    = 2;
1413 	type.def_id   = 1;
1414 	type.def_name = NULL;
1415 
1416 	type_table.insert(make_pair(type.name, type));
1417 }
1418 
1419 
1420 static void
1421 add_rect_type()
1422 {
1423 	field_t* fields  = (field_t*)alloc_mem(4 * sizeof(field_t));
1424 	fields[0].type   = get_type("float");
1425 	fields[0].name   = "left";
1426 	fields[0].resize = 0;
1427 	fields[0].data   = make_default(fields[0].type);
1428 	fields[1].type   = get_type("float");
1429 	fields[1].name   = "top";
1430 	fields[1].resize = 0;
1431 	fields[1].data   = make_default(fields[1].type);
1432 	fields[2].type   = get_type("float");
1433 	fields[2].name   = "right";
1434 	fields[2].resize = 0;
1435 	fields[2].data   = make_default(fields[2].type);
1436 	fields[3].type   = get_type("float");
1437 	fields[3].name   = "bottom";
1438 	fields[3].resize = 0;
1439 	fields[3].data   = make_default(fields[3].type);
1440 
1441 	type_t type;
1442 	type.code     = B_RECT_TYPE;
1443 	type.name     = "rect";
1444 	type.fields   = fields;
1445 	type.count    = 4;
1446 	type.def_id   = 1;
1447 	type.def_name = NULL;
1448 
1449 	type_table.insert(make_pair(type.name, type));
1450 }
1451 
1452 
1453 static void
1454 add_rgb_color_type()
1455 {
1456 	field_t* fields  = (field_t*)alloc_mem(4 * sizeof(field_t));
1457 	fields[0].type   = get_type("uint8");
1458 	fields[0].name   = "red";
1459 	fields[0].resize = 0;
1460 	fields[0].data   = make_default(fields[0].type);
1461 	fields[1].type   = get_type("uint8");
1462 	fields[1].name   = "green";
1463 	fields[1].resize = 0;
1464 	fields[1].data   = make_default(fields[1].type);
1465 	fields[2].type   = get_type("uint8");
1466 	fields[2].name   = "blue";
1467 	fields[2].resize = 0;
1468 	fields[2].data   = make_default(fields[2].type);
1469 	fields[3].type   = get_type("uint8");
1470 	fields[3].name   = "alpha";
1471 	fields[3].resize = 0;
1472 	fields[3].data   = make_default(fields[3].type);
1473 
1474 	*((uint8*)fields[3].data.ptr) = 255;
1475 
1476 	type_t type;
1477 	type.code     = B_RGB_COLOR_TYPE;
1478 	type.name     = "rgb_color";
1479 	type.fields   = fields;
1480 	type.count    = 4;
1481 	type.def_id   = 1;
1482 	type.def_name = NULL;
1483 
1484 	type_table.insert(make_pair(type.name, type));
1485 }
1486 
1487 
1488 static void
1489 add_app_signature_type()
1490 {
1491 	field_t* fields  = (field_t*)alloc_mem(1 * sizeof(field_t));
1492 	fields[0].type   = get_type("string");
1493 	fields[0].name   = "signature";
1494 	fields[0].resize = 0;
1495 	fields[0].data   = make_default(fields[0].type);
1496 
1497 	type_t type;
1498 	type.code     = 'MIMS';
1499 	type.name     = "app_signature";
1500 	type.fields   = fields;
1501 	type.count    = 1;
1502 	type.def_id   = 1;
1503 	type.def_name = "BEOS:APP_SIG";
1504 
1505 	type_table.insert(make_pair(type.name, type));
1506 }
1507 
1508 
1509 static void
1510 add_app_flags()
1511 {
1512 	field_t* fields  = (field_t*)alloc_mem(1 * sizeof(field_t));
1513 	fields[0].type   = get_type("uint32");
1514 	fields[0].name   = "flags";
1515 	fields[0].resize = 0;
1516 	fields[0].data   = make_default(fields[0].type);
1517 
1518 	type_t type;
1519 	type.code     = 'APPF';
1520 	type.name     = "app_flags";
1521 	type.fields   = fields;
1522 	type.count    = 1;
1523 	type.def_id   = 1;
1524 	type.def_name = "BEOS:APP_FLAGS";
1525 
1526 	type_table.insert(make_pair(type.name, type));
1527 }
1528 
1529 
1530 static void
1531 add_app_version()
1532 {
1533 	field_t* fields  = (field_t*)alloc_mem(7 * sizeof(field_t));
1534 	fields[0].type   = get_type("uint32");
1535 	fields[0].name   = "major";
1536 	fields[0].resize = 0;
1537 	fields[0].data   = make_default(fields[0].type);
1538 	fields[1].type   = get_type("uint32");
1539 	fields[1].name   = "middle";
1540 	fields[1].resize = 0;
1541 	fields[1].data   = make_default(fields[1].type);
1542 	fields[2].type   = get_type("uint32");
1543 	fields[2].name   = "minor";
1544 	fields[2].resize = 0;
1545 	fields[2].data   = make_default(fields[2].type);
1546 	fields[3].type   = get_type("uint32");
1547 	fields[3].name   = "variety";
1548 	fields[3].resize = 0;
1549 	fields[3].data   = make_default(fields[3].type);
1550 	fields[4].type   = get_type("uint32");
1551 	fields[4].name   = "internal";
1552 	fields[4].resize = 0;
1553 	fields[4].data   = make_default(fields[4].type);
1554 	fields[5].type   = get_type("string");
1555 	fields[5].name   = "short_info";
1556 	fields[5].resize = 64;
1557 	fields[5].data   = make_data(fields[5].resize, fields[5].type);
1558 	fields[6].type   = get_type("string");
1559 	fields[6].name   = "long_info";
1560 	fields[6].resize = 256;
1561 	fields[6].data   = make_data(fields[6].resize, fields[6].type);
1562 
1563 	memset(fields[5].data.ptr, '\0', fields[5].data.size);
1564 	memset(fields[6].data.ptr, '\0', fields[6].data.size);
1565 
1566 	type_t type;
1567 	type.code     = 'APPV';
1568 	type.name     = "app_version";
1569 	type.fields   = fields;
1570 	type.count    = 7;
1571 	type.def_id   = 1;
1572 	type.def_name = "BEOS:APP_VERSION";
1573 
1574 	type_table.insert(make_pair(type.name, type));
1575 }
1576 
1577 
1578 static void
1579 add_png_icon()
1580 {
1581 	field_t* fields  = (field_t*)alloc_mem(1 * sizeof(field_t));
1582 	fields[0].type   = get_type("raw");
1583 	fields[0].name   = "icon";
1584 	fields[0].resize = 0;
1585 	fields[0].data   = make_data(fields[0].resize, fields[0].type);
1586 
1587 	type_t type;
1588 	type.code     = 'PNG ';
1589 	type.name     = "png_icon";
1590 	type.fields   = fields;
1591 	type.count    = 1;
1592 	type.def_id   = 101;
1593 	type.def_name = "BEOS:ICON";
1594 
1595 	type_table.insert(make_pair(type.name, type));
1596 }
1597 
1598 
1599 static void
1600 add_vector_icon()
1601 {
1602 	field_t* fields  = (field_t*)alloc_mem(1 * sizeof(field_t));
1603 	fields[0].type   = get_type("raw");
1604 	fields[0].name   = "icon";
1605 	fields[0].resize = 0;
1606 	fields[0].data   = make_data(fields[0].resize, fields[0].type);
1607 
1608 	type_t type;
1609 	type.code     = 'VICN';
1610 	type.name     = "vector_icon";
1611 	type.fields   = fields;
1612 	type.count    = 1;
1613 	type.def_id   = 101;
1614 	type.def_name = "BEOS:ICON";
1615 
1616 	type_table.insert(make_pair(type.name, type));
1617 }
1618 
1619 
1620 static void
1621 add_large_icon()
1622 {
1623 	field_t* fields  = (field_t*)alloc_mem(1 * sizeof(field_t));
1624 	fields[0].type   = get_type("raw");
1625 	fields[0].name   = "icon";
1626 	fields[0].resize = 1024;
1627 	fields[0].data   = make_data(fields[0].resize, fields[0].type);
1628 
1629 	type_t type;
1630 	type.code     = 'ICON';
1631 	type.name     = "large_icon";
1632 	type.fields   = fields;
1633 	type.count    = 1;
1634 	type.def_id   = 101;
1635 	type.def_name = "BEOS:L:STD_ICON";
1636 
1637 	type_table.insert(make_pair(type.name, type));
1638 }
1639 
1640 
1641 static void
1642 add_mini_icon()
1643 {
1644 	field_t* fields  = (field_t*)alloc_mem(1 * sizeof(field_t));
1645 	fields[0].type   = get_type("raw");
1646 	fields[0].name   = "icon";
1647 	fields[0].resize = 256;
1648 	fields[0].data   = make_data(fields[0].resize, fields[0].type);
1649 
1650 	type_t type;
1651 	type.code     = 'MICN';
1652 	type.name     = "mini_icon";
1653 	type.fields   = fields;
1654 	type.count    = 1;
1655 	type.def_id   = 101;
1656 	type.def_name = "BEOS:M:STD_ICON";
1657 
1658 	type_table.insert(make_pair(type.name, type));
1659 }
1660 
1661 
1662 static void
1663 add_file_types()
1664 {
1665 	field_t* fields  = (field_t*)alloc_mem(1 * sizeof(field_t));
1666 	fields[0].type   = get_type("message");
1667 	fields[0].name   = "types";
1668 	fields[0].resize = 0;
1669 	fields[0].data   = make_default(fields[0].type);
1670 
1671 	type_t type;
1672 	type.code     = 'MSGG';
1673 	type.name     = "file_types";
1674 	type.fields   = fields;
1675 	type.count    = 1;
1676 	type.def_id   = 1;
1677 	type.def_name = "BEOS:FILE_TYPES";
1678 
1679 	type_table.insert(make_pair(type.name, type));
1680 }
1681 
1682 
1683 static void
1684 add_define(const char* name, int32 value)
1685 {
1686 	define_t define;
1687 	define.name  = name;
1688 	define.value = value;
1689 
1690 	define_table.insert(make_pair(define.name, define));
1691 }
1692 
1693 
1694 void
1695 init_parser()
1696 {
1697 	add_builtin_type(B_BOOL_TYPE,    "bool");
1698 	add_builtin_type(B_INT8_TYPE,    "int8");
1699 	add_builtin_type(B_UINT8_TYPE,   "uint8");
1700 	add_builtin_type(B_INT16_TYPE,   "int16");
1701 	add_builtin_type(B_UINT16_TYPE,  "uint16");
1702 	add_builtin_type(B_INT32_TYPE,   "int32");
1703 	add_builtin_type(B_UINT32_TYPE,  "uint32");
1704 	add_builtin_type(B_SIZE_T_TYPE,  "size_t");
1705 	add_builtin_type(B_SSIZE_T_TYPE, "ssize_t");
1706 	add_builtin_type(B_TIME_TYPE,    "time_t");
1707 	add_builtin_type(B_INT64_TYPE,   "int64");
1708 	add_builtin_type(B_UINT64_TYPE,  "uint64");
1709 	add_builtin_type(B_OFF_T_TYPE,   "off_t");
1710 	add_builtin_type(B_FLOAT_TYPE,   "float");
1711 	add_builtin_type(B_DOUBLE_TYPE,  "double");
1712 	add_builtin_type(B_STRING_TYPE,  "string");
1713 	add_builtin_type(B_RAW_TYPE,     "raw");
1714 	add_builtin_type(B_RAW_TYPE,     "buffer");
1715 	add_builtin_type(B_MESSAGE_TYPE, "message");
1716 
1717 	add_point_type();
1718 	add_rect_type();
1719 	add_rgb_color_type();
1720 	add_app_signature_type();
1721 	add_app_flags();
1722 	add_app_version();
1723 	add_large_icon();
1724 	add_mini_icon();
1725 	add_vector_icon();
1726 	add_png_icon();
1727 	add_file_types();
1728 
1729 	add_define("B_SINGLE_LAUNCH",    0x0);
1730 	add_define("B_MULTIPLE_LAUNCH",  0x1);
1731 	add_define("B_EXCLUSIVE_LAUNCH", 0x2);
1732 	add_define("B_BACKGROUND_APP",   0x4);
1733 	add_define("B_ARGV_ONLY",        0x8);
1734 
1735 	add_define("B_APPV_DEVELOPMENT",   0x0);
1736 	add_define("B_APPV_ALPHA",         0x1);
1737 	add_define("B_APPV_BETA",          0x2);
1738 	add_define("B_APPV_GAMMA",         0x3);
1739 	add_define("B_APPV_GOLDEN_MASTER", 0x4);
1740 	add_define("B_APPV_FINAL",         0x5);
1741 }
1742 
1743 
1744 void
1745 clean_up_parser()
1746 {
1747 	// The symbol table entries have several malloc'ed objects associated
1748 	// with them (such as their name). They were allocated with alloc_mem(),
1749 	// so we don't need to free them here; compile.cpp already does that
1750 	// when it cleans up. However, we do need to remove the entries from
1751 	// the tables, otherwise they will still be around the next time we are
1752 	// asked to compile something.
1753 
1754 #ifdef DEBUG
1755 	// Note that in DEBUG mode, we _do_ free these items, so they don't show
1756 	// up in the mem leak statistics. The names etc of builtin items are not
1757 	// alloc_mem()'d but we still free_mem() them. Not entirely correct, but
1758 	// it doesn't seem to hurt, and we only do it in DEBUG mode anyway.
1759 
1760 	for (sym_iter_t i = symbol_table.begin(); i != symbol_table.end(); ++i) {
1761 		free_mem((void*) i->first);
1762 	}
1763 
1764 	for (type_iter_t i = type_table.begin(); i != type_table.end(); ++i) {
1765 		free_mem((void*) i->first);
1766 		type_t type = i->second;
1767 
1768 		for (int32 t = 0; t < type.count; ++t) {
1769 			free_mem((void*) type.fields[t].name);
1770 			free_mem((void*) type.fields[t].data.ptr);
1771 		}
1772 		free_mem((void*) type.fields);
1773 		free_mem((void*) type.name);
1774 		free_mem((void*) type.def_name);
1775 	}
1776 #endif
1777 
1778 	symbol_table.clear();
1779 	type_table.clear();
1780 	define_table.clear();
1781 }
1782 
1783