123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369 |
- /**
- * @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__)
- # if (__ghs_asm == 2)
- # define INCBIN_MACRO ".file"
- /* Or consider the ".myrawdata" entry in the ld file */
- # else
- # define INCBIN_MACRO "\tINCBIN"
- # endif
- #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_MANGLE 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"
- # if defined(__ghs__)
- # define INCBIN_INT ".word "
- # else
- # define INCBIN_INT ".int "
- # endif
- # 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_ALIGN_HOST \
- ".text\n" \
- ); \
- INCBIN_EXTERN(NAME)
- #endif
- #endif
|