Browse Source

Experimenting with incbin

Piotr Czajkowski 5 years ago
parent
commit
0c5cf8fa29
5 changed files with 745 additions and 1 deletions
  1. 4 1
      extractHistory.c
  2. 0 0
      extractHistory.h
  3. 289 0
      incbin.c
  4. 357 0
      incbin.h
  5. 95 0
      mqxliffHistory.xsl

+ 4 - 1
extractHistory.c

@@ -4,6 +4,9 @@
 #include "zip.h"
 #include "stopif.h"
 #include "extractHistory.h"
+#include "incbin.h"
+
+INCBIN(MqxliffHistory, "mqxliffHistory.xsl");
 
 void usage(const char *name) {
 	printf("%s inputFile\n", name);
@@ -18,7 +21,7 @@ int main(int argc, char **argv) {
 	char *dot = strrchr(argv[1], '.');
 	Stopif(!dot, return 1, "Bad input file name!\n");
 
-	Stopif(!transformLoad(mqxliffHistory, sizeof(mqxliffHistory)), return 1, "Can't load transform!\n");
+	Stopif(!transformLoad((char*)gMqxliffHistoryData, gMqxliffHistorySize), return 1, "Can't load transform!\n");
 	readZIP(argv[1], historyFile);
 	transformCleanup();	
 

File diff suppressed because it is too large
+ 0 - 0
extractHistory.h


+ 289 - 0
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 MAX_PATH
+#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;
+                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 = g%s%s + sizeof(g%s%s);\n", prefix, name, s(kEnd), name, s(kData), name, s(kData));
+            fprintf(out, "INCBIN_CONST unsigned int %s%s%s = sizeof(g%s%s);\n", prefix, name, s(kSize), 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;
+}

+ 357 - 0
incbin.h

@@ -0,0 +1,357 @@
+/**
+ * @file incbin.h
+ * @author Dale Weiler
+ * @brief Utility for including binary files
+ *
+ * Facilities for including binary files into the current translation unit and
+ * making use from them externally in other translation units.
+ */
+#ifndef INCBIN_HDR
+#define INCBIN_HDR
+#include <limits.h>
+#if   defined(__AVX512BW__) || \
+      defined(__AVX512CD__) || \
+      defined(__AVX512DQ__) || \
+      defined(__AVX512ER__) || \
+      defined(__AVX512PF__) || \
+      defined(__AVX512VL__) || \
+      defined(__AVX512F__)
+# define INCBIN_ALIGNMENT_INDEX 6
+#elif defined(__AVX__)      || \
+      defined(__AVX2__)
+# define INCBIN_ALIGNMENT_INDEX 5
+#elif defined(__SSE__)      || \
+      defined(__SSE2__)     || \
+      defined(__SSE3__)     || \
+      defined(__SSSE3__)    || \
+      defined(__SSE4_1__)   || \
+      defined(__SSE4_2__)   || \
+      defined(__neon__)
+# define INCBIN_ALIGNMENT_INDEX 4
+#elif ULONG_MAX != 0xffffffffu
+# define INCBIN_ALIGNMENT_INDEX 3
+# else
+# define INCBIN_ALIGNMENT_INDEX 2
+#endif
+
+/* Lookup table of (1 << n) where `n' is `INCBIN_ALIGNMENT_INDEX' */
+#define INCBIN_ALIGN_SHIFT_0 1
+#define INCBIN_ALIGN_SHIFT_1 2
+#define INCBIN_ALIGN_SHIFT_2 4
+#define INCBIN_ALIGN_SHIFT_3 8
+#define INCBIN_ALIGN_SHIFT_4 16
+#define INCBIN_ALIGN_SHIFT_5 32
+#define INCBIN_ALIGN_SHIFT_6 64
+
+/* Actual alignment value */
+#define INCBIN_ALIGNMENT \
+    INCBIN_CONCATENATE( \
+        INCBIN_CONCATENATE(INCBIN_ALIGN_SHIFT, _), \
+        INCBIN_ALIGNMENT_INDEX)
+
+/* Stringize */
+#define INCBIN_STR(X) \
+    #X
+#define INCBIN_STRINGIZE(X) \
+    INCBIN_STR(X)
+/* Concatenate */
+#define INCBIN_CAT(X, Y) \
+    X ## Y
+#define INCBIN_CONCATENATE(X, Y) \
+    INCBIN_CAT(X, Y)
+/* Deferred macro expansion */
+#define INCBIN_EVAL(X) \
+    X
+#define INCBIN_INVOKE(N, ...) \
+    INCBIN_EVAL(N(__VA_ARGS__))
+
+/* Green Hills uses a different directive for including binary data */
+#if defined(__ghs__)
+#  define INCBIN_MACRO "\tINCBIN"
+#else
+#  define INCBIN_MACRO ".incbin"
+#endif
+
+#ifndef _MSC_VER
+#  define INCBIN_ALIGN \
+    __attribute__((aligned(INCBIN_ALIGNMENT)))
+#else
+#  define INCBIN_ALIGN __declspec(align(INCBIN_ALIGNMENT))
+#endif
+
+#if defined(__arm__) || /* GNU C and RealView */ \
+    defined(__arm) || /* Diab */ \
+    defined(_ARM) /* ImageCraft */
+#  define INCBIN_ARM
+#endif
+
+#ifdef __GNUC__
+/* Utilize .balign where supported */
+#  define INCBIN_ALIGN_HOST ".balign " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
+#  define INCBIN_ALIGN_BYTE ".balign 1\n"
+#elif defined(INCBIN_ARM)
+/*
+ * On arm assemblers, the alignment value is calculated as (1 << n) where `n' is
+ * the shift count. This is the value passed to `.align'
+ */
+#  define INCBIN_ALIGN_HOST ".align" INCBIN_STRINGIZE(INCBIN_ALIGNMENT_INDEX) "\n"
+#  define INCBIN_ALIGN_BYTE ".align 0\n"
+#else
+/* We assume other inline assembler's treat `.align' as `.balign' */
+#  define INCBIN_ALIGN_HOST ".align" INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
+#  define INCBIN_ALIGN_BYTE ".align 1\n"
+#endif
+
+/* INCBIN_CONST is used by incbin.c generated files */
+#if defined(__cplusplus)
+#  define INCBIN_EXTERNAL extern "C"
+#  define INCBIN_CONST    extern const
+#else
+#  define INCBIN_EXTERNAL extern
+#  define INCBIN_CONST    const
+#endif
+
+/**
+ * @brief Optionally override the linker section into which data is emitted.
+ *
+ * @warning If you use this facility, you'll have to deal with platform-specific linker output
+ * section naming on your own
+ *
+ * Overriding the default linker output section, e.g for esp8266/Arduino:
+ * @code
+ * #define INCBIN_OUTPUT_SECTION ".irom.text"
+ * #include "incbin.h"
+ * INCBIN(Foo, "foo.txt");
+ * // Data is emitted into program memory that never gets copied to RAM
+ * @endcode
+ */
+#if !defined(INCBIN_OUTPUT_SECTION)
+#  if defined(__APPLE__)
+#    define INCBIN_OUTPUT_SECTION         ".const_data"
+#  else
+#    define INCBIN_OUTPUT_SECTION         ".rodata"
+#  endif
+#endif
+
+#if defined(__APPLE__)
+/* The directives are different for Apple branded compilers */
+#  define INCBIN_SECTION         INCBIN_OUTPUT_SECTION "\n"
+#  define INCBIN_GLOBAL(NAME)    ".globl " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
+#  define INCBIN_INT             ".long "
+#  define INCBIN_MANGLE          "_"
+#  define INCBIN_BYTE            ".byte "
+#  define INCBIN_TYPE(...)
+#else
+#  define INCBIN_SECTION         ".section " INCBIN_OUTPUT_SECTION "\n"
+#  define INCBIN_GLOBAL(NAME)    ".global " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
+#  define INCBIN_INT             ".int "
+#  if defined(__USER_LABEL_PREFIX__)
+#    define INCBIN_MANGLE        INCBIN_STRINGIZE(__USER_LABEL_PREFIX__)
+#  else
+#    define INCBIN_MANGLE        ""
+#  endif
+#  if defined(INCBIN_ARM)
+/* On arm assemblers, `@' is used as a line comment token */
+#    define INCBIN_TYPE(NAME)    ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", %object\n"
+#  elif defined(__MINGW32__) || defined(__MINGW64__)
+/* Mingw doesn't support this directive either */
+#    define INCBIN_TYPE(NAME)
+#  else
+/* It's safe to use `@' on other architectures */
+#    define INCBIN_TYPE(NAME)    ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", @object\n"
+#  endif
+#  define INCBIN_BYTE            ".byte "
+#endif
+
+/* List of style types used for symbol names */
+#define INCBIN_STYLE_CAMEL 0
+#define INCBIN_STYLE_SNAKE 1
+
+/**
+ * @brief Specify the prefix to use for symbol names.
+ *
+ * By default this is `g', producing symbols of the form:
+ * @code
+ * #include "incbin.h"
+ * INCBIN(Foo, "foo.txt");
+ *
+ * // Now you have the following symbols:
+ * // const unsigned char gFooData[];
+ * // const unsigned char *const gFooEnd;
+ * // const unsigned int gFooSize;
+ * @endcode
+ *
+ * If however you specify a prefix before including: e.g:
+ * @code
+ * #define INCBIN_PREFIX incbin
+ * #include "incbin.h"
+ * INCBIN(Foo, "foo.txt");
+ *
+ * // Now you have the following symbols instead:
+ * // const unsigned char incbinFooData[];
+ * // const unsigned char *const incbinFooEnd;
+ * // const unsigned int incbinFooSize;
+ * @endcode
+ */
+#if !defined(INCBIN_PREFIX)
+#  define INCBIN_PREFIX g
+#endif
+
+/**
+ * @brief Specify the style used for symbol names.
+ *
+ * Possible options are
+ * - INCBIN_STYLE_CAMEL "CamelCase"
+ * - INCBIN_STYLE_SNAKE "snake_case"
+ *
+ * Default option is *INCBIN_STYLE_CAMEL* producing symbols of the form:
+ * @code
+ * #include "incbin.h"
+ * INCBIN(Foo, "foo.txt");
+ *
+ * // Now you have the following symbols:
+ * // const unsigned char <prefix>FooData[];
+ * // const unsigned char *const <prefix>FooEnd;
+ * // const unsigned int <prefix>FooSize;
+ * @endcode
+ *
+ * If however you specify a style before including: e.g:
+ * @code
+ * #define INCBIN_STYLE INCBIN_STYLE_SNAKE
+ * #include "incbin.h"
+ * INCBIN(foo, "foo.txt");
+ *
+ * // Now you have the following symbols:
+ * // const unsigned char <prefix>foo_data[];
+ * // const unsigned char *const <prefix>foo_end;
+ * // const unsigned int <prefix>foo_size;
+ * @endcode
+ */
+#if !defined(INCBIN_STYLE)
+#  define INCBIN_STYLE INCBIN_STYLE_CAMEL
+#endif
+
+/* Style lookup tables */
+#define INCBIN_STYLE_0_DATA Data
+#define INCBIN_STYLE_0_END End
+#define INCBIN_STYLE_0_SIZE Size
+#define INCBIN_STYLE_1_DATA _data
+#define INCBIN_STYLE_1_END _end
+#define INCBIN_STYLE_1_SIZE _size
+
+/* Style lookup: returning identifier */
+#define INCBIN_STYLE_IDENT(TYPE) \
+    INCBIN_CONCATENATE( \
+        INCBIN_STYLE_, \
+        INCBIN_CONCATENATE( \
+            INCBIN_EVAL(INCBIN_STYLE), \
+            INCBIN_CONCATENATE(_, TYPE)))
+
+/* Style lookup: returning string literal */
+#define INCBIN_STYLE_STRING(TYPE) \
+    INCBIN_STRINGIZE( \
+        INCBIN_STYLE_IDENT(TYPE)) \
+
+/* Generate the global labels by indirectly invoking the macro with our style
+ * type and concatenating the name against them. */
+#define INCBIN_GLOBAL_LABELS(NAME, TYPE) \
+    INCBIN_INVOKE( \
+        INCBIN_GLOBAL, \
+        INCBIN_CONCATENATE( \
+            NAME, \
+            INCBIN_INVOKE( \
+                INCBIN_STYLE_IDENT, \
+                TYPE))) \
+    INCBIN_INVOKE( \
+        INCBIN_TYPE, \
+        INCBIN_CONCATENATE( \
+            NAME, \
+            INCBIN_INVOKE( \
+                INCBIN_STYLE_IDENT, \
+                TYPE)))
+
+/**
+ * @brief Externally reference binary data included in another translation unit.
+ *
+ * Produces three external symbols that reference the binary data included in
+ * another translation unit.
+ *
+ * The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
+ * "Data", as well as "End" and "Size" after. An example is provided below.
+ *
+ * @param NAME The name given for the binary data
+ *
+ * @code
+ * INCBIN_EXTERN(Foo);
+ *
+ * // Now you have the following symbols:
+ * // extern const unsigned char <prefix>FooData[];
+ * // extern const unsigned char *const <prefix>FooEnd;
+ * // extern const unsigned int <prefix>FooSize;
+ * @endcode
+ */
+#define INCBIN_EXTERN(NAME) \
+    INCBIN_EXTERNAL const INCBIN_ALIGN unsigned char \
+        INCBIN_CONCATENATE( \
+            INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
+            INCBIN_STYLE_IDENT(DATA))[]; \
+    INCBIN_EXTERNAL const INCBIN_ALIGN unsigned char *const \
+    INCBIN_CONCATENATE( \
+        INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
+        INCBIN_STYLE_IDENT(END)); \
+    INCBIN_EXTERNAL const unsigned int \
+        INCBIN_CONCATENATE( \
+            INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
+            INCBIN_STYLE_IDENT(SIZE))
+
+/**
+ * @brief Include a binary file into the current translation unit.
+ *
+ * Includes a binary file into the current translation unit, producing three symbols
+ * for objects that encode the data and size respectively.
+ *
+ * The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
+ * "Data", as well as "End" and "Size" after. An example is provided below.
+ *
+ * @param NAME The name to associate with this binary data (as an identifier.)
+ * @param FILENAME The file to include (as a string literal.)
+ *
+ * @code
+ * INCBIN(Icon, "icon.png");
+ *
+ * // Now you have the following symbols:
+ * // const unsigned char <prefix>IconData[];
+ * // const unsigned char *const <prefix>IconEnd;
+ * // const unsigned int <prefix>IconSize;
+ * @endcode
+ *
+ * @warning This must be used in global scope
+ * @warning The identifiers may be different if INCBIN_STYLE is not default
+ *
+ * To externally reference the data included by this in another translation unit
+ * please @see INCBIN_EXTERN.
+ */
+#ifdef _MSC_VER
+#define INCBIN(NAME, FILENAME) \
+    INCBIN_EXTERN(NAME)
+#else
+#define INCBIN(NAME, FILENAME) \
+    __asm__(INCBIN_SECTION \
+            INCBIN_GLOBAL_LABELS(NAME, DATA) \
+            INCBIN_ALIGN_HOST \
+            INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) ":\n" \
+            INCBIN_MACRO " \"" FILENAME "\"\n" \
+            INCBIN_GLOBAL_LABELS(NAME, END) \
+            INCBIN_ALIGN_BYTE \
+            INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) ":\n" \
+                INCBIN_BYTE "1\n" \
+            INCBIN_GLOBAL_LABELS(NAME, SIZE) \
+            INCBIN_ALIGN_HOST \
+            INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(SIZE) ":\n" \
+                INCBIN_INT INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) " - " \
+                           INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) "\n" \
+    ); \
+    INCBIN_EXTERN(NAME)
+
+#endif
+#endif

+ 95 - 0
mqxliffHistory.xsl

@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions"
+	xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" xmlns:mq="MQXliff" xml:space="preserve">
+	<xsl:output method="html" encoding="UTF-8" indent="yes"/>
+	<xsl:template match="/">
+		<html>
+			<head>
+				<title>History for <xsl:value-of select="//xliff:file/@original" /></title>
+				<style>
+					table {
+						width: 100%;
+					}
+					td {
+						word-wrap: break-word;
+						overflow: hidden;
+					}
+					table, th, td {
+						border: 1px solid black;
+					}
+					caption {
+						font-weight: bold;
+					}
+				</style>
+			</head>
+			<body>
+				<table>
+					<caption>Versions</caption>
+					<tbody>
+						<tr>
+							<th>Version</th>
+							<th>Event</th>
+							<th>User</th>
+						</tr>
+						<xsl:apply-templates select="//mq:versioninfos" />						
+					</tbody>
+				</table>
+				<br/>
+				<table>
+					<caption>Segments</caption>
+					<tbody>
+						<xsl:apply-templates select="//xliff:body" />						
+					</tbody>
+				</table>
+			</body>
+		</html>
+	</xsl:template>
+	
+	<xsl:template match="//mq:versioninfos">
+	    <xsl:for-each select="mq:minorversioninfo">
+			 <tr>
+					<td><xsl:value-of select="./@mq:minorversion" /></td>
+					<td><xsl:value-of select="./@mq:createreason" /></td>
+					<td><xsl:value-of select="./@mq:creatoruser" /></td>
+			 </tr>
+	    </xsl:for-each>
+	</xsl:template>
+	
+	<xsl:template match="//xliff:body">
+		<xsl:for-each select="xliff:trans-unit">
+			<tr>
+				<th>Segment#</th>
+				<th>Version</th>
+				<th>Source</th>
+				<th>Target</th>
+				<th>Status</th>
+				<th>User</th>
+				<th>Date</th>
+			</tr>
+			 <tr>
+					<td><xsl:value-of select="./@id" /></td>
+					<td><xsl:text>Current</xsl:text></td>
+					<td><xsl:value-of select="./xliff:source/text()" /></td>
+					<td><xsl:value-of select="./xliff:target/text()" /></td>
+					<td><xsl:value-of select="./@mq:status" /></td>
+					<td><xsl:value-of select="./@mq:lastchanginguser" /></td>
+					<td><xsl:value-of select="./@mq:lastchangedtimestamp" /></td>
+			</tr>
+			<xsl:apply-templates select="mq:minorversions" />
+		</xsl:for-each>
+	</xsl:template>
+		
+	<xsl:template match="mq:minorversions">
+		<xsl:for-each select="mq:historical-unit">
+			 <tr>
+					<td></td>
+					<td><xsl:value-of select="./@mq:minorversionstart" /><xsl:text> - </xsl:text><xsl:value-of select="./@mq:minorversionend" /></td>
+					<td><xsl:value-of select="./xliff:source/text()" /></td>
+					<td><xsl:value-of select="./xliff:target/text()" /></td>
+					<td><xsl:value-of select="./@mq:status" /></td>
+					<td><xsl:value-of select="./@mq:lastchanginguser" /></td>
+					<td><xsl:value-of select="./@mq:lastchangedtimestamp" /></td>
+			 </tr>
+		</xsl:for-each>
+	</xsl:template>
+</xsl:stylesheet>

Some files were not shown because too many files changed in this diff