| /** |
| * @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 |