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
36using namespace std;
37
38#define YYERROR_VERBOSE
39
40static void yyerror(const char*);
41
42struct 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
50typedef std::map<const char*, int32, ident_compare_t> sym_tab_t;
51typedef sym_tab_t::iterator sym_iter_t;
52
53typedef std::map<const char*, type_t, ident_compare_t> type_tab_t;
54typedef type_tab_t::iterator type_iter_t;
55
56typedef std::map<const char*, define_t, ident_compare_t> define_tab_t;
57typedef define_tab_t::iterator define_iter_t;
58
59
60static sym_tab_t symbol_table;  // symbol table for enums
61static int32 enum_cnt;          // counter for enum symbols without id
62static type_tab_t type_table;  // symbol table for data types
63static define_tab_t define_table;  // symbol table for defines
64
65
66static void add_user_type(res_id_t, type_code, const char*, list_t);
67static void add_symbol(const char*, int32);
68static int32 get_symbol(const char*);
69
70static bool is_type(const char* name);
71static define_t get_define(const char* name);
72
73static data_t make_data(size_t, type_t);
74static data_t make_bool(bool);
75static data_t make_int(uint64);
76static data_t make_float(double);
77
78static data_t import_data(char*);
79static data_t resize_data(data_t, size_t);
80
81static BMessage* make_msg(list_t);
82static data_t flatten_msg(BMessage*);
83
84static data_t make_default(type_t);
85static data_t make_type(char* name, list_t);
86
87static list_t make_field_list(field_t);
88static list_t concat_field_list(list_t, field_t);
89static list_t make_data_list(data_t);
90static list_t concat_data_list(list_t, data_t);
91static data_t concat_data(data_t, data_t);
92
93static data_t cast(type_t, data_t);
94
95static data_t unary_expr(data_t, char);
96static data_t binary_expr(data_t, data_t, char);
97
98static 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
146script
147	: /* empty */
148	| script enum
149	| script typedef
150	| script resource
151	;
152
153enum
154	: enumstart '{' '}' ';'
155	| enumstart '{' symbols '}' ';'
156	| enumstart '{' symbols ',' '}' ';'
157	;
158
159enumstart
160	: ENUM { enum_cnt = 0; }
161	;
162
163symbols
164	: symbols ',' symboldef
165	| symboldef
166	;
167
168symboldef
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
182typedef
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
193typedeffields
194	: typedeffields ',' typedeffield { $$ = concat_field_list($1, $3); }
195	| typedeffield                   { $$ = make_field_list($1); }
196	;
197
198typedeffield
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
229resource
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
244id
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
290array
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
298arrayfields
299	: arrayfields ',' expr { $$ = concat_data($1, $3); }
300	| expr                 { $$ = $1; $$.type = get_type("raw"); }
301	;
302
303message
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
327msgfields
328	: msgfields ',' msgfield { $$ = concat_data_list($1, $3); }
329	| msgfield               { $$ = make_data_list($1); }
330	;
331
332msgfield
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
357archive
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
394type
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
408type_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
425typefields
426	: typefields ',' typefield { $$ = concat_data_list($1, $3); }
427	| typefield                { $$ = make_data_list($1); }
428	;
429
430typefield
431	: IDENT '=' expr { $$ = $3; $$.name = $1; }
432	| expr           { $$ = $1; }
433	;
434
435expr
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
448data
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
471typecast
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
478datatype
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
485integer
486	: INTEGER     { $$ = $1; }
487	| '-' INTEGER { $$ = -($2); }
488	;
489
490float
491	: FLOAT       { $$ = $1; }
492	| '-' FLOAT   { $$ = -($2); }
493	;
494
495%%
496//------------------------------------------------------------------------------
497
498
499void
500yyerror(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
513void
514add_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
523int32
524get_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
535static void
536add_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
550void
551add_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
574static bool
575is_builtin_type(type_t type)
576{
577	return type.count == 0;
578}
579
580
581static bool
582same_type(type_t type1, type_t type2)
583{
584	return type1.name == type2.name;  // no need for strcmp
585}
586
587
588type_t
589get_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
600bool
601is_type(const char* name)
602{
603	return type_table.find(name) != type_table.end();
604}
605
606
607define_t
608get_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
619data_t
620make_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
631data_t
632make_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
640data_t
641make_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
649data_t
650make_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
658data_t
659import_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
687data_t
688resize_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
710BMessage*
711make_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
727data_t
728flatten_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
743data_t
744make_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
831static data_t*
832fill_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
876static data_t
877convert_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
915data_t
916make_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
938list_t
939make_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
949list_t
950concat_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
964list_t
965make_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
975list_t
976concat_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
990data_t
991concat_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
1004static data_t
1005cast_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
1043static data_t
1044cast_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
1082static data_t
1083cast_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
1121static data_t
1122cast_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
1160static data_t
1161cast_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
1203static data_t
1204cast_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
1246data_t
1247cast(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
1296data_t
1297unary_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
1315data_t
1316binary_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
1367void
1368add_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
1395static void
1396add_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
1420static void
1421add_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
1453static void
1454add_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
1488static void
1489add_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
1509static void
1510add_app_name_catalog_entry()
1511{
1512	field_t* fields  = (field_t*)alloc_mem(1 * sizeof(field_t));
1513	fields[0].type   = get_type("string");
1514	fields[0].name   = "catalog_entry";
1515	fields[0].resize = 0;
1516	fields[0].data   = make_default(fields[0].type);
1517
1518	type_t type;
1519	type.code     = B_STRING_TYPE;
1520	type.name     = "app_name_catalog_entry";
1521	type.fields   = fields;
1522	type.count    = 1;
1523	type.def_id   = 1;
1524	type.def_name = "SYS:NAME";
1525
1526	type_table.insert(make_pair(type.name, type));
1527}
1528
1529
1530static void
1531add_app_flags()
1532{
1533	field_t* fields  = (field_t*)alloc_mem(1 * sizeof(field_t));
1534	fields[0].type   = get_type("uint32");
1535	fields[0].name   = "flags";
1536	fields[0].resize = 0;
1537	fields[0].data   = make_default(fields[0].type);
1538
1539	type_t type;
1540	type.code     = 'APPF';
1541	type.name     = "app_flags";
1542	type.fields   = fields;
1543	type.count    = 1;
1544	type.def_id   = 1;
1545	type.def_name = "BEOS:APP_FLAGS";
1546
1547	type_table.insert(make_pair(type.name, type));
1548}
1549
1550
1551static void
1552add_app_version()
1553{
1554	field_t* fields  = (field_t*)alloc_mem(7 * sizeof(field_t));
1555	fields[0].type   = get_type("uint32");
1556	fields[0].name   = "major";
1557	fields[0].resize = 0;
1558	fields[0].data   = make_default(fields[0].type);
1559	fields[1].type   = get_type("uint32");
1560	fields[1].name   = "middle";
1561	fields[1].resize = 0;
1562	fields[1].data   = make_default(fields[1].type);
1563	fields[2].type   = get_type("uint32");
1564	fields[2].name   = "minor";
1565	fields[2].resize = 0;
1566	fields[2].data   = make_default(fields[2].type);
1567	fields[3].type   = get_type("uint32");
1568	fields[3].name   = "variety";
1569	fields[3].resize = 0;
1570	fields[3].data   = make_default(fields[3].type);
1571	fields[4].type   = get_type("uint32");
1572	fields[4].name   = "internal";
1573	fields[4].resize = 0;
1574	fields[4].data   = make_default(fields[4].type);
1575	fields[5].type   = get_type("string");
1576	fields[5].name   = "short_info";
1577	fields[5].resize = 64;
1578	fields[5].data   = make_data(fields[5].resize, fields[5].type);
1579	fields[6].type   = get_type("string");
1580	fields[6].name   = "long_info";
1581	fields[6].resize = 256;
1582	fields[6].data   = make_data(fields[6].resize, fields[6].type);
1583
1584	memset(fields[5].data.ptr, '\0', fields[5].data.size);
1585	memset(fields[6].data.ptr, '\0', fields[6].data.size);
1586
1587	type_t type;
1588	type.code     = 'APPV';
1589	type.name     = "app_version";
1590	type.fields   = fields;
1591	type.count    = 7;
1592	type.def_id   = 1;
1593	type.def_name = "BEOS:APP_VERSION";
1594
1595	type_table.insert(make_pair(type.name, type));
1596}
1597
1598
1599static void
1600add_png_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     = 'PNG ';
1610	type.name     = "png_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
1620static void
1621add_vector_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 = 0;
1627	fields[0].data   = make_data(fields[0].resize, fields[0].type);
1628
1629	type_t type;
1630	type.code     = 'VICN';
1631	type.name     = "vector_icon";
1632	type.fields   = fields;
1633	type.count    = 1;
1634	type.def_id   = 101;
1635	type.def_name = "BEOS:ICON";
1636
1637	type_table.insert(make_pair(type.name, type));
1638}
1639
1640
1641static void
1642add_large_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 = 1024;
1648	fields[0].data   = make_data(fields[0].resize, fields[0].type);
1649
1650	type_t type;
1651	type.code     = 'ICON';
1652	type.name     = "large_icon";
1653	type.fields   = fields;
1654	type.count    = 1;
1655	type.def_id   = 101;
1656	type.def_name = "BEOS:L:STD_ICON";
1657
1658	type_table.insert(make_pair(type.name, type));
1659}
1660
1661
1662static void
1663add_mini_icon()
1664{
1665	field_t* fields  = (field_t*)alloc_mem(1 * sizeof(field_t));
1666	fields[0].type   = get_type("raw");
1667	fields[0].name   = "icon";
1668	fields[0].resize = 256;
1669	fields[0].data   = make_data(fields[0].resize, fields[0].type);
1670
1671	type_t type;
1672	type.code     = 'MICN';
1673	type.name     = "mini_icon";
1674	type.fields   = fields;
1675	type.count    = 1;
1676	type.def_id   = 101;
1677	type.def_name = "BEOS:M:STD_ICON";
1678
1679	type_table.insert(make_pair(type.name, type));
1680}
1681
1682
1683static void
1684add_file_types()
1685{
1686	field_t* fields  = (field_t*)alloc_mem(1 * sizeof(field_t));
1687	fields[0].type   = get_type("message");
1688	fields[0].name   = "types";
1689	fields[0].resize = 0;
1690	fields[0].data   = make_default(fields[0].type);
1691
1692	type_t type;
1693	type.code     = 'MSGG';
1694	type.name     = "file_types";
1695	type.fields   = fields;
1696	type.count    = 1;
1697	type.def_id   = 1;
1698	type.def_name = "BEOS:FILE_TYPES";
1699
1700	type_table.insert(make_pair(type.name, type));
1701}
1702
1703
1704static void
1705add_define(const char* name, int32 value)
1706{
1707	define_t define;
1708	define.name  = name;
1709	define.value = value;
1710
1711	define_table.insert(make_pair(define.name, define));
1712}
1713
1714
1715void
1716init_parser()
1717{
1718	add_builtin_type(B_BOOL_TYPE,    "bool");
1719	add_builtin_type(B_INT8_TYPE,    "int8");
1720	add_builtin_type(B_UINT8_TYPE,   "uint8");
1721	add_builtin_type(B_INT16_TYPE,   "int16");
1722	add_builtin_type(B_UINT16_TYPE,  "uint16");
1723	add_builtin_type(B_INT32_TYPE,   "int32");
1724	add_builtin_type(B_UINT32_TYPE,  "uint32");
1725	add_builtin_type(B_SIZE_T_TYPE,  "size_t");
1726	add_builtin_type(B_SSIZE_T_TYPE, "ssize_t");
1727	add_builtin_type(B_TIME_TYPE,    "time_t");
1728	add_builtin_type(B_INT64_TYPE,   "int64");
1729	add_builtin_type(B_UINT64_TYPE,  "uint64");
1730	add_builtin_type(B_OFF_T_TYPE,   "off_t");
1731	add_builtin_type(B_FLOAT_TYPE,   "float");
1732	add_builtin_type(B_DOUBLE_TYPE,  "double");
1733	add_builtin_type(B_STRING_TYPE,  "string");
1734	add_builtin_type(B_RAW_TYPE,     "raw");
1735	add_builtin_type(B_RAW_TYPE,     "buffer");
1736	add_builtin_type(B_MESSAGE_TYPE, "message");
1737
1738	add_point_type();
1739	add_rect_type();
1740	add_rgb_color_type();
1741	add_app_signature_type();
1742	add_app_name_catalog_entry();
1743	add_app_flags();
1744	add_app_version();
1745	add_large_icon();
1746	add_mini_icon();
1747	add_vector_icon();
1748	add_png_icon();
1749	add_file_types();
1750
1751	add_define("B_SINGLE_LAUNCH",    0x0);
1752	add_define("B_MULTIPLE_LAUNCH",  0x1);
1753	add_define("B_EXCLUSIVE_LAUNCH", 0x2);
1754	add_define("B_BACKGROUND_APP",   0x4);
1755	add_define("B_ARGV_ONLY",        0x8);
1756
1757	add_define("B_APPV_DEVELOPMENT",   0x0);
1758	add_define("B_APPV_ALPHA",         0x1);
1759	add_define("B_APPV_BETA",          0x2);
1760	add_define("B_APPV_GAMMA",         0x3);
1761	add_define("B_APPV_GOLDEN_MASTER", 0x4);
1762	add_define("B_APPV_FINAL",         0x5);
1763}
1764
1765
1766void
1767clean_up_parser()
1768{
1769	// The symbol table entries have several malloc'ed objects associated
1770	// with them (such as their name). They were allocated with alloc_mem(),
1771	// so we don't need to free them here; compile.cpp already does that
1772	// when it cleans up. However, we do need to remove the entries from
1773	// the tables, otherwise they will still be around the next time we are
1774	// asked to compile something.
1775
1776#ifdef DEBUG
1777	// Note that in DEBUG mode, we _do_ free these items, so they don't show
1778	// up in the mem leak statistics. The names etc of builtin items are not
1779	// alloc_mem()'d but we still free_mem() them. Not entirely correct, but
1780	// it doesn't seem to hurt, and we only do it in DEBUG mode anyway.
1781
1782	for (sym_iter_t i = symbol_table.begin(); i != symbol_table.end(); ++i) {
1783		free_mem((void*) i->first);
1784	}
1785
1786	for (type_iter_t i = type_table.begin(); i != type_table.end(); ++i) {
1787		free_mem((void*) i->first);
1788		type_t type = i->second;
1789
1790		for (int32 t = 0; t < type.count; ++t) {
1791			free_mem((void*) type.fields[t].name);
1792			free_mem((void*) type.fields[t].data.ptr);
1793		}
1794		free_mem((void*) type.fields);
1795		free_mem((void*) type.name);
1796		free_mem((void*) type.def_name);
1797	}
1798#endif
1799
1800	symbol_table.clear();
1801	type_table.clear();
1802	define_table.clear();
1803}
1804
1805