Skip to content

Instantly share code, notes, and snippets.

@jdek
Last active March 12, 2018 19:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jdek/f2c812cce696aa75001ddb11f4aec353 to your computer and use it in GitHub Desktop.
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
#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