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
operatorident_compare_t44 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
add_symbol(const char * name,int32 id)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
get_symbol(const char * name)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
add_builtin_type(type_code code,const char * name)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
add_user_type(res_id_t id,type_code code,const char * name,list_t list)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
is_builtin_type(type_t type)575 is_builtin_type(type_t type)
576 {
577 return type.count == 0;
578 }
579
580
581 static bool
same_type(type_t type1,type_t type2)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
get_type(const char * name)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
is_type(const char * name)601 is_type(const char* name)
602 {
603 return type_table.find(name) != type_table.end();
604 }
605
606
607 define_t
get_define(const char * name)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
make_data(size_t size,type_t type)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
make_bool(bool b)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
make_int(uint64 i)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
make_float(double f)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
import_data(char * filename)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
resize_data(data_t data,size_t newSize)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*
make_msg(list_t list)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
flatten_msg(BMessage * msg)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
make_default(type_t type)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*
fill_slots(type_t type,list_t list)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
convert_slots(type_t type,data_t * slots)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
make_type(char * name,list_t list)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
make_field_list(field_t field)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
concat_field_list(list_t list,field_t field)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
make_data_list(data_t data)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
concat_data_list(list_t list,data_t data)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
concat_data(data_t data1,data_t data2)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
cast_to_uint8(type_t new_type,data_t data)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
cast_to_uint16(type_t new_type,data_t data)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
cast_to_uint32(type_t new_type,data_t data)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
cast_to_uint64(type_t new_type,data_t data)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
cast_to_float(type_t new_type,data_t data)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
cast_to_double(type_t new_type,data_t data)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
cast(type_t newType,data_t data)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
unary_expr(data_t data,char oper)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
binary_expr(data_t data1,data_t data2,char oper)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
add_resource(res_id_t id,type_code code,data_t data)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
add_point_type()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
add_rect_type()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
add_rgb_color_type()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
add_app_signature_type()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
add_app_name_catalog_entry()1510 add_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
1530 static void
add_app_flags()1531 add_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
1551 static void
add_app_version()1552 add_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
1599 static void
add_png_icon()1600 add_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
1620 static void
add_vector_icon()1621 add_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
1641 static void
add_large_icon()1642 add_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
1662 static void
add_mini_icon()1663 add_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
1683 static void
add_file_types()1684 add_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
1704 static void
add_define(const char * name,int32 value)1705 add_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
1715 void
init_parser()1716 init_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
1766 void
clean_up_parser()1767 clean_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