Make UEFI boot-platform build again
[haiku.git] / src / bin / rc / decompile.cpp
blob68a6de5349d672d9b34f13a286762b80d460c174
1 /*
2 * Copyright (c) 2003 Matthijs Hollemans
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
24 #include <AppFileInfo.h>
25 #include <Mime.h>
26 #include <Resources.h>
27 #include <Roster.h>
28 #include <TypeConstants.h>
30 #include <ctype.h>
31 #include <errno.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <unistd.h>
36 #include "rdef.h"
37 #include "private.h"
39 // What we add to the front of enum symbols.
40 #define PREFIX "R_"
43 static FILE *sOutputFile;
44 static FILE *sHeaderFile;
46 // Level of indentation (how many tabs).
47 static int32 sTabs;
48 static bool sBraceOnNextLine = false;
51 static void write_generic_data(const char *name, type_code type,
52 const void *data, size_t length);
55 static void
56 indent()
58 for (int32 t = 0; t < sTabs; ++t) {
59 fprintf(sOutputFile, "\t");
64 void
65 open_brace()
67 if (sBraceOnNextLine) {
68 fprintf(sOutputFile, "\n");
69 indent();
70 fprintf(sOutputFile, "{\n");
71 } else
72 fprintf(sOutputFile, " {\n");
74 ++sTabs;
78 void
79 close_brace()
81 --sTabs;
83 fprintf(sOutputFile, "\n");
84 indent();
85 fprintf(sOutputFile, "}");
89 static bool
90 make_code(uint32 value, char *code)
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;
107 return false;
111 static void
112 write_code(uint32 value)
114 char code[5];
115 if (make_code(value, code))
116 fprintf(sOutputFile, "'%s'", code);
117 else
118 fprintf(sOutputFile, "%" B_PRIu32, value);
122 static void
123 write_field_name(const char *name)
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.
130 if (name != NULL)
131 fprintf(sOutputFile, "\"%s\" = ", name);
135 static bool
136 is_ident(const char *name)
138 if (name[0] != '_' && !isalpha(name[0]))
139 return false;
141 for (size_t t = 1; t < strlen(name); ++t) {
142 if (name[t] != '_' && !isalnum(name[t]))
143 return false;
146 return true;
150 static bool
151 has_prefix(const char *name)
153 size_t name_len = strlen(name);
154 size_t prefix_len = strlen(PREFIX);
156 if (name_len > prefix_len) {
157 if (strncmp(name, PREFIX, prefix_len) == 0)
158 return true;
161 return false;
165 static bool
166 is_string(const void *data, size_t length)
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).
173 if (length == 0)
174 return false;
176 char *ptr = (char *)data;
178 for (size_t t = 0; t < length - 1; ++t) {
179 if (!isprint(*ptr++))
180 return false;
183 return (*ptr == '\0');
187 static void
188 write_rsrc(type_code type, int32 id, const char *name)
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);
207 } else {
208 fprintf(sOutputFile, "resource(%" B_PRId32 ", \"%s\") ", id, name);
213 // #pragma mark - generic types
216 static uint8 *
217 write_raw_line(uint8 *ptr, uint8 *end, size_t bytesPerLine)
219 uint32 count = 0;
221 fprintf(sOutputFile, "$\"");
223 while (ptr < end && count < bytesPerLine) {
224 fprintf(sOutputFile, "%02X", *ptr++);
225 ++count;
228 fprintf(sOutputFile, "\"");
230 return ptr;
234 static void
235 write_raw(const char *name, type_code type, const void *data,
236 size_t length, size_t bytesPerLine = 32)
238 uint8 *ptr = (uint8 *)data;
239 uint8 *end = ptr + length;
241 if (length > bytesPerLine) {
242 if (type != B_RAW_TYPE) {
243 fprintf(sOutputFile, "#");
244 write_code(type);
245 fprintf(sOutputFile, " ");
248 write_field_name(name);
249 fprintf(sOutputFile, "array");
251 open_brace();
253 int32 item = 0;
254 while (ptr < end) {
255 if (item++ > 0)
256 fprintf(sOutputFile, "\n");
258 indent();
259 ptr = write_raw_line(ptr, end, bytesPerLine);
262 close_brace();
263 } else {
264 if (type != B_RAW_TYPE) {
265 fprintf(sOutputFile, "#");
266 write_code(type);
267 fprintf(sOutputFile, " ");
270 write_field_name(name);
271 write_raw_line(ptr, end, bytesPerLine);
276 static void
277 write_bool(const char *name, const void *data, size_t length)
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");
288 static void
289 write_int8(const char *name, const void *data, size_t length)
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);
300 static void
301 write_int16(const char *name, const void *data, size_t length)
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);
312 static void
313 write_int32(const char *name, const void *data, size_t length)
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);
324 static void
325 write_int64(const char *name, const void *data, size_t length)
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);
336 static void
337 write_uint8(const char *name, const void *data, size_t length)
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);
348 static void
349 write_uint16(const char *name, const void *data, size_t length)
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);
360 static void
361 write_uint32(const char *name, const void *data, size_t length)
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);
372 static void
373 write_uint64(const char *name, const void *data, size_t length)
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);
384 static void
385 write_float(const char *name, const void *data, size_t length)
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);
396 static void
397 write_double(const char *name, const void *data, size_t length)
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);
408 static void
409 write_size(const char *name, const void *data, size_t length)
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);
420 static void
421 write_ssize(const char *name, const void *data, size_t length)
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);
432 static void
433 write_off(const char *name, const void *data, size_t length)
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);
444 static void
445 write_time(const char *name, const void *data, size_t length)
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);
456 static void
457 write_point(const char *name, const void *data)
459 ///TODO: using built-in type table
461 write_field_name(name);
462 float *f = (float *)data;
463 fprintf(sOutputFile, "point { %#g, %#g }", f[0], f[1]);
467 static void
468 write_rect(const char *name, const void *data)
470 ///TODO: using built-in type table
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]);
478 static void
479 write_rgb(const char *name, const void *data)
481 ///TODO: using built-in type table
483 write_field_name(name);
484 uint8 *b = (uint8 *)data;
486 fprintf(sOutputFile, "rgb_color { 0x%02X, 0x%02X, 0x%02X, 0x%02X }",
487 b[0], b[1], b[2], b[3]);
491 static const char *
492 write_string_line(const char *ptr, const char *end, size_t charsPerLine)
494 uint32 count = 0;
495 bool end_of_item = false;
497 fprintf(sOutputFile, "\"");
499 while (ptr < end && count < charsPerLine && !end_of_item) {
500 char c = *ptr++;
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;
512 case '\0': end_of_item = true; break;
514 default:
516 if ((uint8)c < 128 && !isprint(c)) {
517 fprintf(sOutputFile, "\\0x%02X", (uint8)c); count += 5;
518 } else {
519 fprintf(sOutputFile, "%c", c); ++count;
525 fprintf(sOutputFile, "\"");
527 if (end_of_item && ptr < end)
528 fprintf(sOutputFile, ",");
530 return ptr;
534 static void
535 write_string(const char *name, type_code type,
536 const void *data, size_t length)
538 const char *ptr = (const char *)data;
539 const char *end = ptr + length;
540 size_t charsPerLine = 64;
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'.
548 if (length > charsPerLine || strlen(ptr) < length - 1) {
549 fprintf(sOutputFile, "#");
550 write_code(type);
551 fprintf(sOutputFile, " array");
553 if (name != NULL) {
554 fprintf(sOutputFile, " ");
555 write_field_name(name);
556 fprintf(sOutputFile, " array");
559 open_brace();
561 int32 item = 0;
562 while (ptr < end) {
563 if (item++ > 0)
564 fprintf(sOutputFile, "\n");
566 indent();
567 ptr = write_string_line(ptr, end, charsPerLine);
570 close_brace();
571 } else {
572 if (type != B_STRING_TYPE) {
573 fprintf(sOutputFile, "#");
574 write_code(type);
575 fprintf(sOutputFile, " ");
578 write_field_name(name);
579 write_string_line(ptr, end, charsPerLine);
584 static void
585 write_fields(BMessage &msg)
587 int32 t = 0;
588 int32 item = 0;
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;
600 open_brace();
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");
608 indent();
609 write_generic_data(name, type, data, length);
613 ++t;
616 close_brace();
620 static void
621 write_message(const char *name, BMessage &msg, type_code type)
623 if (type != B_MESSAGE_TYPE) {
624 fprintf(sOutputFile, "#");
625 write_code(type);
626 fprintf(sOutputFile, " ");
629 write_field_name(name);
631 const char *class_;
632 if (msg.FindString("class", &class_) == B_OK) {
633 fprintf(sOutputFile, "archive");
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);
642 fprintf(sOutputFile, ")");
644 msg.RemoveName("add_on");
645 } else if (msg.what != 0) {
646 fprintf(sOutputFile, "(, ");
647 write_code(msg.what);
648 fprintf(sOutputFile, ")");
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, ")");
661 if (msg.CountNames(B_ANY_TYPE) > 0)
662 write_fields(msg);
666 static void
667 write_other(const char *name, type_code type,
668 const void *data, size_t length)
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);
680 // #pragma mark - special types
683 static void
684 write_app_signature(const void *data, size_t length)
686 fprintf(sOutputFile, "resource app_signature ");
687 write_string_line((const char *)data, (const char *)data + length, length * 2);
691 static void
692 write_app_flags(const void *data, size_t length)
694 fprintf(sOutputFile, "resource app_flags ");
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;
709 if (flags & B_BACKGROUND_APP)
710 fputs(" | B_BACKGROUND_APP", sOutputFile);
711 if (flags & B_ARGV_ONLY)
712 fputs(" | B_ARGV_ONLY", sOutputFile);
716 static void
717 write_app_icon(uint32 which, const void *data, size_t length)
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;
739 fprintf(sOutputFile, "resource %s_icon ", type);
740 write_raw(NULL, B_RAW_TYPE, data, length, lineWidth);
744 static void
745 write_app_file_types(const void *data, size_t length)
747 fputs("resource file_types ", sOutputFile);
748 write_other(NULL, B_MESSAGE_TYPE, data, length);
752 static void
753 write_app_version(const void *data, size_t length)
755 const version_info *version = (const version_info *)data;
756 //const version_info *systemVersion = version + 1;
758 fputs("resource app_version", sOutputFile);
759 open_brace();
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);
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;
784 fprintf(sOutputFile, "\tvariety = %s,\n"
785 "\tinternal = %" B_PRIu32 ",\n\n", variety, version->internal);
787 fprintf(sOutputFile, "\tshort_info = ");
788 write_string(NULL, B_STRING_TYPE, version->short_info, strlen(version->short_info));
790 fprintf(sOutputFile, ",\n\tlong_info = ");
791 write_string(NULL, B_STRING_TYPE, version->long_info, strlen(version->long_info));
793 close_brace();
797 // #pragma mark - file examination
800 static void
801 write_generic_data(const char *name, type_code type,
802 const void *data, size_t length)
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;
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;
825 case B_MIME_STRING_TYPE:
826 case B_STRING_TYPE:
827 write_string(name, type, data, length);
828 break;
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;
839 default:
840 write_other(name, type, data, length);
841 break;
846 static void
847 write_data(int32 id, const char *name, type_code type,
848 const void *data, size_t length)
850 // check for special types
852 switch (type) {
853 case B_MIME_STRING_TYPE:
854 if (!strcmp(name, "BEOS:APP_SIG")) {
855 write_app_signature(data, length);
856 return;
858 break;
860 case 'VICN':
861 if (!strcmp(name, "BEOS:ICON")) {
862 write_app_icon('VICN', data, length);
863 return;
865 break;
867 case 'PNG ':
868 if (!strcmp(name, "BEOS:ICON")) {
869 write_app_icon('PNG ', data, length);
870 return;
872 break;
874 case 'MICN':
875 if (!strcmp(name, "BEOS:M:STD_ICON")) {
876 write_app_icon(B_MINI_ICON, data, length);
877 return;
879 break;
881 case 'ICON':
882 if (!strcmp(name, "BEOS:L:STD_ICON")) {
883 write_app_icon(B_LARGE_ICON, data, length);
884 return;
886 break;
888 case B_MESSAGE_TYPE:
889 if (!strcmp(name, "BEOS:FILE_TYPES")) {
890 write_app_file_types(data, length);
891 return;
893 break;
895 case 'APPF':
896 if (!strcmp(name, "BEOS:APP_FLAGS") && length == 4) {
897 write_app_flags(data, length);
898 return;
900 break;
902 case 'APPV':
903 if (!strcmp(name, "BEOS:APP_VERSION") && length == sizeof(version_info) * 2) {
904 write_app_version(data, length);
905 return;
907 break;
910 // write generic types
912 write_rsrc(type, id, name);
913 write_generic_data(NULL, type, data, length);
917 static void
918 examine_file(char *fileName)
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;
927 BResources res;
928 if (res.SetTo(&file) != B_OK) {
929 strcpy(rdef_err_file, fileName);
930 rdef_err = RDEF_NO_RESOURCES;
931 return;
934 int32 t = 0;
935 type_code type;
936 int32 id;
937 const char *name;
938 size_t length;
939 const void *data;
941 while (res.GetResourceInfo(t, &type, &id, &name, &length)) {
942 sTabs = 0;
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");
951 ++t;
956 static status_t
957 open_output_files(const char *fileName, const char *headerName)
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;
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;
975 fprintf(sOutputFile, "\n#include \"%s\"\n", headerName);
977 if (sBraceOnNextLine)
978 fprintf(sHeaderFile, "\nenum\n{\n");
979 else
980 fprintf(sHeaderFile, "\nenum {\n");
983 return B_OK;
987 static void
988 close_output_files(const char *fileName, const char *headerName)
990 if (flags & RDEF_AUTO_NAMES) {
991 fprintf(sHeaderFile, "};\n");
992 fclose(sHeaderFile);
994 if (rdef_err != B_OK)
995 unlink(headerName);
998 fclose(sOutputFile);
1000 if (rdef_err != B_OK)
1001 unlink(fileName);
1005 status_t
1006 rdef_decompile(const char *fileName)
1008 clear_error();
1010 if (fileName == NULL || fileName[0] == '\0') {
1011 rdef_err = B_BAD_VALUE;
1012 return rdef_err;
1015 char headerName[B_PATH_NAME_LENGTH + 1];
1016 if ((flags & RDEF_AUTO_NAMES) != 0)
1017 sprintf(headerName, "%s.h", fileName);
1019 rdef_err = open_output_files(fileName, headerName);
1020 if (rdef_err != B_OK)
1021 return rdef_err;
1023 for (ptr_iter_t i = input_files.begin();
1024 (i != input_files.end()) && (rdef_err == B_OK); ++i) {
1025 examine_file((char *)*i);
1028 close_output_files(fileName, headerName);
1029 return rdef_err;