summaryrefslogtreecommitdiff
path: root/third_party/incbin/incbin.c
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/incbin/incbin.c')
-rw-r--r--third_party/incbin/incbin.c289
1 files changed, 289 insertions, 0 deletions
diff --git a/third_party/incbin/incbin.c b/third_party/incbin/incbin.c
new file mode 100644
index 0000000000..4d4f64c9bf
--- /dev/null
+++ b/third_party/incbin/incbin.c
@@ -0,0 +1,289 @@
+#ifdef _MSC_VER
+# define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <limits.h>
+
+#ifndef PATH_MAX
+# define PATH_MAX 260
+#endif
+
+#define SEARCH_PATHS_MAX 64
+#define FILE_PATHS_MAX 1024
+
+static int fline(char **line, size_t *n, FILE *fp) {
+ int chr;
+ char *pos;
+ if (!line || !n || !fp)
+ return -1;
+ if (!*line)
+ if (!(*line = (char *)malloc((*n=64))))
+ return -1;
+ chr = *n;
+ pos = *line;
+ for (;;) {
+ int c = fgetc(fp);
+ if (chr < 2) {
+ *n += (*n > 16) ? *n : 64;
+ chr = *n + *line - pos;
+ if (!(*line = (char *)realloc(*line,*n)))
+ return -1;
+ pos = *n - chr + *line;
+ }
+ if (ferror(fp))
+ return -1;
+ if (c == EOF) {
+ if (pos == *line)
+ return -1;
+ else
+ break;
+ }
+ *pos++ = c;
+ chr--;
+ if (c == '\n')
+ break;
+ }
+ *pos = '\0';
+ return pos - *line;
+}
+
+static FILE *open_file(const char *name, const char *mode, const char (*searches)[PATH_MAX], int count) {
+ int i;
+ for (i = 0; i < count; i++) {
+ char buffer[FILENAME_MAX + PATH_MAX];
+ FILE *fp;
+#ifndef _MSC_VER
+ snprintf(buffer, sizeof(buffer), "%s/%s", searches[i], name);
+#else
+ _snprintf(buffer, sizeof(buffer), "%s/%s", searches[i], name);
+#endif
+ if ((fp = fopen(buffer, mode)))
+ return fp;
+ }
+ return !count ? fopen(name, mode) : NULL;
+}
+
+static int strcicmp(const char *s1, const char *s2) {
+ const unsigned char *us1 = (const unsigned char *)s1,
+ *us2 = (const unsigned char *)s2;
+ while (tolower(*us1) == tolower(*us2)) {
+ if (*us1++ == '\0')
+ return 0;
+ us2++;
+ }
+ return tolower(*us1) - tolower(*us2);
+}
+
+/* styles */
+enum { kCamel, kSnake };
+/* identifiers */
+enum { kData, kEnd, kSize };
+
+static const char *styled(int style, int ident) {
+ switch (style) {
+ case kCamel:
+ switch (ident) {
+ case kData: return "Data";
+ case kEnd: return "End";
+ case kSize: return "Size";
+ }
+ break;
+ case kSnake:
+ switch (ident) {
+ case kData: return "_data";
+ case kEnd: return "_end";
+ case kSize: return "_size";
+ }
+ break;
+ }
+}
+
+int main(int argc, char **argv) {
+ int ret, i, paths, files = 0, style = kCamel;
+ char outfile[FILENAME_MAX] = "data.c";
+ char search_paths[SEARCH_PATHS_MAX][PATH_MAX];
+ char prefix[FILENAME_MAX] = "g";
+ char file_paths[FILE_PATHS_MAX][PATH_MAX];
+ FILE *out = NULL;
+
+ argc--;
+ argv++;
+
+ #define s(IDENT) styled(style, IDENT)
+
+ if (argc == 0) {
+usage:
+ fprintf(stderr, "%s [-help] [-Ipath...] | <files> | [-o output] | [-p prefix]\n", argv[-1]);
+ fprintf(stderr, " -o - output file [default is \"data.c\"]\n");
+ fprintf(stderr, " -p - specify a prefix for symbol names (default is \"g\")\n");
+ fprintf(stderr, " -S<style> - specify a style for symbol generation (default is \"camelcase\")\n");
+ fprintf(stderr, " -I<path> - specify an include path for the tool to use\n");
+ fprintf(stderr, " -help - this\n");
+ fprintf(stderr, "example:\n");
+ fprintf(stderr, " %s icon.png music.mp3 -o file.c\n", argv[-1]);
+ fprintf(stderr, "styles (for -S):\n");
+ fprintf(stderr, " camelcase\n");
+ fprintf(stderr, " snakecase\n");
+ return 1;
+ }
+
+ for (i = 0, paths = 0; i < argc; i++) {
+ if (!strcmp(argv[i], "-o")) {
+ if (i + 1 < argc) {
+ strcpy(outfile, argv[i + 1]);
+ memmove(argv+i+1, argv+i+2, (argc-i-2) * sizeof *argv);
+ argc--;
+ continue;
+ }
+ } else if (!strcmp(argv[i], "-p")) {
+ /* supports "-p" with no prefix as well as
+ * "-p -" which is another way of saying "no prefix"
+ * and "-p <prefix>" for an actual prefix.
+ */
+ if (argv[i+1][0] == '-') {
+ prefix[0] = '\0';
+ /* is it just a -? */
+ if (i + 1 < argc && !strcmp(argv[i+1], "-")) {
+ memmove(argv+i+1, argv+i+2, (argc-i-2) * sizeof *argv);
+ argc--;
+ }
+ continue;
+ }
+ strcpy(prefix, argv[i + 1]);
+ memmove(argv+i+1, argv+i+2, (argc-i-2) * sizeof *argv);
+ argc--;
+ continue;
+ } else if (!strncmp(argv[i], "-I", 2)) {
+ char *name = argv[i] + 2; /* skip "-I"; */
+ if (paths >= SEARCH_PATHS_MAX) {
+ fprintf(stderr, "maximum search paths exceeded\n");
+ return 1;
+ }
+ strcpy(search_paths[paths++], name);
+ continue;
+ } else if (!strncmp(argv[i], "-S", 2)) {
+ char *name = argv[i] + 2; /* skip "-S"; */
+ if (!strcicmp(name, "camel") || !strcicmp(name, "camelcase"))
+ style = kCamel;
+ else if (!strcicmp(name, "snake") || !strcicmp(name, "snakecase"))
+ style = kSnake;
+ else
+ goto usage;
+ continue;
+ } else if (!strcmp(argv[i], "-help")) {
+ goto usage;
+ } else {
+ if (files >= sizeof file_paths / sizeof *file_paths) {
+ fprintf(stderr, "maximum file paths exceeded\n");
+ return 1;
+ }
+ strcpy(file_paths[files++], argv[i]);
+ }
+ }
+
+ if (!(out = fopen(outfile, "w"))) {
+ fprintf(stderr, "failed to open `%s' for output\n", outfile);
+ return 1;
+ }
+
+ fprintf(out, "/* File automatically generated by incbin */\n");
+ /* Be sure to define the prefix if we're not using the default */
+ if (strcmp(prefix, "g"))
+ fprintf(out, "#define INCBIN_PREFIX %s\n", prefix);
+ if (style != 0)
+ fprintf(out, "#define INCBIN_STYLE INCBIN_STYLE_SNAKE\n");
+ fprintf(out, "#include \"incbin.h\"\n\n");
+ fprintf(out, "#ifdef __cplusplus\n");
+ fprintf(out, "extern \"C\" {\n");
+ fprintf(out, "#endif\n\n");
+
+ for (i = 0; i < files; i++) {
+ FILE *fp = open_file(file_paths[i], "r", search_paths, paths);
+ char *line = NULL;
+ size_t size = 0;
+ if (!fp) {
+ fprintf(stderr, "failed to open `%s' for reading\n", file_paths[i]);
+ fclose(out);
+ return 1;
+ }
+ while (fline(&line, &size, fp) != -1) {
+ char *inc, *beg, *sep, *end, *name, *file;
+ FILE *f;
+ if (!(inc = strstr(line, "INCBIN"))) continue;
+ if (!(beg = strchr(inc, '('))) continue;
+ if (!(sep = strchr(beg, ','))) continue;
+ if (!(end = strchr(sep, ')'))) continue;
+ name = beg + 1;
+ file = sep + 1;
+ while (isspace(*name)) name++;
+ while (isspace(*file)) file++;
+ sep--;
+ while (isspace(*sep)) sep--;
+ *++sep = '\0';
+ end--;
+ while (isspace(*end)) end--;
+ *++end = '\0';
+ fprintf(out, "/* INCBIN(%s, %s); */\n", name, file);
+ fprintf(out, "INCBIN_CONST INCBIN_ALIGN unsigned char %s%s%s[] = {\n ", prefix, name, s(kData));
+ *--end = '\0';
+ file++;
+ if (!(f = open_file(file, "rb", search_paths, paths))) {
+ fprintf(stderr, "failed to include data `%s'\n", file);
+ goto end;
+ } else {
+ long size, i;
+ unsigned char *data, count = 0;
+ fseek(f, 0, SEEK_END);
+ size = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ if (!(data = (unsigned char *)malloc(size))) {
+ fprintf(stderr, "out of memory\n");
+ fclose(f);
+ ret = 1;
+ goto end;
+ }
+ if (fread(data, size, 1, f) != 1) {
+ fprintf(stderr, "failed reading include data `%s'\n", file);
+ free(data);
+ fclose(f);
+ ret = 1;
+ goto end;
+ }
+ for (i = 0; i < size; i++) {
+ if (count == 12) {
+ fprintf(out, "\n ");
+ count = 0;
+ }
+ fprintf(out, i != size - 1 ? "0x%02X, " : "0x%02X", data[i]);
+ count++;
+ }
+ free(data);
+ fclose(f);
+ }
+ fprintf(out, "\n};\n");
+ fprintf(out, "INCBIN_CONST INCBIN_ALIGN unsigned char *const %s%s%s = %s%s%s + sizeof(%s%s%s);\n", prefix, name, s(kEnd), prefix, name, s(kData), prefix, name, s(kData));
+ fprintf(out, "INCBIN_CONST unsigned int %s%s%s = sizeof(%s%s%s);\n", prefix, name, s(kSize), prefix, name, s(kData));
+ }
+end:
+ free(line);
+ fclose(fp);
+ printf("included `%s'\n", file_paths[i]);
+ }
+
+ if (ret == 0) {
+ fprintf(out, "\n#ifdef __cplusplus\n");
+ fprintf(out, "}\n");
+ fprintf(out, "#endif\n");
+ fclose(out);
+ printf("generated `%s'\n", outfile);
+ return 0;
+ }
+
+ fclose(out);
+ remove(outfile);
+ return 1;
+}