1+ /**
2+ * @file incbin.h
3+ * @author Dale Weiler
4+ * @brief Utility for including binary files
5+ *
6+ * Facilities for including binary files into the current translation unit and
7+ * making use from them externally in other translation units.
8+ */
9+ #ifndef INCBIN_HDR
10+ #define INCBIN_HDR
11+ #include <limits.h>
12+ #if defined(__AVX512BW__ ) || \
13+ defined(__AVX512CD__ ) || \
14+ defined(__AVX512DQ__ ) || \
15+ defined(__AVX512ER__ ) || \
16+ defined(__AVX512PF__ ) || \
17+ defined(__AVX512VL__ ) || \
18+ defined(__AVX512F__ )
19+ # define INCBIN_ALIGNMENT_INDEX 6
20+ #elif defined(__AVX__ ) || \
21+ defined(__AVX2__ )
22+ # define INCBIN_ALIGNMENT_INDEX 5
23+ #elif defined(__SSE__ ) || \
24+ defined(__SSE2__ ) || \
25+ defined(__SSE3__ ) || \
26+ defined(__SSSE3__ ) || \
27+ defined(__SSE4_1__ ) || \
28+ defined(__SSE4_2__ ) || \
29+ defined(__neon__ )
30+ # define INCBIN_ALIGNMENT_INDEX 4
31+ #elif ULONG_MAX != 0xffffffffu
32+ # define INCBIN_ALIGNMENT_INDEX 3
33+ # else
34+ # define INCBIN_ALIGNMENT_INDEX 2
35+ #endif
36+
37+ /* Lookup table of (1 << n) where `n' is `INCBIN_ALIGNMENT_INDEX' */
38+ #define INCBIN_ALIGN_SHIFT_0 1
39+ #define INCBIN_ALIGN_SHIFT_1 2
40+ #define INCBIN_ALIGN_SHIFT_2 4
41+ #define INCBIN_ALIGN_SHIFT_3 8
42+ #define INCBIN_ALIGN_SHIFT_4 16
43+ #define INCBIN_ALIGN_SHIFT_5 32
44+ #define INCBIN_ALIGN_SHIFT_6 64
45+
46+ /* Actual alignment value */
47+ #define INCBIN_ALIGNMENT \
48+ INCBIN_CONCATENATE( \
49+ INCBIN_CONCATENATE(INCBIN_ALIGN_SHIFT, _), \
50+ INCBIN_ALIGNMENT_INDEX)
51+
52+ /* Stringize */
53+ #define INCBIN_STR (X ) \
54+ #X
55+ #define INCBIN_STRINGIZE (X ) \
56+ INCBIN_STR(X)
57+ /* Concatenate */
58+ #define INCBIN_CAT (X , Y ) \
59+ X ## Y
60+ #define INCBIN_CONCATENATE (X , Y ) \
61+ INCBIN_CAT(X, Y)
62+ /* Deferred macro expansion */
63+ #define INCBIN_EVAL (X ) \
64+ X
65+ #define INCBIN_INVOKE (N , ...) \
66+ INCBIN_EVAL(N(__VA_ARGS__))
67+
68+ /* Green Hills uses a different directive for including binary data */
69+ #if defined(__ghs__ )
70+ # if (__ghs_asm == 2 )
71+ # define INCBIN_MACRO ".file"
72+ /* Or consider the ".myrawdata" entry in the ld file */
73+ # else
74+ # define INCBIN_MACRO "\tINCBIN"
75+ # endif
76+ #else
77+ # define INCBIN_MACRO ".incbin"
78+ #endif
79+
80+ #ifndef _MSC_VER
81+ # define INCBIN_ALIGN \
82+ __attribute__((aligned(INCBIN_ALIGNMENT)))
83+ #else
84+ # define INCBIN_ALIGN __declspec(align(INCBIN_ALIGNMENT))
85+ #endif
86+
87+ #if defined(__arm__ ) || /* GNU C and RealView */ \
88+ defined(__arm ) || /* Diab */ \
89+ defined(_ARM ) /* ImageCraft */
90+ # define INCBIN_ARM
91+ #endif
92+
93+ #ifdef __GNUC__
94+ /* Utilize .balign where supported */
95+ # define INCBIN_ALIGN_HOST ".balign " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
96+ # define INCBIN_ALIGN_BYTE ".balign 1\n"
97+ #elif defined(INCBIN_ARM )
98+ /*
99+ * On arm assemblers, the alignment value is calculated as (1 << n) where `n' is
100+ * the shift count. This is the value passed to `.align'
101+ */
102+ # define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT_INDEX) "\n"
103+ # define INCBIN_ALIGN_BYTE ".align 0\n"
104+ #else
105+ /* We assume other inline assembler's treat `.align' as `.balign' */
106+ # define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
107+ # define INCBIN_ALIGN_BYTE ".align 1\n"
108+ #endif
109+
110+ /* INCBIN_CONST is used by incbin.c generated files */
111+ #if defined(__cplusplus )
112+ # define INCBIN_EXTERNAL extern "C"
113+ # define INCBIN_CONST extern const
114+ #else
115+ # define INCBIN_EXTERNAL extern
116+ # define INCBIN_CONST const
117+ #endif
118+
119+ /**
120+ * @brief Optionally override the linker section into which data is emitted.
121+ *
122+ * @warning If you use this facility, you'll have to deal with platform-specific linker output
123+ * section naming on your own
124+ *
125+ * Overriding the default linker output section, e.g for esp8266/Arduino:
126+ * @code
127+ * #define INCBIN_OUTPUT_SECTION ".irom.text"
128+ * #include "incbin.h"
129+ * INCBIN(Foo, "foo.txt");
130+ * // Data is emitted into program memory that never gets copied to RAM
131+ * @endcode
132+ */
133+ #if !defined(INCBIN_OUTPUT_SECTION )
134+ # if defined(__APPLE__ )
135+ # define INCBIN_OUTPUT_SECTION ".const_data"
136+ # else
137+ # define INCBIN_OUTPUT_SECTION ".rodata"
138+ # endif
139+ #endif
140+
141+ #if defined(__APPLE__ )
142+ /* The directives are different for Apple branded compilers */
143+ # define INCBIN_SECTION INCBIN_OUTPUT_SECTION "\n"
144+ # define INCBIN_GLOBAL (NAME ) ".globl " INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
145+ # define INCBIN_INT ".long "
146+ # define INCBIN_MANGLE "_"
147+ # define INCBIN_BYTE ".byte "
148+ # define INCBIN_TYPE (...)
149+ #else
150+ # define INCBIN_SECTION ".section " INCBIN_OUTPUT_SECTION "\n"
151+ # define INCBIN_GLOBAL (NAME ) ".global " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
152+ # if defined(__ghs__ )
153+ # define INCBIN_INT ".word "
154+ # else
155+ # define INCBIN_INT ".int "
156+ # endif
157+ # if defined(__USER_LABEL_PREFIX__ )
158+ # define INCBIN_MANGLE INCBIN_STRINGIZE(__USER_LABEL_PREFIX__)
159+ # else
160+ # define INCBIN_MANGLE ""
161+ # endif
162+ # if defined(INCBIN_ARM )
163+ /* On arm assemblers, `@' is used as a line comment token */
164+ # define INCBIN_TYPE (NAME ) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", %object\n"
165+ # elif defined(__MINGW32__ ) || defined(__MINGW64__ )
166+ /* Mingw doesn't support this directive either */
167+ # define INCBIN_TYPE (NAME )
168+ # else
169+ /* It's safe to use `@' on other architectures */
170+ # define INCBIN_TYPE (NAME ) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", @object\n"
171+ # endif
172+ # define INCBIN_BYTE ".byte "
173+ #endif
174+
175+ /* List of style types used for symbol names */
176+ #define INCBIN_STYLE_CAMEL 0
177+ #define INCBIN_STYLE_SNAKE 1
178+
179+ /**
180+ * @brief Specify the prefix to use for symbol names.
181+ *
182+ * By default this is `g', producing symbols of the form:
183+ * @code
184+ * #include "incbin.h"
185+ * INCBIN(Foo, "foo.txt");
186+ *
187+ * // Now you have the following symbols:
188+ * // const unsigned char gFooData[];
189+ * // const unsigned char *const gFooEnd;
190+ * // const unsigned int gFooSize;
191+ * @endcode
192+ *
193+ * If however you specify a prefix before including: e.g:
194+ * @code
195+ * #define INCBIN_PREFIX incbin
196+ * #include "incbin.h"
197+ * INCBIN(Foo, "foo.txt");
198+ *
199+ * // Now you have the following symbols instead:
200+ * // const unsigned char incbinFooData[];
201+ * // const unsigned char *const incbinFooEnd;
202+ * // const unsigned int incbinFooSize;
203+ * @endcode
204+ */
205+ #if !defined(INCBIN_PREFIX )
206+ # define INCBIN_PREFIX g
207+ #endif
208+
209+ /**
210+ * @brief Specify the style used for symbol names.
211+ *
212+ * Possible options are
213+ * - INCBIN_STYLE_CAMEL "CamelCase"
214+ * - INCBIN_STYLE_SNAKE "snake_case"
215+ *
216+ * Default option is *INCBIN_STYLE_CAMEL* producing symbols of the form:
217+ * @code
218+ * #include "incbin.h"
219+ * INCBIN(Foo, "foo.txt");
220+ *
221+ * // Now you have the following symbols:
222+ * // const unsigned char <prefix>FooData[];
223+ * // const unsigned char *const <prefix>FooEnd;
224+ * // const unsigned int <prefix>FooSize;
225+ * @endcode
226+ *
227+ * If however you specify a style before including: e.g:
228+ * @code
229+ * #define INCBIN_STYLE INCBIN_STYLE_SNAKE
230+ * #include "incbin.h"
231+ * INCBIN(foo, "foo.txt");
232+ *
233+ * // Now you have the following symbols:
234+ * // const unsigned char <prefix>foo_data[];
235+ * // const unsigned char *const <prefix>foo_end;
236+ * // const unsigned int <prefix>foo_size;
237+ * @endcode
238+ */
239+ #if !defined(INCBIN_STYLE )
240+ # define INCBIN_STYLE INCBIN_STYLE_CAMEL
241+ #endif
242+
243+ /* Style lookup tables */
244+ #define INCBIN_STYLE_0_DATA Data
245+ #define INCBIN_STYLE_0_END End
246+ #define INCBIN_STYLE_0_SIZE Size
247+ #define INCBIN_STYLE_1_DATA _data
248+ #define INCBIN_STYLE_1_END _end
249+ #define INCBIN_STYLE_1_SIZE _size
250+
251+ /* Style lookup: returning identifier */
252+ #define INCBIN_STYLE_IDENT (TYPE ) \
253+ INCBIN_CONCATENATE( \
254+ INCBIN_STYLE_, \
255+ INCBIN_CONCATENATE( \
256+ INCBIN_EVAL(INCBIN_STYLE), \
257+ INCBIN_CONCATENATE(_, TYPE)))
258+
259+ /* Style lookup: returning string literal */
260+ #define INCBIN_STYLE_STRING (TYPE ) \
261+ INCBIN_STRINGIZE( \
262+ INCBIN_STYLE_IDENT(TYPE)) \
263+
264+ /* Generate the global labels by indirectly invoking the macro with our style
265+ * type and concatenating the name against them. */
266+ #define INCBIN_GLOBAL_LABELS (NAME , TYPE ) \
267+ INCBIN_INVOKE( \
268+ INCBIN_GLOBAL, \
269+ INCBIN_CONCATENATE( \
270+ NAME, \
271+ INCBIN_INVOKE( \
272+ INCBIN_STYLE_IDENT, \
273+ TYPE))) \
274+ INCBIN_INVOKE( \
275+ INCBIN_TYPE, \
276+ INCBIN_CONCATENATE( \
277+ NAME, \
278+ INCBIN_INVOKE( \
279+ INCBIN_STYLE_IDENT, \
280+ TYPE)))
281+
282+ /**
283+ * @brief Externally reference binary data included in another translation unit.
284+ *
285+ * Produces three external symbols that reference the binary data included in
286+ * another translation unit.
287+ *
288+ * The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
289+ * "Data", as well as "End" and "Size" after. An example is provided below.
290+ *
291+ * @param NAME The name given for the binary data
292+ *
293+ * @code
294+ * INCBIN_EXTERN(Foo);
295+ *
296+ * // Now you have the following symbols:
297+ * // extern const unsigned char <prefix>FooData[];
298+ * // extern const unsigned char *const <prefix>FooEnd;
299+ * // extern const unsigned int <prefix>FooSize;
300+ * @endcode
301+ */
302+ #define INCBIN_EXTERN (NAME ) \
303+ INCBIN_EXTERNAL const INCBIN_ALIGN unsigned char \
304+ INCBIN_CONCATENATE( \
305+ INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
306+ INCBIN_STYLE_IDENT(DATA))[]; \
307+ INCBIN_EXTERNAL const INCBIN_ALIGN unsigned char *const \
308+ INCBIN_CONCATENATE( \
309+ INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
310+ INCBIN_STYLE_IDENT(END)); \
311+ INCBIN_EXTERNAL const unsigned int \
312+ INCBIN_CONCATENATE( \
313+ INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
314+ INCBIN_STYLE_IDENT(SIZE))
315+
316+ /**
317+ * @brief Include a binary file into the current translation unit.
318+ *
319+ * Includes a binary file into the current translation unit, producing three symbols
320+ * for objects that encode the data and size respectively.
321+ *
322+ * The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
323+ * "Data", as well as "End" and "Size" after. An example is provided below.
324+ *
325+ * @param NAME The name to associate with this binary data (as an identifier.)
326+ * @param FILENAME The file to include (as a string literal.)
327+ *
328+ * @code
329+ * INCBIN(Icon, "icon.png");
330+ *
331+ * // Now you have the following symbols:
332+ * // const unsigned char <prefix>IconData[];
333+ * // const unsigned char *const <prefix>IconEnd;
334+ * // const unsigned int <prefix>IconSize;
335+ * @endcode
336+ *
337+ * @warning This must be used in global scope
338+ * @warning The identifiers may be different if INCBIN_STYLE is not default
339+ *
340+ * To externally reference the data included by this in another translation unit
341+ * please @see INCBIN_EXTERN.
342+ */
343+ #ifdef _MSC_VER
344+ #define INCBIN (NAME , FILENAME ) \
345+ INCBIN_EXTERN(NAME)
346+ #else
347+ #define INCBIN (NAME , FILENAME ) \
348+ __asm__(INCBIN_SECTION \
349+ INCBIN_GLOBAL_LABELS(NAME, DATA) \
350+ INCBIN_ALIGN_HOST \
351+ INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) ":\n" \
352+ INCBIN_MACRO " \"" FILENAME "\"\n" \
353+ INCBIN_GLOBAL_LABELS(NAME, END) \
354+ INCBIN_ALIGN_BYTE \
355+ INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) ":\n" \
356+ INCBIN_BYTE "1\n" \
357+ INCBIN_GLOBAL_LABELS(NAME, SIZE) \
358+ INCBIN_ALIGN_HOST \
359+ INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(SIZE) ":\n" \
360+ INCBIN_INT INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) " - " \
361+ INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) "\n" \
362+ INCBIN_ALIGN_HOST \
363+ ".text\n" \
364+ ); \
365+ INCBIN_EXTERN(NAME)
366+
367+ #endif
368+ #endif
0 commit comments