1e221c09eSPhilippe Houdoin /*
2e221c09eSPhilippe Houdoin * Copyright (c) 2003 Matthijs Hollemans
3e221c09eSPhilippe Houdoin *
4e221c09eSPhilippe Houdoin * Permission is hereby granted, free of charge, to any person obtaining a
5e221c09eSPhilippe Houdoin * copy of this software and associated documentation files (the "Software"),
6e221c09eSPhilippe Houdoin * to deal in the Software without restriction, including without limitation
7e221c09eSPhilippe Houdoin * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8e221c09eSPhilippe Houdoin * and/or sell copies of the Software, and to permit persons to whom the
9e221c09eSPhilippe Houdoin * Software is furnished to do so, subject to the following conditions:
10e221c09eSPhilippe Houdoin *
11e221c09eSPhilippe Houdoin * The above copyright notice and this permission notice shall be included in
12e221c09eSPhilippe Houdoin * all copies or substantial portions of the Software.
13e221c09eSPhilippe Houdoin *
14e221c09eSPhilippe Houdoin * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15e221c09eSPhilippe Houdoin * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16e221c09eSPhilippe Houdoin * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17e221c09eSPhilippe Houdoin * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18e221c09eSPhilippe Houdoin * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19e221c09eSPhilippe Houdoin * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20e221c09eSPhilippe Houdoin * DEALINGS IN THE SOFTWARE.
21e221c09eSPhilippe Houdoin */
22e221c09eSPhilippe Houdoin
23e221c09eSPhilippe Houdoin
24e221c09eSPhilippe Houdoin #include <stdarg.h>
25e221c09eSPhilippe Houdoin #include <stdio.h>
26e221c09eSPhilippe Houdoin #include <stdlib.h>
27e221c09eSPhilippe Houdoin #include <string.h>
28e221c09eSPhilippe Houdoin
29e221c09eSPhilippe Houdoin #include "rdef.h"
30e221c09eSPhilippe Houdoin
31e221c09eSPhilippe Houdoin
32e221c09eSPhilippe Houdoin extern const char *__progname;
33e221c09eSPhilippe Houdoin
34e221c09eSPhilippe Houdoin static const char *kTitle = "Haiku Resource Compiler 1.1";
35e221c09eSPhilippe Houdoin static const char *kProgramName = __progname;
36e221c09eSPhilippe Houdoin
37e221c09eSPhilippe Houdoin
38e221c09eSPhilippe Houdoin static bool sQuiet = false;
39e221c09eSPhilippe Houdoin static bool sDecompile = false;
40e221c09eSPhilippe Houdoin static uint32 sFlags = 0;
41e221c09eSPhilippe Houdoin
42e221c09eSPhilippe Houdoin static char sOutputFile[B_PATH_NAME_LENGTH] = { 0 };
43e221c09eSPhilippe Houdoin static char *sFirstInputFile = NULL;
44e221c09eSPhilippe Houdoin
45e221c09eSPhilippe Houdoin
46e221c09eSPhilippe Houdoin void
warn(const char * format,...)47e221c09eSPhilippe Houdoin warn(const char *format, ...)
48e221c09eSPhilippe Houdoin {
49e221c09eSPhilippe Houdoin va_list ap;
50e221c09eSPhilippe Houdoin
51e221c09eSPhilippe Houdoin if (!sQuiet) {
52e221c09eSPhilippe Houdoin fprintf(stderr, "%s: Warning! ", kProgramName);
53e221c09eSPhilippe Houdoin va_start(ap, format);
54e221c09eSPhilippe Houdoin vfprintf(stderr, format, ap);
55e221c09eSPhilippe Houdoin va_end(ap);
56e221c09eSPhilippe Houdoin fprintf(stderr, "\n");
57e221c09eSPhilippe Houdoin }
58e221c09eSPhilippe Houdoin }
59e221c09eSPhilippe Houdoin
60e221c09eSPhilippe Houdoin
61e221c09eSPhilippe Houdoin void
error(const char * format,...)62e221c09eSPhilippe Houdoin error(const char *format, ...)
63e221c09eSPhilippe Houdoin {
64e221c09eSPhilippe Houdoin va_list ap;
65e221c09eSPhilippe Houdoin
66e221c09eSPhilippe Houdoin if (!sQuiet) {
67e221c09eSPhilippe Houdoin fprintf(stderr, "%s: Error! ", kProgramName);
68e221c09eSPhilippe Houdoin va_start(ap, format);
69e221c09eSPhilippe Houdoin vfprintf(stderr, format, ap);
70e221c09eSPhilippe Houdoin va_end(ap);
71e221c09eSPhilippe Houdoin fprintf(stderr, "\n");
72e221c09eSPhilippe Houdoin }
73e221c09eSPhilippe Houdoin
74e221c09eSPhilippe Houdoin exit(EXIT_FAILURE);
75e221c09eSPhilippe Houdoin }
76e221c09eSPhilippe Houdoin
77e221c09eSPhilippe Houdoin
78e221c09eSPhilippe Houdoin static void
usage()79e221c09eSPhilippe Houdoin usage()
80e221c09eSPhilippe Houdoin {
81e221c09eSPhilippe Houdoin printf("%s\n\n"
82e221c09eSPhilippe Houdoin "To compile an rdef script into a resource file:\n"
83e221c09eSPhilippe Houdoin " %s [options] [-o <file>] <file>...\n\n"
84e221c09eSPhilippe Houdoin "To convert a resource file back into an rdef script:\n"
85e221c09eSPhilippe Houdoin " %s [options] [-o <file>] -d <file>...\n\n"
86e221c09eSPhilippe Houdoin "Options:\n"
87e221c09eSPhilippe Houdoin " -d --decompile create an rdef script from a resource file\n"
88e221c09eSPhilippe Houdoin " --auto-names construct resource names from ID symbols\n"
89e221c09eSPhilippe Houdoin " -h --help show this message\n"
90e221c09eSPhilippe Houdoin " -I --include <dir> add <dir> to the list of include paths\n"
91e221c09eSPhilippe Houdoin " -m --merge do not erase existing contents of output file\n"
92e221c09eSPhilippe Houdoin " -o --output specify output file name, default is out.xxx\n"
93e221c09eSPhilippe Houdoin " -q --quiet do not display any error messages\n"
94e221c09eSPhilippe Houdoin " -V --version show software version and license\n",
95e221c09eSPhilippe Houdoin kTitle, kProgramName, kProgramName);
96e221c09eSPhilippe Houdoin
97e221c09eSPhilippe Houdoin exit(EXIT_SUCCESS);
98e221c09eSPhilippe Houdoin }
99e221c09eSPhilippe Houdoin
100e221c09eSPhilippe Houdoin
101e221c09eSPhilippe Houdoin static void
version()102e221c09eSPhilippe Houdoin version()
103e221c09eSPhilippe Houdoin {
104e221c09eSPhilippe Houdoin printf("%s\n\n"
105e221c09eSPhilippe Houdoin "Copyright (c) 2003 Matthijs Hollemans\n\n"
106e221c09eSPhilippe Houdoin
107e221c09eSPhilippe Houdoin "Permission is hereby granted, free of charge, to any person obtaining a\n"
108e221c09eSPhilippe Houdoin "copy of this software and associated documentation files (the \"Software\"),\n"
109e221c09eSPhilippe Houdoin "to deal in the Software without restriction, including without limitation\n"
110e221c09eSPhilippe Houdoin "the rights to use, copy, modify, merge, publish, distribute, sublicense,\n"
111e221c09eSPhilippe Houdoin "and/or sell copies of the Software, and to permit persons to whom the\n"
112e221c09eSPhilippe Houdoin "Software is furnished to do so, subject to the following conditions:\n\n"
113e221c09eSPhilippe Houdoin
114e221c09eSPhilippe Houdoin "The above copyright notice and this permission notice shall be included in\n"
115e221c09eSPhilippe Houdoin "all copies or substantial portions of the Software.\n\n"
116e221c09eSPhilippe Houdoin
117e221c09eSPhilippe Houdoin "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n"
118e221c09eSPhilippe Houdoin "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n"
119e221c09eSPhilippe Houdoin "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n"
120e221c09eSPhilippe Houdoin "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n"
121e221c09eSPhilippe Houdoin "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n"
122e221c09eSPhilippe Houdoin "FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n"
123e221c09eSPhilippe Houdoin "DEALINGS IN THE SOFTWARE.\n",
124e221c09eSPhilippe Houdoin kTitle);
125e221c09eSPhilippe Houdoin
126e221c09eSPhilippe Houdoin exit(EXIT_SUCCESS);
127e221c09eSPhilippe Houdoin }
128e221c09eSPhilippe Houdoin
129e221c09eSPhilippe Houdoin
130e221c09eSPhilippe Houdoin static bool
has_extension(char * name,const char * ext)131e221c09eSPhilippe Houdoin has_extension(char *name, const char *ext)
132e221c09eSPhilippe Houdoin {
133e221c09eSPhilippe Houdoin size_t nameLength = strlen(name);
134e221c09eSPhilippe Houdoin size_t extLength = strlen(ext);
135e221c09eSPhilippe Houdoin
136e221c09eSPhilippe Houdoin if (nameLength > extLength)
137e221c09eSPhilippe Houdoin return strcmp(name + nameLength - extLength, ext) == 0;
138e221c09eSPhilippe Houdoin
139e221c09eSPhilippe Houdoin return false;
140e221c09eSPhilippe Houdoin }
141e221c09eSPhilippe Houdoin
142e221c09eSPhilippe Houdoin
143e221c09eSPhilippe Houdoin static void
cut_extension(char * name,const char * ext)144e221c09eSPhilippe Houdoin cut_extension(char *name, const char *ext)
145e221c09eSPhilippe Houdoin {
146e221c09eSPhilippe Houdoin if (!has_extension(name, ext))
147e221c09eSPhilippe Houdoin return;
148e221c09eSPhilippe Houdoin
149e221c09eSPhilippe Houdoin name[strlen(name) - strlen(ext)] = '\0';
150e221c09eSPhilippe Houdoin }
151e221c09eSPhilippe Houdoin
152e221c09eSPhilippe Houdoin
153e221c09eSPhilippe Houdoin static void
add_extension(char * name,const char * ext)154e221c09eSPhilippe Houdoin add_extension(char *name, const char *ext)
155e221c09eSPhilippe Houdoin {
156e221c09eSPhilippe Houdoin strlcat(name, ext, B_PATH_NAME_LENGTH);
157e221c09eSPhilippe Houdoin }
158e221c09eSPhilippe Houdoin
159e221c09eSPhilippe Houdoin
160e221c09eSPhilippe Houdoin static void
parse_options(int argc,char * argv[])161e221c09eSPhilippe Houdoin parse_options(int argc, char *argv[])
162e221c09eSPhilippe Houdoin {
163e221c09eSPhilippe Houdoin int32 args_left = argc - 1;
164e221c09eSPhilippe Houdoin
165e221c09eSPhilippe Houdoin // ToDo: use getopt_long()
166e221c09eSPhilippe Houdoin
167e221c09eSPhilippe Houdoin for (int32 i = 1; i < argc; ++i) {
168e221c09eSPhilippe Houdoin if (strcmp(argv[i], "-o") == 0
169e221c09eSPhilippe Houdoin || strcmp(argv[i], "--output") == 0) {
170e221c09eSPhilippe Houdoin if (i + 1 >= argc)
171e221c09eSPhilippe Houdoin error("%s should be followed by a file name", argv[i]);
172e221c09eSPhilippe Houdoin
173e221c09eSPhilippe Houdoin strcpy(sOutputFile, argv[i + 1]);
174e221c09eSPhilippe Houdoin
175e221c09eSPhilippe Houdoin argv[i] = NULL;
176e221c09eSPhilippe Houdoin argv[i + 1] = NULL;
177e221c09eSPhilippe Houdoin ++i; args_left -= 2;
178e221c09eSPhilippe Houdoin } else if (strcmp(argv[i], "-I") == 0
179e221c09eSPhilippe Houdoin || strcmp(argv[i], "--include") == 0) {
180e221c09eSPhilippe Houdoin if (i + 1 >= argc)
181e221c09eSPhilippe Houdoin error("%s should be followed by a directory name", argv[i]);
182e221c09eSPhilippe Houdoin
183e221c09eSPhilippe Houdoin rdef_add_include_dir(argv[i + 1], true);
184e221c09eSPhilippe Houdoin
185e221c09eSPhilippe Houdoin argv[i] = NULL;
186e221c09eSPhilippe Houdoin argv[i + 1] = NULL;
187e221c09eSPhilippe Houdoin ++i; args_left -= 2;
188e221c09eSPhilippe Houdoin } else if (strcmp(argv[i], "-d") == 0
189e221c09eSPhilippe Houdoin || strcmp(argv[i], "--decompile") == 0) {
190e221c09eSPhilippe Houdoin sDecompile = true;
191e221c09eSPhilippe Houdoin argv[i] = NULL;
192e221c09eSPhilippe Houdoin --args_left;
193e221c09eSPhilippe Houdoin } else if (strcmp(argv[i], "-m") == 0
194e221c09eSPhilippe Houdoin || strcmp(argv[i], "--merge") == 0) {
195e221c09eSPhilippe Houdoin sFlags |= RDEF_MERGE_RESOURCES;
196e221c09eSPhilippe Houdoin argv[i] = NULL;
197e221c09eSPhilippe Houdoin --args_left;
198e221c09eSPhilippe Houdoin } else if (strcmp(argv[i], "--auto-names") == 0) {
199e221c09eSPhilippe Houdoin sFlags |= RDEF_AUTO_NAMES;
200e221c09eSPhilippe Houdoin argv[i] = NULL;
201e221c09eSPhilippe Houdoin --args_left;
202e221c09eSPhilippe Houdoin } else if (strcmp(argv[i], "-q") == 0
203e221c09eSPhilippe Houdoin || strcmp(argv[i], "--quiet") == 0) {
204e221c09eSPhilippe Houdoin sQuiet = true;
205e221c09eSPhilippe Houdoin argv[i] = NULL;
206e221c09eSPhilippe Houdoin --args_left;
207e221c09eSPhilippe Houdoin } else if (strcmp(argv[i], "-h") == 0
208e221c09eSPhilippe Houdoin || strcmp(argv[i], "--help") == 0) {
209e221c09eSPhilippe Houdoin usage();
210e221c09eSPhilippe Houdoin } else if (strcmp(argv[i], "-V") == 0
211e221c09eSPhilippe Houdoin || strcmp(argv[i], "--version") == 0) {
212e221c09eSPhilippe Houdoin version();
213e221c09eSPhilippe Houdoin } else if (!strcmp(argv[i], "-")) {
214e221c09eSPhilippe Houdoin // stdin input file
215e221c09eSPhilippe Houdoin break;
216e221c09eSPhilippe Houdoin } else if (argv[i][0] == '-') {
217e221c09eSPhilippe Houdoin error("unknown option %s", argv[i]);
218e221c09eSPhilippe Houdoin argv[i] = NULL;
219e221c09eSPhilippe Houdoin --args_left;
220e221c09eSPhilippe Houdoin }
221e221c09eSPhilippe Houdoin }
222e221c09eSPhilippe Houdoin
22335f15210SStephan Aßmus if (args_left < 1) {
224e221c09eSPhilippe Houdoin error("no input files");
22535f15210SStephan Aßmus usage();
22635f15210SStephan Aßmus }
227e221c09eSPhilippe Houdoin
228e221c09eSPhilippe Houdoin for (int i = 1; i < argc; ++i) {
229e221c09eSPhilippe Houdoin if (argv[i] == NULL)
230e221c09eSPhilippe Houdoin continue;
231e221c09eSPhilippe Houdoin
232e221c09eSPhilippe Houdoin if (sFirstInputFile == NULL)
233e221c09eSPhilippe Houdoin sFirstInputFile = argv[i];
234e221c09eSPhilippe Houdoin
235e221c09eSPhilippe Houdoin rdef_add_input_file(argv[i]);
236e221c09eSPhilippe Houdoin }
237e221c09eSPhilippe Houdoin
238e221c09eSPhilippe Houdoin if (sOutputFile[0] == '\0') {
239e221c09eSPhilippe Houdoin // no output file name was given, use the name of the
240e221c09eSPhilippe Houdoin // first source file as base
241e221c09eSPhilippe Houdoin strlcpy(sOutputFile, sFirstInputFile, sizeof(sOutputFile));
242e221c09eSPhilippe Houdoin
243e221c09eSPhilippe Houdoin cut_extension(sOutputFile, sDecompile ? ".rsrc" : ".rdef");
244e221c09eSPhilippe Houdoin add_extension(sOutputFile, sDecompile ? ".rdef" : ".rsrc");
245e221c09eSPhilippe Houdoin }
246e221c09eSPhilippe Houdoin }
247e221c09eSPhilippe Houdoin
248e221c09eSPhilippe Houdoin
249e221c09eSPhilippe Houdoin static void
compile()250e221c09eSPhilippe Houdoin compile()
251e221c09eSPhilippe Houdoin {
252e221c09eSPhilippe Houdoin if (!has_extension(sOutputFile, ".rsrc"))
253e221c09eSPhilippe Houdoin add_extension(sOutputFile, ".rsrc");
254e221c09eSPhilippe Houdoin
255e221c09eSPhilippe Houdoin rdef_compile(sOutputFile);
256e221c09eSPhilippe Houdoin }
257e221c09eSPhilippe Houdoin
258e221c09eSPhilippe Houdoin
259e221c09eSPhilippe Houdoin static void
decompile()260e221c09eSPhilippe Houdoin decompile()
261e221c09eSPhilippe Houdoin {
262e221c09eSPhilippe Houdoin if (!has_extension(sOutputFile, ".rdef"))
263e221c09eSPhilippe Houdoin add_extension(sOutputFile, ".rdef");
264e221c09eSPhilippe Houdoin
265e221c09eSPhilippe Houdoin rdef_decompile(sOutputFile);
266e221c09eSPhilippe Houdoin }
267e221c09eSPhilippe Houdoin
268e221c09eSPhilippe Houdoin
269e221c09eSPhilippe Houdoin static void
report_error()270e221c09eSPhilippe Houdoin report_error()
271e221c09eSPhilippe Houdoin {
272e221c09eSPhilippe Houdoin switch (rdef_err) {
273e221c09eSPhilippe Houdoin case RDEF_COMPILE_ERR:
274*f4742397SMurai Takashi error("%s:%" B_PRId32 " %s", rdef_err_file, rdef_err_line, rdef_err_msg);
275e221c09eSPhilippe Houdoin break;
276e221c09eSPhilippe Houdoin
277e221c09eSPhilippe Houdoin case RDEF_FILE_NOT_FOUND:
278e221c09eSPhilippe Houdoin error("%s not found", rdef_err_file);
279e221c09eSPhilippe Houdoin break;
280e221c09eSPhilippe Houdoin
281e221c09eSPhilippe Houdoin case RDEF_NO_RESOURCES:
282e221c09eSPhilippe Houdoin error("%s is not a resource file", rdef_err_file);
283e221c09eSPhilippe Houdoin break;
284e221c09eSPhilippe Houdoin
285e221c09eSPhilippe Houdoin case RDEF_WRITE_ERR:
286e221c09eSPhilippe Houdoin error("error writing to %s (%s)", rdef_err_file, rdef_err_msg);
287e221c09eSPhilippe Houdoin break;
288e221c09eSPhilippe Houdoin
289e221c09eSPhilippe Houdoin case B_NO_MEMORY:
290e221c09eSPhilippe Houdoin error("out of memory");
291e221c09eSPhilippe Houdoin break;
292e221c09eSPhilippe Houdoin
293e221c09eSPhilippe Houdoin case B_ERROR:
294e221c09eSPhilippe Houdoin default:
295*f4742397SMurai Takashi error("unknown error: %" B_PRIx32 " (%s)", rdef_err, strerror(rdef_err));
296e221c09eSPhilippe Houdoin break;
297e221c09eSPhilippe Houdoin }
298e221c09eSPhilippe Houdoin }
299e221c09eSPhilippe Houdoin
300e221c09eSPhilippe Houdoin
301e221c09eSPhilippe Houdoin int
main(int argc,char * argv[])302e221c09eSPhilippe Houdoin main(int argc, char *argv[])
303e221c09eSPhilippe Houdoin {
304e221c09eSPhilippe Houdoin parse_options(argc, argv);
305e221c09eSPhilippe Houdoin
306e221c09eSPhilippe Houdoin rdef_set_flags(sFlags);
307e221c09eSPhilippe Houdoin
308e221c09eSPhilippe Houdoin if (sDecompile)
309e221c09eSPhilippe Houdoin decompile();
310e221c09eSPhilippe Houdoin else
311e221c09eSPhilippe Houdoin compile();
312e221c09eSPhilippe Houdoin
313e221c09eSPhilippe Houdoin rdef_free_input_files();
314e221c09eSPhilippe Houdoin rdef_free_include_dirs();
315e221c09eSPhilippe Houdoin
316e221c09eSPhilippe Houdoin if (rdef_err != B_OK)
317e221c09eSPhilippe Houdoin report_error();
318e221c09eSPhilippe Houdoin
319e221c09eSPhilippe Houdoin return EXIT_SUCCESS;
320e221c09eSPhilippe Houdoin }
321e221c09eSPhilippe Houdoin
322