git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14613 a95241bf-73f2-0310-859d-f6bbb57e9c96
822 lines
18 KiB
C++
822 lines
18 KiB
C++
/*
|
|
* Copyright (c) 2003 Matthijs Hollemans
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#include <Mime.h>
|
|
#include <Resources.h>
|
|
#include <TypeConstants.h>
|
|
|
|
#include <ctype.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include "rdef.h"
|
|
#include "private.h"
|
|
|
|
// What we add to the front of enum symbols.
|
|
#define PREFIX "R_"
|
|
|
|
|
|
static FILE *sOutputFile;
|
|
static FILE *sHeaderFile;
|
|
|
|
// Level of indentation (how many tabs).
|
|
static int32 sTabs;
|
|
static bool sBraceOnNextLine = false;
|
|
|
|
static void examine_data(const char *, type_code, const void *, size_t);
|
|
|
|
|
|
static void
|
|
indent()
|
|
{
|
|
for (int32 t = 0; t < sTabs; ++t) {
|
|
fprintf(sOutputFile, "\t");
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
open_brace()
|
|
{
|
|
if (sBraceOnNextLine) {
|
|
fprintf(sOutputFile, "\n");
|
|
indent();
|
|
fprintf(sOutputFile, "{\n");
|
|
} else
|
|
fprintf(sOutputFile, " {\n");
|
|
|
|
++sTabs;
|
|
}
|
|
|
|
|
|
void
|
|
close_brace()
|
|
{
|
|
--sTabs;
|
|
|
|
fprintf(sOutputFile, "\n");
|
|
indent();
|
|
fprintf(sOutputFile, "}");
|
|
}
|
|
|
|
|
|
static bool
|
|
make_code(uint32 value, char *code)
|
|
{
|
|
code[0] = (value >> 24) & 0xFF;
|
|
if (isprint(code[0])) {
|
|
code[1] = (value >> 16) & 0xFF;
|
|
if (isprint(code[1])) {
|
|
code[2] = (value >> 8) & 0xFF;
|
|
if (isprint(code[2])) {
|
|
code[3] = value & 0xFF;
|
|
if (isprint(code[3])) {
|
|
code[4] = '\0';
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
static void
|
|
write_code(uint32 value)
|
|
{
|
|
char code[5];
|
|
if (make_code(value, code))
|
|
fprintf(sOutputFile, "'%s'", code);
|
|
else
|
|
fprintf(sOutputFile, "%lu", value);
|
|
}
|
|
|
|
|
|
static void
|
|
write_field_name(const char *name)
|
|
{
|
|
// We call this from the write_xxx() functions to properly align a
|
|
// field's type code (which goes to the left of the field name) and
|
|
// the field's data (to right of the name). If we are not currently
|
|
// writing a field (but the entire resource), name is NULL.
|
|
|
|
if (name != NULL)
|
|
fprintf(sOutputFile, "\"%s\" = ", name);
|
|
}
|
|
|
|
|
|
static bool
|
|
is_ident(const char *name)
|
|
{
|
|
if (name[0] != '_' && !isalpha(name[0]))
|
|
return false;
|
|
|
|
for (size_t t = 1; t < strlen(name); ++t) {
|
|
if (name[t] != '_' && !isalnum(name[t]))
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
static bool
|
|
has_prefix(const char *name)
|
|
{
|
|
size_t name_len = strlen(name);
|
|
size_t prefix_len = strlen(PREFIX);
|
|
|
|
if (name_len > prefix_len) {
|
|
if (strncmp(name, PREFIX, prefix_len) == 0)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
static void
|
|
write_rsrc(type_code type, int32 id, const char *name)
|
|
{
|
|
if (name[0] == '\0') {
|
|
fprintf(sOutputFile, "resource(%ld) ", id);
|
|
} else if ((flags & RDEF_AUTO_NAMES) != 0&& is_ident(name)) {
|
|
char code[5];
|
|
if (has_prefix(name)) {
|
|
fprintf(sOutputFile, "resource(%s) ", name);
|
|
fprintf(sHeaderFile, "\t%s = %ld,\n", name, id);
|
|
} else if (make_code(type, code)) {
|
|
fprintf(sOutputFile, "resource(%s%s_%s) ", PREFIX, code, name);
|
|
fprintf(sHeaderFile, "\t%s%s_%s = %ld,\n", PREFIX, code, name, id);
|
|
} else {
|
|
fprintf(sOutputFile, "resource(%s%ld_%s) ", PREFIX, type, name);
|
|
fprintf(sHeaderFile, "\t%s%ld_%s = %ld,\n", PREFIX, type, name, id);
|
|
}
|
|
} else {
|
|
fprintf(sOutputFile, "resource(%ld, \"%s\") ", id, name);
|
|
}
|
|
}
|
|
|
|
|
|
static uint8 *
|
|
write_raw_line(uint8 *ptr, uint8 *end, size_t bytesPerLine)
|
|
{
|
|
uint32 count = 0;
|
|
|
|
fprintf(sOutputFile, "$\"");
|
|
|
|
while (ptr < end && count < bytesPerLine) {
|
|
fprintf(sOutputFile, "%02X", *ptr++);
|
|
++count;
|
|
}
|
|
|
|
fprintf(sOutputFile, "\"");
|
|
|
|
return ptr;
|
|
}
|
|
|
|
|
|
static void
|
|
write_raw(const char *name, type_code type, const void *data,
|
|
size_t length, size_t bytesPerLine = 32)
|
|
{
|
|
uint8 *ptr = (uint8 *)data;
|
|
uint8 *end = ptr + length;
|
|
|
|
if (length > bytesPerLine) {
|
|
if (type != B_RAW_TYPE) {
|
|
fprintf(sOutputFile, "#");
|
|
write_code(type);
|
|
fprintf(sOutputFile, " ");
|
|
}
|
|
|
|
write_field_name(name);
|
|
fprintf(sOutputFile, "array");
|
|
|
|
open_brace();
|
|
|
|
int32 item = 0;
|
|
while (ptr < end) {
|
|
if (item++ > 0)
|
|
fprintf(sOutputFile, "\n");
|
|
|
|
indent();
|
|
ptr = write_raw_line(ptr, end, bytesPerLine);
|
|
}
|
|
|
|
close_brace();
|
|
} else {
|
|
if (type != B_RAW_TYPE) {
|
|
fprintf(sOutputFile, "#");
|
|
write_code(type);
|
|
fprintf(sOutputFile, " ");
|
|
}
|
|
|
|
write_field_name(name);
|
|
write_raw_line(ptr, end, bytesPerLine);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
write_bool(const char *name, const void *data, size_t length)
|
|
{
|
|
if (length != sizeof(bool)) {
|
|
write_raw(name, B_BOOL_TYPE, data, length);
|
|
} else {
|
|
write_field_name(name);
|
|
fprintf(sOutputFile, "%s", *(bool *)data ? "true" : "false");
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
write_int8(const char *name, const void *data, size_t length)
|
|
{
|
|
if (length != sizeof(int8)) {
|
|
write_raw(name, B_INT8_TYPE, data, length);
|
|
} else {
|
|
write_field_name(name);
|
|
fprintf(sOutputFile, "(int8)%d", *(int8 *)data);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
write_int16(const char *name, const void *data, size_t length)
|
|
{
|
|
if (length != sizeof(int16)) {
|
|
write_raw(name, B_INT16_TYPE, data, length);
|
|
} else {
|
|
write_field_name(name);
|
|
fprintf(sOutputFile, "(int16)%d", *(int16 *)data);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
write_int32(const char *name, const void *data, size_t length)
|
|
{
|
|
if (length != sizeof(int32)) {
|
|
write_raw(name, B_INT32_TYPE, data, length);
|
|
} else {
|
|
write_field_name(name);
|
|
fprintf(sOutputFile, "%ld", *(int32 *)data);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
write_int64(const char *name, const void *data, size_t length)
|
|
{
|
|
if (length != sizeof(int64)) {
|
|
write_raw(name, B_INT64_TYPE, data, length);
|
|
} else {
|
|
write_field_name(name);
|
|
fprintf(sOutputFile, "(int64)%lld", *(int64 *)data);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
write_uint8(const char *name, const void *data, size_t length)
|
|
{
|
|
if (length != sizeof(uint8)) {
|
|
write_raw(name, B_UINT8_TYPE, data, length);
|
|
} else {
|
|
write_field_name(name);
|
|
fprintf(sOutputFile, "(uint8)%u", *(uint8 *)data);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
write_uint16(const char *name, const void *data, size_t length)
|
|
{
|
|
if (length != sizeof(uint16)) {
|
|
write_raw(name, B_UINT16_TYPE, data, length);
|
|
} else {
|
|
write_field_name(name);
|
|
fprintf(sOutputFile, "(uint16)%u", *(uint16 *)data);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
write_uint32(const char *name, const void *data, size_t length)
|
|
{
|
|
if (length != sizeof(uint32)) {
|
|
write_raw(name, B_UINT32_TYPE, data, length);
|
|
} else {
|
|
write_field_name(name);
|
|
fprintf(sOutputFile, "(uint32)%lu", *(uint32 *)data);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
write_uint64(const char *name, const void *data, size_t length)
|
|
{
|
|
if (length != sizeof(uint64)) {
|
|
write_raw(name, B_UINT64_TYPE, data, length);
|
|
} else {
|
|
write_field_name(name);
|
|
fprintf(sOutputFile, "(uint64)%llu", *(uint64 *)data);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
write_float(const char *name, const void *data, size_t length)
|
|
{
|
|
if (length != sizeof(float)) {
|
|
write_raw(name, B_FLOAT_TYPE, data, length);
|
|
} else {
|
|
write_field_name(name);
|
|
fprintf(sOutputFile, "%#g", *(float *)data);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
write_double(const char *name, const void *data, size_t length)
|
|
{
|
|
if (length != sizeof(double)) {
|
|
write_raw(name, B_DOUBLE_TYPE, data, length);
|
|
} else {
|
|
write_field_name(name);
|
|
fprintf(sOutputFile, "(double)%#g", *(double *)data);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
write_size(const char *name, const void *data, size_t length)
|
|
{
|
|
if (length != sizeof(size_t)) {
|
|
write_raw(name, B_SIZE_T_TYPE, data, length);
|
|
} else {
|
|
write_field_name(name);
|
|
fprintf(sOutputFile, "(size_t)%lu", *(size_t *)data);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
write_ssize(const char *name, const void *data, size_t length)
|
|
{
|
|
if (length != sizeof(ssize_t)) {
|
|
write_raw(name, B_SSIZE_T_TYPE, data, length);
|
|
} else {
|
|
write_field_name(name);
|
|
fprintf(sOutputFile, "(ssize_t)%ld", *(ssize_t *)data);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
write_off(const char *name, const void *data, size_t length)
|
|
{
|
|
if (length != sizeof(off_t)) {
|
|
write_raw(name, B_OFF_T_TYPE, data, length);
|
|
} else {
|
|
write_field_name(name);
|
|
fprintf(sOutputFile, "(off_t)%lld", *(off_t *)data);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
write_time(const char *name, const void *data, size_t length)
|
|
{
|
|
if (length != sizeof(time_t)) {
|
|
write_raw(name, B_TIME_TYPE, data, length);
|
|
} else {
|
|
write_field_name(name);
|
|
fprintf(sOutputFile, "(time_t)%ld", *(time_t *)data);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
write_point(const char *name, const void *data)
|
|
{
|
|
///TODO: using built-in type table
|
|
|
|
write_field_name(name);
|
|
float *f = (float *)data;
|
|
fprintf(sOutputFile, "point { %#g, %#g }", f[0], f[1]);
|
|
}
|
|
|
|
|
|
static void
|
|
write_rect(const char *name, const void *data)
|
|
{
|
|
///TODO: using built-in type table
|
|
|
|
write_field_name(name);
|
|
float *f = (float *)data;
|
|
fprintf(sOutputFile, "rect { %#g, %#g, %#g, %#g }", f[0], f[1], f[2], f[3]);
|
|
}
|
|
|
|
|
|
static void
|
|
write_rgb(const char *name, const void *data)
|
|
{
|
|
///TODO: using built-in type table
|
|
|
|
write_field_name(name);
|
|
uint8 *b = (uint8 *)data;
|
|
|
|
fprintf(sOutputFile, "rgb_color { 0x%02X, 0x%02X, 0x%02X, 0x%02X }",
|
|
b[0], b[1], b[2], b[3]);
|
|
}
|
|
|
|
|
|
static char *
|
|
write_string_line(char *ptr, char *end, size_t charsPerLine)
|
|
{
|
|
uint32 count = 0;
|
|
bool end_of_item = false;
|
|
|
|
fprintf(sOutputFile, "\"");
|
|
|
|
while (ptr < end && count < charsPerLine && !end_of_item) {
|
|
char c = *ptr++;
|
|
|
|
switch (c) {
|
|
case '\b': fprintf(sOutputFile, "\\b"); count += 2; break;
|
|
case '\f': fprintf(sOutputFile, "\\f"); count += 2; break;
|
|
case '\n': fprintf(sOutputFile, "\\n"); count += 2; break;
|
|
case '\r': fprintf(sOutputFile, "\\r"); count += 2; break;
|
|
case '\t': fprintf(sOutputFile, "\\t"); count += 2; break;
|
|
case '\v': fprintf(sOutputFile, "\\v"); count += 2; break;
|
|
case '\"': fprintf(sOutputFile, "\\\""); count += 2; break;
|
|
case '\\': fprintf(sOutputFile, "\\\\"); count += 2; break;
|
|
|
|
case '\0': end_of_item = true; break;
|
|
|
|
default:
|
|
{
|
|
if ((uint8)c < 128 && !isprint(c)) {
|
|
fprintf(sOutputFile, "\\0x%02X", (uint8)c); count += 5;
|
|
} else {
|
|
fprintf(sOutputFile, "%c", c); ++count;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fprintf(sOutputFile, "\"");
|
|
|
|
if (end_of_item && ptr < end)
|
|
fprintf(sOutputFile, ",");
|
|
|
|
return ptr;
|
|
}
|
|
|
|
|
|
static void
|
|
write_string(const char *name, type_code type,
|
|
const void *data, size_t length)
|
|
{
|
|
char *ptr = (char *)data;
|
|
char *end = ptr + length;
|
|
size_t charsPerLine = 64;
|
|
|
|
// We write an "array" resource if the string has more than 64
|
|
// characters. A string resource may also be comprised of multiple
|
|
// substrings, each terminated by a '\0' char. In that case, we
|
|
// must write an "array" resource as well. Sneaky as we are, we use
|
|
// strlen() to check for that, because it also looks for a '\0'.
|
|
|
|
if (length > charsPerLine || strlen(ptr) < length - 1) {
|
|
fprintf(sOutputFile, "#");
|
|
write_code(type);
|
|
fprintf(sOutputFile, " array");
|
|
|
|
if (name != NULL) {
|
|
fprintf(sOutputFile, " ");
|
|
write_field_name(name);
|
|
fprintf(sOutputFile, " array");
|
|
}
|
|
|
|
open_brace();
|
|
|
|
int32 item = 0;
|
|
while (ptr < end) {
|
|
if (item++ > 0)
|
|
fprintf(sOutputFile, "\n");
|
|
|
|
indent();
|
|
ptr = write_string_line(ptr, end, charsPerLine);
|
|
}
|
|
|
|
close_brace();
|
|
} else {
|
|
if (type != B_STRING_TYPE) {
|
|
fprintf(sOutputFile, "#");
|
|
write_code(type);
|
|
fprintf(sOutputFile, " ");
|
|
}
|
|
|
|
write_field_name(name);
|
|
write_string_line(ptr, end, charsPerLine);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
write_fields(BMessage &msg)
|
|
{
|
|
int32 t = 0;
|
|
int32 item = 0;
|
|
|
|
#ifdef B_BEOS_VERSION_DANO
|
|
const char *name;
|
|
#else
|
|
char *name;
|
|
#endif
|
|
type_code type;
|
|
int32 count;
|
|
const void *data;
|
|
size_t length;
|
|
|
|
open_brace();
|
|
|
|
while (msg.GetInfo(B_ANY_TYPE, t, &name, &type, &count) == B_OK) {
|
|
for (int32 k = 0; k < count; ++k) {
|
|
if (msg.FindData(name, type, k, &data, (ssize_t*) &length) == B_OK) {
|
|
if (item++ > 0)
|
|
fprintf(sOutputFile, ",\n");
|
|
|
|
indent();
|
|
examine_data(name, type, data, length);
|
|
}
|
|
}
|
|
|
|
++t;
|
|
}
|
|
|
|
close_brace();
|
|
}
|
|
|
|
|
|
static void
|
|
write_message(const char *name, BMessage &msg, type_code type)
|
|
{
|
|
if (type != B_MESSAGE_TYPE) {
|
|
fprintf(sOutputFile, "#");
|
|
write_code(type);
|
|
fprintf(sOutputFile, " ");
|
|
}
|
|
|
|
write_field_name(name);
|
|
|
|
const char *class_;
|
|
if (msg.FindString("class", &class_) == B_OK) {
|
|
fprintf(sOutputFile, "archive");
|
|
|
|
const char *add_on;
|
|
if (msg.FindString("add_on", &add_on) == B_OK) {
|
|
fprintf(sOutputFile, "(\"%s\"", add_on);
|
|
if (msg.what != 0) {
|
|
fprintf(sOutputFile, ", ");
|
|
write_code(msg.what);
|
|
}
|
|
fprintf(sOutputFile, ")");
|
|
|
|
msg.RemoveName("add_on");
|
|
} else if (msg.what != 0) {
|
|
fprintf(sOutputFile, "(, ");
|
|
write_code(msg.what);
|
|
fprintf(sOutputFile, ")");
|
|
}
|
|
|
|
fprintf(sOutputFile, " %s", class_);
|
|
msg.RemoveName("class");
|
|
} else if (msg.what == 0) {
|
|
fprintf(sOutputFile, "message");
|
|
} else {
|
|
fprintf(sOutputFile, "message(");
|
|
write_code(msg.what);
|
|
fprintf(sOutputFile, ")");
|
|
}
|
|
|
|
if (msg.CountNames(B_ANY_TYPE) > 0)
|
|
write_fields(msg);
|
|
}
|
|
|
|
|
|
static bool
|
|
is_string(const void *data, size_t length)
|
|
{
|
|
// We consider the buffer a string if it contains only human readable
|
|
// characters. The buffer should also end with a '\0'. Although the
|
|
// compiler allows string literals to contain embedded '\0' chars as
|
|
// well, we don't allow them here (because they may cause false hits).
|
|
|
|
if (length == 0)
|
|
return false;
|
|
|
|
char *ptr = (char *)data;
|
|
|
|
for (size_t t = 0; t < length - 1; ++t) {
|
|
if (!isprint(*ptr++))
|
|
return false;
|
|
}
|
|
|
|
return (*ptr == '\0');
|
|
}
|
|
|
|
|
|
static void
|
|
write_other(const char *name, type_code type,
|
|
const void *data, size_t length)
|
|
{
|
|
BMessage msg;
|
|
if (msg.Unflatten((const char *)data) == B_OK)
|
|
write_message(name, msg, type);
|
|
else if (is_string(data, length))
|
|
write_string(name, type, data, length);
|
|
else
|
|
write_raw(name, type, data, length);
|
|
}
|
|
|
|
|
|
static void
|
|
examine_data(const char *name, type_code type,
|
|
const void *data, size_t length)
|
|
{
|
|
switch (type) {
|
|
case B_BOOL_TYPE: write_bool(name, data, length); break;
|
|
case B_INT8_TYPE: write_int8(name, data, length); break;
|
|
case B_INT16_TYPE: write_int16(name, data, length); break;
|
|
case B_INT32_TYPE: write_int32(name, data, length); break;
|
|
case B_INT64_TYPE: write_int64(name, data, length); break;
|
|
case B_UINT8_TYPE: write_uint8(name, data, length); break;
|
|
case B_UINT16_TYPE: write_uint16(name, data, length); break;
|
|
case B_UINT32_TYPE: write_uint32(name, data, length); break;
|
|
case B_UINT64_TYPE: write_uint64(name, data, length); break;
|
|
case B_FLOAT_TYPE: write_float(name, data, length); break;
|
|
case B_DOUBLE_TYPE: write_double(name, data, length); break;
|
|
case B_SIZE_T_TYPE: write_size(name, data, length); break;
|
|
case B_SSIZE_T_TYPE: write_ssize(name, data, length); break;
|
|
case B_OFF_T_TYPE: write_off(name, data, length); break;
|
|
case B_TIME_TYPE: write_time(name, data, length); break;
|
|
|
|
case B_POINT_TYPE: write_point(name, data); break;
|
|
case B_RECT_TYPE: write_rect(name, data); break;
|
|
case B_RGB_COLOR_TYPE: write_rgb(name, data); break;
|
|
|
|
case B_MIME_STRING_TYPE: write_string(name, type, data, length); break;
|
|
case B_STRING_TYPE: write_string(name, type, data, length); break;
|
|
|
|
case B_POINTER_TYPE: write_raw(name, type, data, length); break;
|
|
case 'MICN': write_raw(name, type, data, length, 16); break;
|
|
case 'ICON': write_raw(name, type, data, length); break;
|
|
|
|
default: write_other(name, type, data, length); break;
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
examine_file(char *fileName)
|
|
{
|
|
BFile file(fileName, B_READ_ONLY);
|
|
if (file.InitCheck() != B_OK) {
|
|
strcpy(rdef_err_file, fileName);
|
|
rdef_err = RDEF_FILE_NOT_FOUND;
|
|
return;
|
|
}
|
|
|
|
BResources res;
|
|
if (res.SetTo(&file) != B_OK) {
|
|
strcpy(rdef_err_file, fileName);
|
|
rdef_err = RDEF_NO_RESOURCES;
|
|
return;
|
|
}
|
|
|
|
int32 t = 0;
|
|
type_code type;
|
|
int32 id;
|
|
const char *name;
|
|
size_t length;
|
|
const void *data;
|
|
|
|
while (res.GetResourceInfo(t, &type, &id, &name, &length)) {
|
|
sTabs = 0;
|
|
|
|
data = res.LoadResource(type, id, NULL);
|
|
if (data != NULL) {
|
|
fprintf(sOutputFile, "\n");
|
|
write_rsrc(type, id, name);
|
|
examine_data(NULL, type, data, length);
|
|
fprintf(sOutputFile, ";\n");
|
|
}
|
|
|
|
++t;
|
|
}
|
|
}
|
|
|
|
|
|
static status_t
|
|
open_output_files(const char *fileName, const char *headerName)
|
|
{
|
|
sOutputFile = fopen(fileName, "w");
|
|
if (sOutputFile == NULL) {
|
|
strcpy(rdef_err_msg, strerror(errno));
|
|
strcpy(rdef_err_file, fileName);
|
|
return RDEF_WRITE_ERR;
|
|
}
|
|
|
|
if (flags & RDEF_AUTO_NAMES) {
|
|
sHeaderFile = fopen(headerName, "w");
|
|
if (sHeaderFile == NULL) {
|
|
strcpy(rdef_err_msg, strerror(errno));
|
|
strcpy(rdef_err_file, headerName);
|
|
fclose(sOutputFile);
|
|
return RDEF_WRITE_ERR;
|
|
}
|
|
|
|
fprintf(sOutputFile, "\n#include \"%s\"\n", headerName);
|
|
|
|
if (sBraceOnNextLine)
|
|
fprintf(sHeaderFile, "\nenum\n{\n");
|
|
else
|
|
fprintf(sHeaderFile, "\nenum {\n");
|
|
}
|
|
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
static void
|
|
close_output_files(const char *fileName, const char *headerName)
|
|
{
|
|
if (flags & RDEF_AUTO_NAMES) {
|
|
fprintf(sHeaderFile, "};\n");
|
|
fclose(sHeaderFile);
|
|
|
|
if (rdef_err != B_OK)
|
|
unlink(headerName);
|
|
}
|
|
|
|
fclose(sOutputFile);
|
|
|
|
if (rdef_err != B_OK)
|
|
unlink(fileName);
|
|
}
|
|
|
|
|
|
status_t
|
|
rdef_decompile(const char *fileName)
|
|
{
|
|
clear_error();
|
|
|
|
if (fileName == NULL || fileName[0] == '\0') {
|
|
rdef_err = B_BAD_VALUE;
|
|
return rdef_err;
|
|
}
|
|
|
|
char headerName[B_PATH_NAME_LENGTH + 1];
|
|
if ((flags & RDEF_AUTO_NAMES) != 0)
|
|
sprintf(headerName, "%s.h", fileName);
|
|
|
|
rdef_err = open_output_files(fileName, headerName);
|
|
if (rdef_err != B_OK)
|
|
return rdef_err;
|
|
|
|
for (ptr_iter_t i = input_files.begin();
|
|
(i != input_files.end()) && (rdef_err == B_OK); ++i) {
|
|
examine_file((char *)*i);
|
|
}
|
|
|
|
close_output_files(fileName, headerName);
|
|
return rdef_err;
|
|
}
|
|
|