Last active
March 12, 2018 19:15
-
-
Save jdek/f2c812cce696aa75001ddb11f4aec353 to your computer and use it in GitHub Desktop.
cc -g -pedantic -Werror -Wall -Wno-unused-variable -o windres windres.c -DFORK
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <getopt.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdbool.h> | |
#include <string.h> | |
#include <pthread.h> | |
#include <sys/stat.h> | |
// cc -g -pedantic -Werror -Wall -Wno-unused-variable -o windres windres.c -DFORK | |
#define VERSION_MAJOR 0 | |
#define VERSION_MINOR 0 | |
#define VERSION_PATCH 1 | |
#ifndef TARGET | |
#define TARGET "x86_86-w64-mingw32" | |
#endif | |
#ifndef TMPDIR | |
#define TMPDIR "/tmp" | |
#endif | |
#define _STR(x) #x | |
#define STR(x) _STR(x) | |
#define VERSION STR(VERSION_MAJOR) "." STR(VERSION_MINOR) "." STR(VERSION_PATCH) | |
static bool verbose_flag = false; | |
static char *supported_formats[] = { | |
"res", | |
"rc", | |
"coff", | |
}; | |
void show_version() | |
{ | |
fprintf(stderr, "Non-GNU assembler version " VERSION " (" TARGET ")\n"); | |
} | |
void show_help(char *program) | |
{ | |
fprintf(stderr, | |
"usage: %s [options] <input> <output>\n" | |
"\t-i, --input\t\n" | |
"\t-o, --output\t\n" | |
"\t-J, --input-format\t\n" | |
"\t-O, --output-format\t\n" | |
"\t--preprocessor\t\n" | |
"\t--preprocessor-arg\t\n" | |
"\t-i, --include-dir\t\n" | |
"\t-D, --define\t\n" | |
"\t-U, --undefine\t\n" | |
"\t-c, --codepage\t\n" | |
"\t-v, --verbose\t\n" | |
"\t-V, --version\t\n" | |
"\t-h, --help\t\n", | |
program); | |
} | |
#define LLVM_RC_DRIVER | |
int main(int argc, char* argv[argc]) | |
{ | |
int guessed_input_format = -1; | |
int guessed_output_format = -1; | |
int input_format = -1; | |
int output_format = -1; | |
char *input_file = NULL; | |
char *output_file = NULL; | |
char **includes = NULL; | |
int includes_len = 0; | |
char **defines = NULL; | |
int defines_len = 0; | |
char **undefines = NULL; | |
int undefines_len = 0; | |
FILE *input; | |
FILE *output; | |
static struct option long_options[] = { | |
{ "input", required_argument, NULL, 'i' }, | |
{ "output", required_argument, NULL, 'o' }, | |
{ "input-format", required_argument, NULL, 'J' }, | |
{ "output-format", required_argument, NULL, 'O' }, | |
{ "preprocessor", required_argument, NULL, 0 }, | |
{ "preprocessor-arg", required_argument, NULL, 0 }, | |
{ "include-dir", required_argument, NULL, 'I' }, | |
{ "define", required_argument, NULL, 'D' }, | |
{ "undefine", required_argument, NULL, 'U' }, | |
{ "codepage", required_argument, NULL, 'c' }, | |
{ "language", required_argument, NULL, 'l' }, | |
{ "", no_argument, NULL, 'r' }, | |
{ "verbose", no_argument, NULL, 'v' }, | |
{ "version", no_argument, NULL, 'V' }, | |
{ "help", no_argument, NULL, 'h' }, | |
{ NULL, 0, NULL, 0 } | |
}; | |
int c = -1; | |
while ((c = getopt_long(argc, argv, "i:o:J:O:I:D:U:c:l:vVh", long_options, NULL)) != -1) { | |
int *format = NULL; | |
char **file = NULL; | |
switch (c) { | |
case 'v': | |
verbose_flag = true; | |
break; | |
case 'V': | |
show_version(); | |
break; | |
case 'i': | |
file = &input_file; | |
case 'o': | |
if (!file) | |
file = &output_file; | |
*file = strdup(optarg); | |
break; | |
case 'J': | |
format = &input_format; | |
case 'O': | |
if (!format) | |
format = &output_format; | |
for (int i = 0; i < sizeof(supported_formats)/sizeof(*supported_formats) + 1; i++) { | |
if (i == sizeof(supported_formats)/sizeof(*supported_formats)) { | |
goto help; | |
} | |
if (!strcmp(supported_formats[i], optarg)) { | |
*format = i; | |
break; | |
} | |
} | |
break; | |
default: | |
help: | |
show_help(argc > 0 ? argv[0] : "windres"); | |
return 0; | |
} | |
} | |
argc -= optind; | |
argv += optind; | |
if (argc >= 1) { | |
input_file = strdup(argv[0]); | |
if (argc >= 2) { | |
output_file = strdup(argv[1]); | |
} | |
} | |
#ifdef LLVM_RC_DRIVER | |
/* | |
/D <value> Define a symbol for the C preprocessor. | |
/FO <value> Change the output file location. | |
/H Display this help and exit. | |
/I <value> Add an include path. | |
/LN <value> Set the default language name. | |
/L <value> Set the default language identifier. | |
/N Null-terminate all strings in the string table. | |
/U <value> Undefine a symbol for the C preprocessor. | |
/V Be verbose. | |
/X Ignore 'include' variable. | |
/Y Suppress warnings on duplicate resource IDs. | |
*/ | |
pid_t llvm_rc_pid = fork(); | |
if (!llvm_rc_pid) { | |
int i = 0; | |
argc = 3 + | |
verbose_flag + | |
includes_len * 2 + | |
defines_len * 2 + | |
undefines_len * 2; | |
argv = calloc(argc, sizeof(char*)); | |
argv[i++] = "llvm-rc"; | |
if (verbose_flag) | |
argv[i++] = "/V"; | |
argv[i++] = "/FO"; | |
argv[i++] = output_file ? output_file : "/dev/fd/1"; | |
argv[i++] = input_file ? input_file : "/dev/fd/0"; | |
for (int j = 0; j < includes_len; j++) { | |
argv[i++] = "/I"; | |
argv[i++] = includes[j]; | |
} | |
for (int j = 0; j < defines_len; j++) { | |
argv[i++] = "/I"; | |
argv[i++] = defines[j]; | |
} | |
for (int j = 0; j < undefines_len; j++) { | |
argv[i++] = "/I"; | |
argv[i++] = undefines[j]; | |
} | |
argv[i++] = "\0"; | |
if (verbose_flag) { | |
for (int j = 0; j < i; j++) { | |
fprintf(stderr, "%s ", argv[j]); | |
} | |
fprintf(stderr, "\n"); | |
} | |
execvp("llvm-rc", argv); | |
} | |
int sig; | |
while (wait(&sig) > 0) | |
; | |
if (!input_file) { | |
input = stdin; | |
} else { | |
input = fopen(input_file, "rb"); | |
/* FIXME */ | |
} | |
if (!output_file) { | |
output = stdout; | |
} else { | |
output = fopen(output_file, "wb"); | |
/* FIXME */ | |
} | |
for (int i = 0; i < argc; ++i) { | |
fprintf(stderr, "%s\n", argv[i]); | |
} | |
if (input != stdin) | |
fclose(input); | |
if (output != stdout) | |
fclose(output); | |
free(input_file); | |
free(output_file); | |
#endif | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment