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 #include <AppFileInfo.h> 25 #include <Mime.h> 26 #include <Resources.h> 27 #include <Roster.h> 28 #include <TypeConstants.h> 29 30 #include <ctype.h> 31 #include <errno.h> 32 #include <stdio.h> 33 #include <string.h> 34 #include <unistd.h> 35 36 #include "rdef.h" 37 #include "private.h" 38 39 // What we add to the front of enum symbols. 40 #define PREFIX "R_" 41 42 43 static FILE *sOutputFile; 44 static FILE *sHeaderFile; 45 46 // Level of indentation (how many tabs). 47 static int32 sTabs; 48 static bool sBraceOnNextLine = false; 49 50 51 static void write_generic_data(const char *name, type_code type, 52 const void *data, size_t length); 53 54 55 static void 56 indent() 57 { 58 for (int32 t = 0; t < sTabs; ++t) { 59 fprintf(sOutputFile, "\t"); 60 } 61 } 62 63 64 void 65 open_brace() 66 { 67 if (sBraceOnNextLine) { 68 fprintf(sOutputFile, "\n"); 69 indent(); 70 fprintf(sOutputFile, "{\n"); 71 } else 72 fprintf(sOutputFile, " {\n"); 73 74 ++sTabs; 75 } 76 77 78 void 79 close_brace() 80 { 81 --sTabs; 82 83 fprintf(sOutputFile, "\n"); 84 indent(); 85 fprintf(sOutputFile, "}"); 86 } 87 88 89 static bool 90 make_code(uint32 value, char *code) 91 { 92 code[0] = (value >> 24) & 0xFF; 93 if (isprint(code[0])) { 94 code[1] = (value >> 16) & 0xFF; 95 if (isprint(code[1])) { 96 code[2] = (value >> 8) & 0xFF; 97 if (isprint(code[2])) { 98 code[3] = value & 0xFF; 99 if (isprint(code[3])) { 100 code[4] = '\0'; 101 return true; 102 } 103 } 104 } 105 } 106 107 return false; 108 } 109 110 111 static void 112 write_code(uint32 value) 113 { 114 char code[5]; 115 if (make_code(value, code)) 116 fprintf(sOutputFile, "'%s'", code); 117 else 118 fprintf(sOutputFile, "%" B_PRIu32, value); 119 } 120 121 122 static void 123 write_field_name(const char *name) 124 { 125 // We call this from the write_xxx() functions to properly align a 126 // field's type code (which goes to the left of the field name) and 127 // the field's data (to right of the name). If we are not currently 128 // writing a field (but the entire resource), name is NULL. 129 130 if (name != NULL) 131 fprintf(sOutputFile, "\"%s\" = ", name); 132 } 133 134 135 static bool 136 is_ident(const char *name) 137 { 138 if (name[0] != '_' && !isalpha(name[0])) 139 return false; 140 141 for (size_t t = 1; t < strlen(name); ++t) { 142 if (name[t] != '_' && !isalnum(name[t])) 143 return false; 144 } 145 146 return true; 147 } 148 149 150 static bool 151 has_prefix(const char *name) 152 { 153 size_t name_len = strlen(name); 154 size_t prefix_len = strlen(PREFIX); 155 156 if (name_len > prefix_len) { 157 if (strncmp(name, PREFIX, prefix_len) == 0) 158 return true; 159 } 160 161 return false; 162 } 163 164 165 static bool 166 is_string(const void *data, size_t length) 167 { 168 // We consider the buffer a string if it contains only human readable 169 // characters. The buffer should also end with a '\0'. Although the 170 // compiler allows string literals to contain embedded '\0' chars as 171 // well, we don't allow them here (because they may cause false hits). 172 173 if (length == 0) 174 return false; 175 176 char *ptr = (char *)data; 177 178 for (size_t t = 0; t < length - 1; ++t) { 179 if (!isprint(*ptr++)) 180 return false; 181 } 182 183 return (*ptr == '\0'); 184 } 185 186 187 static void 188 write_rsrc(type_code type, int32 id, const char *name) 189 { 190 if (name[0] == '\0') { 191 fprintf(sOutputFile, "resource(%" B_PRId32 ") ", id); 192 } else if ((flags & RDEF_AUTO_NAMES) != 0&& is_ident(name)) { 193 char code[5]; 194 if (has_prefix(name)) { 195 fprintf(sOutputFile, "resource(%s) ", name); 196 fprintf(sHeaderFile, "\t%s = %" B_PRId32 ",\n", name, id); 197 } else if (make_code(type, code)) { 198 fprintf(sOutputFile, "resource(%s%s_%s) ", PREFIX, code, name); 199 fprintf(sHeaderFile, "\t%s%s_%s = %" B_PRId32 ",\n", PREFIX, code, 200 name, id); 201 } else { 202 fprintf(sOutputFile, "resource(%s%" B_PRIu32 "_%s) ", PREFIX, 203 (uint32)type, name); 204 fprintf(sHeaderFile, "\t%s%" B_PRIu32 "_%s = %" B_PRId32 ",\n", 205 PREFIX, (uint32)type, name, id); 206 } 207 } else { 208 fprintf(sOutputFile, "resource(%" B_PRId32 ", \"%s\") ", id, name); 209 } 210 } 211 212 213 // #pragma mark - generic types 214 215 216 static uint8 * 217 write_raw_line(uint8 *ptr, uint8 *end, size_t bytesPerLine) 218 { 219 uint32 count = 0; 220 221 fprintf(sOutputFile, "$\""); 222 223 while (ptr < end && count < bytesPerLine) { 224 fprintf(sOutputFile, "%02X", *ptr++); 225 ++count; 226 } 227 228 fprintf(sOutputFile, "\""); 229 230 return ptr; 231 } 232 233 234 static void 235 write_raw(const char *name, type_code type, const void *data, 236 size_t length, size_t bytesPerLine = 32) 237 { 238 uint8 *ptr = (uint8 *)data; 239 uint8 *end = ptr + length; 240 241 if (length > bytesPerLine) { 242 if (type != B_RAW_TYPE) { 243 fprintf(sOutputFile, "#"); 244 write_code(type); 245 fprintf(sOutputFile, " "); 246 } 247 248 write_field_name(name); 249 fprintf(sOutputFile, "array"); 250 251 open_brace(); 252 253 int32 item = 0; 254 while (ptr < end) { 255 if (item++ > 0) 256 fprintf(sOutputFile, "\n"); 257 258 indent(); 259 ptr = write_raw_line(ptr, end, bytesPerLine); 260 } 261 262 close_brace(); 263 } else { 264 if (type != B_RAW_TYPE) { 265 fprintf(sOutputFile, "#"); 266 write_code(type); 267 fprintf(sOutputFile, " "); 268 } 269 270 write_field_name(name); 271 write_raw_line(ptr, end, bytesPerLine); 272 } 273 } 274 275 276 static void 277 write_bool(const char *name, const void *data, size_t length) 278 { 279 if (length != sizeof(bool)) { 280 write_raw(name, B_BOOL_TYPE, data, length); 281 } else { 282 write_field_name(name); 283 fprintf(sOutputFile, "%s", *(bool *)data ? "true" : "false"); 284 } 285 } 286 287 288 static void 289 write_int8(const char *name, const void *data, size_t length) 290 { 291 if (length != sizeof(int8)) { 292 write_raw(name, B_INT8_TYPE, data, length); 293 } else { 294 write_field_name(name); 295 fprintf(sOutputFile, "(int8)%d", *(int8 *)data); 296 } 297 } 298 299 300 static void 301 write_int16(const char *name, const void *data, size_t length) 302 { 303 if (length != sizeof(int16)) { 304 write_raw(name, B_INT16_TYPE, data, length); 305 } else { 306 write_field_name(name); 307 fprintf(sOutputFile, "(int16)%d", *(int16 *)data); 308 } 309 } 310 311 312 static void 313 write_int32(const char *name, const void *data, size_t length) 314 { 315 if (length != sizeof(int32)) { 316 write_raw(name, B_INT32_TYPE, data, length); 317 } else { 318 write_field_name(name); 319 fprintf(sOutputFile, "%" B_PRId32, *(int32 *)data); 320 } 321 } 322 323 324 static void 325 write_int64(const char *name, const void *data, size_t length) 326 { 327 if (length != sizeof(int64)) { 328 write_raw(name, B_INT64_TYPE, data, length); 329 } else { 330 write_field_name(name); 331 fprintf(sOutputFile, "(int64)%" B_PRId64, *(int64 *)data); 332 } 333 } 334 335 336 static void 337 write_uint8(const char *name, const void *data, size_t length) 338 { 339 if (length != sizeof(uint8)) { 340 write_raw(name, B_UINT8_TYPE, data, length); 341 } else { 342 write_field_name(name); 343 fprintf(sOutputFile, "(uint8)%u", *(uint8 *)data); 344 } 345 } 346 347 348 static void 349 write_uint16(const char *name, const void *data, size_t length) 350 { 351 if (length != sizeof(uint16)) { 352 write_raw(name, B_UINT16_TYPE, data, length); 353 } else { 354 write_field_name(name); 355 fprintf(sOutputFile, "(uint16)%u", *(uint16 *)data); 356 } 357 } 358 359 360 static void 361 write_uint32(const char *name, const void *data, size_t length) 362 { 363 if (length != sizeof(uint32)) { 364 write_raw(name, B_UINT32_TYPE, data, length); 365 } else { 366 write_field_name(name); 367 fprintf(sOutputFile, "(uint32)%" B_PRIu32, *(uint32 *)data); 368 } 369 } 370 371 372 static void 373 write_uint64(const char *name, const void *data, size_t length) 374 { 375 if (length != sizeof(uint64)) { 376 write_raw(name, B_UINT64_TYPE, data, length); 377 } else { 378 write_field_name(name); 379 fprintf(sOutputFile, "(uint64)%" B_PRIu64, *(uint64 *)data); 380 } 381 } 382 383 384 static void 385 write_float(const char *name, const void *data, size_t length) 386 { 387 if (length != sizeof(float)) { 388 write_raw(name, B_FLOAT_TYPE, data, length); 389 } else { 390 write_field_name(name); 391 fprintf(sOutputFile, "%#g", *(float *)data); 392 } 393 } 394 395 396 static void 397 write_double(const char *name, const void *data, size_t length) 398 { 399 if (length != sizeof(double)) { 400 write_raw(name, B_DOUBLE_TYPE, data, length); 401 } else { 402 write_field_name(name); 403 fprintf(sOutputFile, "(double)%#g", *(double *)data); 404 } 405 } 406 407 408 static void 409 write_size(const char *name, const void *data, size_t length) 410 { 411 if (length != sizeof(size_t)) { 412 write_raw(name, B_SIZE_T_TYPE, data, length); 413 } else { 414 write_field_name(name); 415 fprintf(sOutputFile, "(size_t)%lu", (unsigned long)*(size_t *)data); 416 } 417 } 418 419 420 static void 421 write_ssize(const char *name, const void *data, size_t length) 422 { 423 if (length != sizeof(ssize_t)) { 424 write_raw(name, B_SSIZE_T_TYPE, data, length); 425 } else { 426 write_field_name(name); 427 fprintf(sOutputFile, "(ssize_t)%ld", (long)*(ssize_t *)data); 428 } 429 } 430 431 432 static void 433 write_off(const char *name, const void *data, size_t length) 434 { 435 if (length != sizeof(off_t)) { 436 write_raw(name, B_OFF_T_TYPE, data, length); 437 } else { 438 write_field_name(name); 439 fprintf(sOutputFile, "(off_t)%" B_PRIdOFF, *(off_t *)data); 440 } 441 } 442 443 444 static void 445 write_time(const char *name, const void *data, size_t length) 446 { 447 if (length != sizeof(time_t)) { 448 write_raw(name, B_TIME_TYPE, data, length); 449 } else { 450 write_field_name(name); 451 fprintf(sOutputFile, "(time_t)%ld", (long)*(time_t *)data); 452 } 453 } 454 455 456 static void 457 write_point(const char *name, const void *data) 458 { 459 ///TODO: using built-in type table 460 461 write_field_name(name); 462 float *f = (float *)data; 463 fprintf(sOutputFile, "point { %#g, %#g }", f[0], f[1]); 464 } 465 466 467 static void 468 write_rect(const char *name, const void *data) 469 { 470 ///TODO: using built-in type table 471 472 write_field_name(name); 473 float *f = (float *)data; 474 fprintf(sOutputFile, "rect { %#g, %#g, %#g, %#g }", f[0], f[1], f[2], f[3]); 475 } 476 477 478 static void 479 write_rgb(const char *name, const void *data) 480 { 481 ///TODO: using built-in type table 482 483 write_field_name(name); 484 uint8 *b = (uint8 *)data; 485 486 fprintf(sOutputFile, "rgb_color { 0x%02X, 0x%02X, 0x%02X, 0x%02X }", 487 b[0], b[1], b[2], b[3]); 488 } 489 490 491 static const char * 492 write_string_line(const char *ptr, const char *end, size_t charsPerLine) 493 { 494 uint32 count = 0; 495 bool end_of_item = false; 496 497 fprintf(sOutputFile, "\""); 498 499 while (ptr < end && count < charsPerLine && !end_of_item) { 500 char c = *ptr++; 501 502 switch (c) { 503 case '\b': fprintf(sOutputFile, "\\b"); count += 2; break; 504 case '\f': fprintf(sOutputFile, "\\f"); count += 2; break; 505 case '\n': fprintf(sOutputFile, "\\n"); count += 2; break; 506 case '\r': fprintf(sOutputFile, "\\r"); count += 2; break; 507 case '\t': fprintf(sOutputFile, "\\t"); count += 2; break; 508 case '\v': fprintf(sOutputFile, "\\v"); count += 2; break; 509 case '\"': fprintf(sOutputFile, "\\\""); count += 2; break; 510 case '\\': fprintf(sOutputFile, "\\\\"); count += 2; break; 511 512 case '\0': end_of_item = true; break; 513 514 default: 515 { 516 if ((uint8)c < 128 && !isprint(c)) { 517 fprintf(sOutputFile, "\\0x%02X", (uint8)c); count += 5; 518 } else { 519 fprintf(sOutputFile, "%c", c); ++count; 520 } 521 } 522 } 523 } 524 525 fprintf(sOutputFile, "\""); 526 527 if (end_of_item && ptr < end) 528 fprintf(sOutputFile, ","); 529 530 return ptr; 531 } 532 533 534 static void 535 write_string(const char *name, type_code type, 536 const void *data, size_t length) 537 { 538 const char *ptr = (const char *)data; 539 const char *end = ptr + length; 540 size_t charsPerLine = 64; 541 542 // We write an "array" resource if the string has more than 64 543 // characters. A string resource may also be comprised of multiple 544 // substrings, each terminated by a '\0' char. In that case, we 545 // must write an "array" resource as well. Sneaky as we are, we use 546 // strlen() to check for that, because it also looks for a '\0'. 547 548 if (length > charsPerLine || strlen(ptr) < length - 1) { 549 fprintf(sOutputFile, "#"); 550 write_code(type); 551 fprintf(sOutputFile, " array"); 552 553 if (name != NULL) { 554 fprintf(sOutputFile, " "); 555 write_field_name(name); 556 fprintf(sOutputFile, " array"); 557 } 558 559 open_brace(); 560 561 int32 item = 0; 562 while (ptr < end) { 563 if (item++ > 0) 564 fprintf(sOutputFile, "\n"); 565 566 indent(); 567 ptr = write_string_line(ptr, end, charsPerLine); 568 } 569 570 close_brace(); 571 } else { 572 if (type != B_STRING_TYPE) { 573 fprintf(sOutputFile, "#"); 574 write_code(type); 575 fprintf(sOutputFile, " "); 576 } 577 578 write_field_name(name); 579 write_string_line(ptr, end, charsPerLine); 580 } 581 } 582 583 584 static void 585 write_fields(BMessage &msg) 586 { 587 int32 t = 0; 588 int32 item = 0; 589 590 #ifdef B_BEOS_VERSION_DANO 591 const char *name; 592 #else 593 char *name; 594 #endif 595 type_code type; 596 int32 count; 597 const void *data; 598 size_t length; 599 600 open_brace(); 601 602 while (msg.GetInfo(B_ANY_TYPE, t, &name, &type, &count) == B_OK) { 603 for (int32 k = 0; k < count; ++k) { 604 if (msg.FindData(name, type, k, &data, (ssize_t*) &length) == B_OK) { 605 if (item++ > 0) 606 fprintf(sOutputFile, ",\n"); 607 608 indent(); 609 write_generic_data(name, type, data, length); 610 } 611 } 612 613 ++t; 614 } 615 616 close_brace(); 617 } 618 619 620 static void 621 write_message(const char *name, BMessage &msg, type_code type) 622 { 623 if (type != B_MESSAGE_TYPE) { 624 fprintf(sOutputFile, "#"); 625 write_code(type); 626 fprintf(sOutputFile, " "); 627 } 628 629 write_field_name(name); 630 631 const char *class_; 632 if (msg.FindString("class", &class_) == B_OK) { 633 fprintf(sOutputFile, "archive"); 634 635 const char *add_on; 636 if (msg.FindString("add_on", &add_on) == B_OK) { 637 fprintf(sOutputFile, "(\"%s\"", add_on); 638 if (msg.what != 0) { 639 fprintf(sOutputFile, ", "); 640 write_code(msg.what); 641 } 642 fprintf(sOutputFile, ")"); 643 644 msg.RemoveName("add_on"); 645 } else if (msg.what != 0) { 646 fprintf(sOutputFile, "(, "); 647 write_code(msg.what); 648 fprintf(sOutputFile, ")"); 649 } 650 651 fprintf(sOutputFile, " %s", class_); 652 msg.RemoveName("class"); 653 } else if (msg.what == 0) { 654 fprintf(sOutputFile, "message"); 655 } else { 656 fprintf(sOutputFile, "message("); 657 write_code(msg.what); 658 fprintf(sOutputFile, ")"); 659 } 660 661 if (msg.CountNames(B_ANY_TYPE) > 0) 662 write_fields(msg); 663 } 664 665 666 static void 667 write_other(const char *name, type_code type, 668 const void *data, size_t length) 669 { 670 BMessage msg; 671 if (msg.Unflatten((const char *)data) == B_OK) 672 write_message(name, msg, type); 673 else if (is_string(data, length)) 674 write_string(name, type, data, length); 675 else 676 write_raw(name, type, data, length); 677 } 678 679 680 // #pragma mark - special types 681 682 683 static void 684 write_app_signature(const void *data, size_t length) 685 { 686 fprintf(sOutputFile, "resource app_signature "); 687 write_string_line((const char *)data, (const char *)data + length, length * 2); 688 } 689 690 691 static void 692 write_app_flags(const void *data, size_t length) 693 { 694 fprintf(sOutputFile, "resource app_flags "); 695 696 uint32 flags = *(uint32 *)data; 697 switch (flags & B_LAUNCH_MASK) { 698 case B_SINGLE_LAUNCH: 699 fputs("B_SINGLE_LAUNCH", sOutputFile); 700 break; 701 case B_MULTIPLE_LAUNCH: 702 fputs("B_MULTIPLE_LAUNCH", sOutputFile); 703 break; 704 case B_EXCLUSIVE_LAUNCH: 705 fputs("B_EXCLUSIVE_LAUNCH", sOutputFile); 706 break; 707 } 708 709 if (flags & B_BACKGROUND_APP) 710 fputs(" | B_BACKGROUND_APP", sOutputFile); 711 if (flags & B_ARGV_ONLY) 712 fputs(" | B_ARGV_ONLY", sOutputFile); 713 } 714 715 716 static void 717 write_app_icon(uint32 which, const void *data, size_t length) 718 { 719 int32 lineWidth = 32; 720 const char* type = ""; 721 switch (which) { 722 case B_MINI_ICON: 723 type = "mini"; 724 lineWidth = 16; 725 break; 726 case B_LARGE_ICON: 727 type = "large"; 728 break; 729 case 'VICN': 730 type = "vector"; 731 break; 732 case 'PNG ': 733 type = "png"; 734 break; 735 default: 736 fprintf(stderr, "write_app_icon() called with invalid type!\n"); 737 break; 738 } 739 fprintf(sOutputFile, "resource %s_icon ", type); 740 write_raw(NULL, B_RAW_TYPE, data, length, lineWidth); 741 } 742 743 744 static void 745 write_app_file_types(const void *data, size_t length) 746 { 747 fputs("resource file_types ", sOutputFile); 748 write_other(NULL, B_MESSAGE_TYPE, data, length); 749 } 750 751 752 static void 753 write_app_version(const void *data, size_t length) 754 { 755 const version_info *version = (const version_info *)data; 756 //const version_info *systemVersion = version + 1; 757 758 fputs("resource app_version", sOutputFile); 759 open_brace(); 760 761 fprintf(sOutputFile, "\tmajor = %" B_PRIu32 ",\n" 762 "\tmiddle = %" B_PRIu32 ",\n" 763 "\tminor = %" B_PRIu32 ",\n\n", version->major, version->middle, 764 version->minor); 765 766 const char *variety = "B_APPV_DEVELOPMENT"; 767 switch (version->variety) { 768 case 1: 769 variety = "B_APPV_ALPHA"; 770 break; 771 case 2: 772 variety = "B_APPV_BETA"; 773 break; 774 case 3: 775 variety = "B_APPV_GAMMA"; 776 break; 777 case 4: 778 variety = "B_APPV_GOLDEN_MASTER"; 779 break; 780 case 5: 781 variety = "B_APPV_FINAL"; 782 break; 783 } 784 fprintf(sOutputFile, "\tvariety = %s,\n" 785 "\tinternal = %" B_PRIu32 ",\n\n", variety, version->internal); 786 787 fprintf(sOutputFile, "\tshort_info = "); 788 write_string(NULL, B_STRING_TYPE, version->short_info, strlen(version->short_info)); 789 790 fprintf(sOutputFile, ",\n\tlong_info = "); 791 write_string(NULL, B_STRING_TYPE, version->long_info, strlen(version->long_info)); 792 793 close_brace(); 794 } 795 796 797 // #pragma mark - file examination 798 799 800 static void 801 write_generic_data(const char *name, type_code type, 802 const void *data, size_t length) 803 { 804 switch (type) { 805 case B_BOOL_TYPE: write_bool(name, data, length); break; 806 case B_INT8_TYPE: write_int8(name, data, length); break; 807 case B_INT16_TYPE: write_int16(name, data, length); break; 808 case B_INT32_TYPE: write_int32(name, data, length); break; 809 case B_INT64_TYPE: write_int64(name, data, length); break; 810 case B_UINT8_TYPE: write_uint8(name, data, length); break; 811 case B_UINT16_TYPE: write_uint16(name, data, length); break; 812 case B_UINT32_TYPE: write_uint32(name, data, length); break; 813 case B_UINT64_TYPE: write_uint64(name, data, length); break; 814 case B_FLOAT_TYPE: write_float(name, data, length); break; 815 case B_DOUBLE_TYPE: write_double(name, data, length); break; 816 case B_SIZE_T_TYPE: write_size(name, data, length); break; 817 case B_SSIZE_T_TYPE: write_ssize(name, data, length); break; 818 case B_OFF_T_TYPE: write_off(name, data, length); break; 819 case B_TIME_TYPE: write_time(name, data, length); break; 820 821 case B_POINT_TYPE: write_point(name, data); break; 822 case B_RECT_TYPE: write_rect(name, data); break; 823 case B_RGB_COLOR_TYPE: write_rgb(name, data); break; 824 825 case B_MIME_STRING_TYPE: 826 case B_STRING_TYPE: 827 write_string(name, type, data, length); 828 break; 829 830 case 'MICN': 831 write_raw(name, type, data, length, 16); 832 break; 833 case B_POINTER_TYPE: 834 case 'ICON': 835 case 'VICN': 836 write_raw(name, type, data, length); 837 break; 838 839 default: 840 write_other(name, type, data, length); 841 break; 842 } 843 } 844 845 846 static void 847 write_data(int32 id, const char *name, type_code type, 848 const void *data, size_t length) 849 { 850 // check for special types 851 852 switch (type) { 853 case B_MIME_STRING_TYPE: 854 if (!strcmp(name, "BEOS:APP_SIG")) { 855 write_app_signature(data, length); 856 return; 857 } 858 break; 859 860 case 'VICN': 861 if (!strcmp(name, "BEOS:ICON")) { 862 write_app_icon('VICN', data, length); 863 return; 864 } 865 break; 866 867 case 'PNG ': 868 if (!strcmp(name, "BEOS:ICON")) { 869 write_app_icon('PNG ', data, length); 870 return; 871 } 872 break; 873 874 case 'MICN': 875 if (!strcmp(name, "BEOS:M:STD_ICON")) { 876 write_app_icon(B_MINI_ICON, data, length); 877 return; 878 } 879 break; 880 881 case 'ICON': 882 if (!strcmp(name, "BEOS:L:STD_ICON")) { 883 write_app_icon(B_LARGE_ICON, data, length); 884 return; 885 } 886 break; 887 888 case B_MESSAGE_TYPE: 889 if (!strcmp(name, "BEOS:FILE_TYPES")) { 890 write_app_file_types(data, length); 891 return; 892 } 893 break; 894 895 case 'APPF': 896 if (!strcmp(name, "BEOS:APP_FLAGS") && length == 4) { 897 write_app_flags(data, length); 898 return; 899 } 900 break; 901 902 case 'APPV': 903 if (!strcmp(name, "BEOS:APP_VERSION") && length == sizeof(version_info) * 2) { 904 write_app_version(data, length); 905 return; 906 } 907 break; 908 } 909 910 // write generic types 911 912 write_rsrc(type, id, name); 913 write_generic_data(NULL, type, data, length); 914 } 915 916 917 static void 918 examine_file(char *fileName) 919 { 920 BFile file(fileName, B_READ_ONLY); 921 if (file.InitCheck() != B_OK) { 922 strcpy(rdef_err_file, fileName); 923 rdef_err = RDEF_FILE_NOT_FOUND; 924 return; 925 } 926 927 BResources res; 928 if (res.SetTo(&file) != B_OK) { 929 strcpy(rdef_err_file, fileName); 930 rdef_err = RDEF_NO_RESOURCES; 931 return; 932 } 933 934 int32 t = 0; 935 type_code type; 936 int32 id; 937 const char *name; 938 size_t length; 939 const void *data; 940 941 while (res.GetResourceInfo(t, &type, &id, &name, &length)) { 942 sTabs = 0; 943 944 data = res.LoadResource(type, id, NULL); 945 if (data != NULL) { 946 fprintf(sOutputFile, "\n"); 947 write_data(id, name, type, data, length); 948 fprintf(sOutputFile, ";\n"); 949 } 950 951 ++t; 952 } 953 } 954 955 956 static status_t 957 open_output_files(const char *fileName, const char *headerName) 958 { 959 sOutputFile = fopen(fileName, "w"); 960 if (sOutputFile == NULL) { 961 strcpy(rdef_err_msg, strerror(errno)); 962 strcpy(rdef_err_file, fileName); 963 return RDEF_WRITE_ERR; 964 } 965 966 if (flags & RDEF_AUTO_NAMES) { 967 sHeaderFile = fopen(headerName, "w"); 968 if (sHeaderFile == NULL) { 969 strcpy(rdef_err_msg, strerror(errno)); 970 strcpy(rdef_err_file, headerName); 971 fclose(sOutputFile); 972 return RDEF_WRITE_ERR; 973 } 974 975 fprintf(sOutputFile, "\n#include \"%s\"\n", headerName); 976 977 if (sBraceOnNextLine) 978 fprintf(sHeaderFile, "\nenum\n{\n"); 979 else 980 fprintf(sHeaderFile, "\nenum {\n"); 981 } 982 983 return B_OK; 984 } 985 986 987 static void 988 close_output_files(const char *fileName, const char *headerName) 989 { 990 if (flags & RDEF_AUTO_NAMES) { 991 fprintf(sHeaderFile, "};\n"); 992 fclose(sHeaderFile); 993 994 if (rdef_err != B_OK) 995 unlink(headerName); 996 } 997 998 fclose(sOutputFile); 999 1000 if (rdef_err != B_OK) 1001 unlink(fileName); 1002 } 1003 1004 1005 status_t 1006 rdef_decompile(const char *fileName) 1007 { 1008 clear_error(); 1009 1010 if (fileName == NULL || fileName[0] == '\0') { 1011 rdef_err = B_BAD_VALUE; 1012 return rdef_err; 1013 } 1014 1015 char headerName[B_PATH_NAME_LENGTH + 1]; 1016 if ((flags & RDEF_AUTO_NAMES) != 0) 1017 sprintf(headerName, "%s.h", fileName); 1018 1019 rdef_err = open_output_files(fileName, headerName); 1020 if (rdef_err != B_OK) 1021 return rdef_err; 1022 1023 for (ptr_iter_t i = input_files.begin(); 1024 (i != input_files.end()) && (rdef_err == B_OK); ++i) { 1025 examine_file((char *)*i); 1026 } 1027 1028 close_output_files(fileName, headerName); 1029 return rdef_err; 1030 } 1031 1032