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