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