/**1* @file incbin.h2* @author Dale Weiler3* @brief Utility for including binary files4*5* Facilities for including binary files into the current translation unit and6* making use from them externally in other translation units.7*/8#ifndef INCBIN_HDR9#define INCBIN_HDR10#include <limits.h>11#if defined(__AVX512BW__) || \12defined(__AVX512CD__) || \13defined(__AVX512DQ__) || \14defined(__AVX512ER__) || \15defined(__AVX512PF__) || \16defined(__AVX512VL__) || \17defined(__AVX512F__)18# define INCBIN_ALIGNMENT_INDEX 619#elif defined(__AVX__) || \20defined(__AVX2__)21# define INCBIN_ALIGNMENT_INDEX 522#elif defined(__SSE__) || \23defined(__SSE2__) || \24defined(__SSE3__) || \25defined(__SSSE3__) || \26defined(__SSE4_1__) || \27defined(__SSE4_2__) || \28defined(__neon__) || \29defined(__ARM_NEON) || \30defined(__ALTIVEC__)31# define INCBIN_ALIGNMENT_INDEX 432#elif ULONG_MAX != 0xffffffffu33# define INCBIN_ALIGNMENT_INDEX 334# else35# define INCBIN_ALIGNMENT_INDEX 236#endif3738/* Lookup table of (1 << n) where `n' is `INCBIN_ALIGNMENT_INDEX' */39#define INCBIN_ALIGN_SHIFT_0 140#define INCBIN_ALIGN_SHIFT_1 241#define INCBIN_ALIGN_SHIFT_2 442#define INCBIN_ALIGN_SHIFT_3 843#define INCBIN_ALIGN_SHIFT_4 1644#define INCBIN_ALIGN_SHIFT_5 3245#define INCBIN_ALIGN_SHIFT_6 644647/* Actual alignment value */48#define INCBIN_ALIGNMENT \49INCBIN_CONCATENATE( \50INCBIN_CONCATENATE(INCBIN_ALIGN_SHIFT, _), \51INCBIN_ALIGNMENT_INDEX)5253/* Stringize */54#define INCBIN_STR(X) \55#X56#define INCBIN_STRINGIZE(X) \57INCBIN_STR(X)58/* Concatenate */59#define INCBIN_CAT(X, Y) \60X ## Y61#define INCBIN_CONCATENATE(X, Y) \62INCBIN_CAT(X, Y)63/* Deferred macro expansion */64#define INCBIN_EVAL(X) \65X66#define INCBIN_INVOKE(N, ...) \67INCBIN_EVAL(N(__VA_ARGS__))68/* Variable argument count for overloading by arity */69#define INCBIN_VA_ARG_COUNTER(_1, _2, _3, N, ...) N70#define INCBIN_VA_ARGC(...) INCBIN_VA_ARG_COUNTER(__VA_ARGS__, 3, 2, 1, 0)7172/* Green Hills uses a different directive for including binary data */73#if defined(__ghs__)74# if (__ghs_asm == 2)75# define INCBIN_MACRO ".file"76/* Or consider the ".myrawdata" entry in the ld file */77# else78# define INCBIN_MACRO "\tINCBIN"79# endif80#else81# define INCBIN_MACRO ".incbin"82#endif8384#ifndef _MSC_VER85# define INCBIN_ALIGN \86__attribute__((aligned(INCBIN_ALIGNMENT)))87#else88# define INCBIN_ALIGN __declspec(align(INCBIN_ALIGNMENT))89#endif9091#if defined(__arm__) || /* GNU C and RealView */ \92defined(__arm) || /* Diab */ \93defined(_ARM) /* ImageCraft */94# define INCBIN_ARM95#endif9697#ifdef __GNUC__98/* Utilize .balign where supported */99# define INCBIN_ALIGN_HOST ".balign " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"100# define INCBIN_ALIGN_BYTE ".balign 1\n"101#elif defined(INCBIN_ARM)102/*103* On arm assemblers, the alignment value is calculated as (1 << n) where `n' is104* the shift count. This is the value passed to `.align'105*/106# define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT_INDEX) "\n"107# define INCBIN_ALIGN_BYTE ".align 0\n"108#else109/* We assume other inline assembler's treat `.align' as `.balign' */110# define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"111# define INCBIN_ALIGN_BYTE ".align 1\n"112#endif113114/* INCBIN_CONST is used by incbin.c generated files */115#if defined(__cplusplus)116# define INCBIN_EXTERNAL extern "C"117# define INCBIN_CONST extern const118#else119# define INCBIN_EXTERNAL extern120# define INCBIN_CONST const121#endif122123/**124* @brief Optionally override the linker section into which size and data is125* emitted.126*127* @warning If you use this facility, you might have to deal with128* platform-specific linker output section naming on your own.129*/130#if !defined(INCBIN_OUTPUT_SECTION)131# if defined(__APPLE__)132# define INCBIN_OUTPUT_SECTION ".const_data"133# else134# define INCBIN_OUTPUT_SECTION ".rodata"135# endif136#endif137138/**139* @brief Optionally override the linker section into which data is emitted.140*141* @warning If you use this facility, you might have to deal with142* platform-specific linker output section naming on your own.143*/144#if !defined(INCBIN_OUTPUT_DATA_SECTION)145# define INCBIN_OUTPUT_DATA_SECTION INCBIN_OUTPUT_SECTION146#endif147148/**149* @brief Optionally override the linker section into which size is emitted.150*151* @warning If you use this facility, you might have to deal with152* platform-specific linker output section naming on your own.153*154* @note This is useful for Harvard architectures where program memory cannot155* be directly read from the program without special instructions. With this you156* can chose to put the size variable in RAM rather than ROM.157*/158#if !defined(INCBIN_OUTPUT_SIZE_SECTION)159# define INCBIN_OUTPUT_SIZE_SECTION INCBIN_OUTPUT_SECTION160#endif161162#if defined(__APPLE__)163# include "TargetConditionals.h"164# if defined(TARGET_OS_IPHONE) && !defined(INCBIN_SILENCE_BITCODE_WARNING)165# warning "incbin is incompatible with bitcode. Using the library will break upload to App Store if you have bitcode enabled. Add `#define INCBIN_SILENCE_BITCODE_WARNING` before including this header to silence this warning."166# endif167/* The directives are different for Apple branded compilers */168# define INCBIN_SECTION INCBIN_OUTPUT_SECTION "\n"169# define INCBIN_GLOBAL(NAME) ".globl " INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"170# define INCBIN_INT ".long "171# define INCBIN_MANGLE "_"172# define INCBIN_BYTE ".byte "173# define INCBIN_TYPE(...)174#else175# define INCBIN_SECTION ".section " INCBIN_OUTPUT_SECTION "\n"176# define INCBIN_GLOBAL(NAME) ".global " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"177# if defined(__ghs__)178# define INCBIN_INT ".word "179# else180# define INCBIN_INT ".int "181# endif182# if defined(__USER_LABEL_PREFIX__)183# define INCBIN_MANGLE INCBIN_STRINGIZE(__USER_LABEL_PREFIX__)184# else185# define INCBIN_MANGLE ""186# endif187# if defined(INCBIN_ARM)188/* On arm assemblers, `@' is used as a line comment token */189# define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", %object\n"190# elif defined(__MINGW32__) || defined(__MINGW64__)191/* Mingw doesn't support this directive either */192# define INCBIN_TYPE(NAME)193# else194/* It's safe to use `@' on other architectures */195# define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", @object\n"196# endif197# define INCBIN_BYTE ".byte "198#endif199200/* List of style types used for symbol names */201#define INCBIN_STYLE_CAMEL 0202#define INCBIN_STYLE_SNAKE 1203204/**205* @brief Specify the prefix to use for symbol names.206*207* @note By default this is "g".208*209* @code210* #define INCBIN_PREFIX incbin211* #include "incbin.h"212* INCBIN(Foo, "foo.txt");213*214* // Now you have the following symbols instead:215* // const unsigned char incbinFoo<data>[];216* // const unsigned char *const incbinFoo<end>;217* // const unsigned int incbinFoo<size>;218* @endcode219*/220#if !defined(INCBIN_PREFIX)221# define INCBIN_PREFIX g222#endif223224/**225* @brief Specify the style used for symbol names.226*227* Possible options are228* - INCBIN_STYLE_CAMEL "CamelCase"229* - INCBIN_STYLE_SNAKE "snake_case"230*231* @note By default this is INCBIN_STYLE_CAMEL232*233* @code234* #define INCBIN_STYLE INCBIN_STYLE_SNAKE235* #include "incbin.h"236* INCBIN(foo, "foo.txt");237*238* // Now you have the following symbols:239* // const unsigned char <prefix>foo_data[];240* // const unsigned char *const <prefix>foo_end;241* // const unsigned int <prefix>foo_size;242* @endcode243*/244#if !defined(INCBIN_STYLE)245# define INCBIN_STYLE INCBIN_STYLE_CAMEL246#endif247248/* Style lookup tables */249#define INCBIN_STYLE_0_DATA Data250#define INCBIN_STYLE_0_END End251#define INCBIN_STYLE_0_SIZE Size252#define INCBIN_STYLE_1_DATA _data253#define INCBIN_STYLE_1_END _end254#define INCBIN_STYLE_1_SIZE _size255256/* Style lookup: returning identifier */257#define INCBIN_STYLE_IDENT(TYPE) \258INCBIN_CONCATENATE( \259INCBIN_STYLE_, \260INCBIN_CONCATENATE( \261INCBIN_EVAL(INCBIN_STYLE), \262INCBIN_CONCATENATE(_, TYPE)))263264/* Style lookup: returning string literal */265#define INCBIN_STYLE_STRING(TYPE) \266INCBIN_STRINGIZE( \267INCBIN_STYLE_IDENT(TYPE)) \268269/* Generate the global labels by indirectly invoking the macro with our style270* type and concatenating the name against them. */271#define INCBIN_GLOBAL_LABELS(NAME, TYPE) \272INCBIN_INVOKE( \273INCBIN_GLOBAL, \274INCBIN_CONCATENATE( \275NAME, \276INCBIN_INVOKE( \277INCBIN_STYLE_IDENT, \278TYPE))) \279INCBIN_INVOKE( \280INCBIN_TYPE, \281INCBIN_CONCATENATE( \282NAME, \283INCBIN_INVOKE( \284INCBIN_STYLE_IDENT, \285TYPE)))286287/**288* @brief Externally reference binary data included in another translation unit.289*290* Produces three external symbols that reference the binary data included in291* another translation unit.292*293* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with294* "Data", as well as "End" and "Size" after. An example is provided below.295*296* @param TYPE Optional array type. Omitting this picks a default of `unsigned char`.297* @param NAME The name given for the binary data298*299* @code300* INCBIN_EXTERN(Foo);301*302* // Now you have the following symbols:303* // extern const unsigned char <prefix>Foo<data>[];304* // extern const unsigned char *const <prefix>Foo<end>;305* // extern const unsigned int <prefix>Foo<size>;306* @endcode307*308* You may specify a custom optional data type as well as the first argument.309* @code310* INCBIN_EXTERN(custom_type, Foo);311*312* // Now you have the following symbols:313* // extern const custom_type <prefix>Foo<data>[];314* // extern const custom_type *const <prefix>Foo<end>;315* // extern const unsigned int <prefix>Foo<size>;316* @endcode317*/318#define INCBIN_EXTERN(...) \319INCBIN_CONCATENATE(INCBIN_EXTERN_, INCBIN_VA_ARGC(__VA_ARGS__))(__VA_ARGS__)320#define INCBIN_EXTERN_1(NAME, ...) \321INCBIN_EXTERN_2(unsigned char, NAME)322#define INCBIN_EXTERN_2(TYPE, NAME) \323INCBIN_EXTERNAL const INCBIN_ALIGN TYPE \324INCBIN_CONCATENATE( \325INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \326INCBIN_STYLE_IDENT(DATA))[]; \327INCBIN_EXTERNAL const INCBIN_ALIGN TYPE *const \328INCBIN_CONCATENATE( \329INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \330INCBIN_STYLE_IDENT(END)); \331INCBIN_EXTERNAL const unsigned int \332INCBIN_CONCATENATE( \333INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \334INCBIN_STYLE_IDENT(SIZE))335336/**337* @brief Externally reference textual data included in another translation unit.338*339* Produces three external symbols that reference the textual data included in340* another translation unit.341*342* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with343* "Data", as well as "End" and "Size" after. An example is provided below.344*345* @param NAME The name given for the textual data346*347* @code348* INCBIN_EXTERN(Foo);349*350* // Now you have the following symbols:351* // extern const char <prefix>Foo<data>[];352* // extern const char *const <prefix>Foo<end>;353* // extern const unsigned int <prefix>Foo<size>;354* @endcode355*/356#define INCTXT_EXTERN(NAME) \357INCBIN_EXTERN_2(char, NAME)358359/**360* @brief Include a binary file into the current translation unit.361*362* Includes a binary file into the current translation unit, producing three symbols363* for objects that encode the data and size respectively.364*365* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with366* "Data", as well as "End" and "Size" after. An example is provided below.367*368* @param TYPE Optional array type. Omitting this picks a default of `unsigned char`.369* @param NAME The name to associate with this binary data (as an identifier.)370* @param FILENAME The file to include (as a string literal.)371*372* @code373* INCBIN(Icon, "icon.png");374*375* // Now you have the following symbols:376* // const unsigned char <prefix>Icon<data>[];377* // const unsigned char *const <prefix>Icon<end>;378* // const unsigned int <prefix>Icon<size>;379* @endcode380*381* You may specify a custom optional data type as well as the first argument.382* These macros are specialized by arity.383* @code384* INCBIN(custom_type, Icon, "icon.png");385*386* // Now you have the following symbols:387* // const custom_type <prefix>Icon<data>[];388* // const custom_type *const <prefix>Icon<end>;389* // const unsigned int <prefix>Icon<size>;390* @endcode391*392* @warning This must be used in global scope393* @warning The identifiers may be different if INCBIN_STYLE is not default394*395* To externally reference the data included by this in another translation unit396* please @see INCBIN_EXTERN.397*/398#ifdef _MSC_VER399# define INCBIN(NAME, FILENAME) \400INCBIN_EXTERN(NAME)401#else402# define INCBIN(...) \403INCBIN_CONCATENATE(INCBIN_, INCBIN_VA_ARGC(__VA_ARGS__))(__VA_ARGS__)404# if defined(__GNUC__)405# define INCBIN_1(...) _Pragma("GCC error \"Single argument INCBIN not allowed\"")406# elif defined(__clang__)407# define INCBIN_1(...) _Pragma("clang error \"Single argument INCBIN not allowed\"")408# else409# define INCBIN_1(...) /* Cannot do anything here */410# endif411# define INCBIN_2(NAME, FILENAME) \412INCBIN_3(unsigned char, NAME, FILENAME)413# define INCBIN_3(TYPE, NAME, FILENAME) INCBIN_COMMON(TYPE, NAME, FILENAME, /* No terminator for binary data */)414# define INCBIN_COMMON(TYPE, NAME, FILENAME, TERMINATOR) \415__asm__(INCBIN_SECTION \416INCBIN_GLOBAL_LABELS(NAME, DATA) \417INCBIN_ALIGN_HOST \418INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) ":\n" \419INCBIN_MACRO " \"" FILENAME "\"\n" \420TERMINATOR \421INCBIN_GLOBAL_LABELS(NAME, END) \422INCBIN_ALIGN_BYTE \423INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) ":\n" \424INCBIN_BYTE "1\n" \425INCBIN_GLOBAL_LABELS(NAME, SIZE) \426INCBIN_ALIGN_HOST \427INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(SIZE) ":\n" \428INCBIN_INT INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) " - " \429INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) "\n" \430INCBIN_ALIGN_HOST \431".text\n" \432); \433INCBIN_EXTERN(TYPE, NAME)434#endif435436/**437* @brief Include a textual file into the current translation unit.438*439* This behaves the same as INCBIN except it produces char compatible arrays440* and implicitly adds a null-terminator byte, thus the size of data included441* by this is one byte larger than that of INCBIN.442*443* Includes a textual file into the current translation unit, producing three444* symbols for objects that encode the data and size respectively.445*446* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with447* "Data", as well as "End" and "Size" after. An example is provided below.448*449* @param NAME The name to associate with this binary data (as an identifier.)450* @param FILENAME The file to include (as a string literal.)451*452* @code453* INCTXT(Readme, "readme.txt");454*455* // Now you have the following symbols:456* // const char <prefix>Readme<data>[];457* // const char *const <prefix>Readme<end>;458* // const unsigned int <prefix>Readme<size>;459* @endcode460*461* @warning This must be used in global scope462* @warning The identifiers may be different if INCBIN_STYLE is not default463*464* To externally reference the data included by this in another translation unit465* please @see INCBIN_EXTERN.466*/467#if defined(_MSC_VER)468# define INCTXT(NAME, FILENAME) \469INCBIN_EXTERN(NAME)470#else471# define INCTXT(NAME, FILENAME) \472INCBIN_COMMON(char, NAME, FILENAME, INCBIN_BYTE "0\n")473#endif474475#endif476477