1 /*****************************************************************************/
2 /* LibreDWG - free implementation of the DWG file format */
3 /* */
4 /* Copyright (C) 2009-2023 Free Software Foundation, Inc. */
5 /* */
6 /* This library is free software, licensed under the terms of the GNU */
7 /* General Public License as published by the Free Software Foundation, */
8 /* either version 3 of the License, or (at your option) any later version. */
9 /* You should have received a copy of the GNU General Public License */
10 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
11 /*****************************************************************************/
12
13 /*
14 * common.h: common general functions and macros
15 * written by Felipe Castro
16 * modified by Felipe Corrêa da Silva Sances
17 * modified by Rodrigo Rodrigues da Silva
18 * modified by Reini Urban
19 */
20
21 #ifndef COMMON_H
22 #define COMMON_H
23
24 #ifndef _DEFAULT_SOURCE
25 # define _DEFAULT_SOURCE 1 /* for __USE_MISC byteswap macros */
26 #endif
27 #ifdef __XSI_VISIBLE
28 # undef __XSI_VISIBLE /* redefined in config.h (cygwin strdup only) */
29 #endif
30 #include "config.h"
31 #include <stddef.h>
32 #include <stdint.h>
33 #include <inttypes.h>
34 #include <stdbool.h>
35 #include <math.h>
36 #include <time.h>
37 #include "dwg.h"
38
39 //#pragma pack()
40 // use as printf("%" PRIuSIZE ", size)
41 #ifndef PRI_SIZE_T_MODIFIER
42 # ifdef _WIN32
43 # if SIZEOF_SIZE_T == 8
44 # define PRI_SIZE_T_MODIFIER "ll"
45 # else
46 # define PRI_SIZE_T_MODIFIER ""
47 # endif
48 # else
49 # if SIZEOF_SIZE_T == 8
50 # define PRI_SIZE_T_MODIFIER "l"
51 # else
52 # define PRI_SIZE_T_MODIFIER ""
53 # endif
54 # endif
55 #endif
56 #define PRIuSIZE PRI_SIZE_T_MODIFIER "u"
57
58 // DoS limits
59 // limit number of vector elements to BS range
60 #define MAX_NUM 0xFFFE
61 // strings also 16bits
62 #define MAX_SIZE_TF 0xFFF0
63 #define MAX_SIZE_T 0xFFFE
64
65 #if !defined AX_STRCASECMP_HEADER && !defined HAVE_STRCASECMP
66 EXPORT int strcasecmp (const char *a, const char *b);
67 #else
68 # include AX_STRCASECMP_HEADER
69 #endif
70
71 #if defined WORDS_BIGENDIAN && !WORDS_BIGENDIAN
72 # undef WORDS_BIGENDIAN
73 #endif
74
75 #ifdef HAVE_ENDIAN_H
76 //#pragma message "_DEFAULT_SOURCE: " _DEFAULT_SOURCE
77 //#pragma message "HAVE_HTOBE64: " HAVE_HTOBE64
78 //#pragma message "HAVE_BYTESWAP_H: " HAVE_BYTESWAP_H
79 //#pragma message "__USE_MISC: " __USE_MISC
80 //#pragma message "LITTLE_ENDIAN: " LITTLE_ENDIAN
81 # include <endian.h>
82 //#pragma message "htobe64: " htobe64
83 // centos 7/glibc quirks
84 # if defined(HAVE_BYTESWAP_H) && !defined(htobe64)
85 # include <byteswap.h>
86 # ifndef WORDS_BIGENDIAN
87 # define le16toh(x) (x)
88 # define htole32(x) (x)
89 # define le32toh(x) (x)
90 # define htole64(x) (x)
91 # define le64toh(x) (x)
92 # define htobe16(x) bswap_16 (x)
93 # define htobe32(x) bswap_32 (x)
94 # define htobe64(x) bswap_64 (x)
95 # define be64toh(x) bswap_64 (x)
96 # else
97 # define le16toh(x) bswap_16 (x)
98 # define htole32(x) bswap_32 (x)
99 # define le32toh(x) bswap_32 (x)
100 # define htole64(x) bswap_64 (x)
101 # define le64toh(x) bswap_64 (x)
102 # define htobe16(x) (x)
103 # define htobe32(x) (x)
104 # define htobe64(x) (x)
105 # define be64toh(x) (x)
106 # endif
107 # endif
108 #elif defined HAVE_SYS_ENDIAN_H
109 # include <sys/endian.h>
110 #elif defined HAVE_MACHINE_ENDIAN_H && defined __APPLE__
111 # include <machine/endian.h>
112 # include <libkern/OSByteOrder.h>
113 # define le16toh OSSwapLittleToHostInt16
114 # define htole32 OSSwapHostToLittleInt32
115 # define le32toh OSSwapLittleToHostInt32
116 # define htole64 OSSwapHostToLittleInt64
117 # define le64toh OSSwapLittleToHostInt64
118 # define htobe16 OSSwapHostToBigInt16
119 # define htobe32 OSSwapHostToBigInt32
120 # define htobe64 OSSwapHostToBigInt64
121 # define be64toh OSSwapBigToHostInt64
122 #elif defined HAVE_WINSOCK2_H && defined __WINDOWS__
123 # include <winsock2.h>
124 # ifndef WORDS_BIGENDIAN
125 # define le16toh(x) (x)
126 # define htole32(x) (x)
127 # define le32toh(x) (x)
128 # define htole64(x) (x)
129 # define le64toh(x) (x)
130 # define htobe16(x) __builtin_bswap16 (x)
131 # define htobe32(x) __builtin_bswap32 (x)
132 # define htobe64(x) __builtin_bswap64 (x)
133 # define be64toh(x) __builtin_bswap64 (x)
134 # else /* e.g. xbox 360 */
135 # define le16toh(x) __builtin_bswap16 (x)
136 # define htole32(x) __builtin_bswap32 (x)
137 # define le32toh(x) __builtin_bswap32 (x)
138 # define htole64(x) __builtin_bswap64 (x)
139 # define le64toh(x) __builtin_bswap64 (x)
140 # define htobe16(x) (x)
141 # define htobe32(x) (x)
142 # define htobe64(x) (x)
143 # define be64toh(x) (x)
144 # endif
145 #elif defined WORDS_BIGENDIAN
146 /* TODO more converters */
147 # if defined HAVE_SYS_PARAM_H
148 # include <sys/param.h>
149 # endif
150 # if defined HAVE_SYS_BYTEORDER_H
151 /* e.g. solaris */
152 # include <sys/byteorder.h>
153 # define le16toh(x) BSWAP_16 (x)
154 # define htole32(x) BSWAP_32 (x)
155 # define le32toh(x) BSWAP_32 (x)
156 # define htole64(x) BSWAP_64 (x)
157 # define le64toh(x) BSWAP_64 (x)
158 # define htobe16(x) (x)
159 # define htobe32(x) (x)
160 # define htobe64(x) (x)
161 # define be64toh(x) (x)
162 # elif defined HAVE_BYTESWAP_H
163 # include <byteswap.h>
164 # define le16toh(x) bswap16 (x)
165 # define htole32(x) bswap32 (x)
166 # define le32toh(x) bswap32 (x)
167 # define htole64(x) bswap64 (x)
168 # define le64toh(x) bswap64 (x)
169 # define htobe16(x) (x)
170 # define htobe32(x) (x)
171 # define htobe64(x) (x)
172 # define be64toh(x) (x)
173 # elif defined HAVE_BYTEORDER_H
174 # include <byteorder.h>
175 /* which os? riot-os */
176 # ifdef RIOT_VERSION
177 # define le16toh(x) byteorder_swap (x)
178 # define htole32(x) byteorder_swapl (x)
179 # define le32toh(x) byteorder_swapl (x)
180 # define htole64(x) byteorder_swapll (x)
181 # define le64toh(x) byteorder_swapll (x)
182 # define htobe16(x) (x)
183 # define htobe32(x) (x)
184 # define htobe64(x) (x)
185 # define be64toh(x) (x)
186 # else
187 /* rtems/libcpu: ... */
188 # error unsupported big-endian platform with byteorder.h
189 # endif
190 # else
191 # error unsupported big-endian platform
192 # endif
193 #else /* little endian: just pass-thru. i.e. mingw */
194 # define NO_BYTESWAP_SUPPORT
195 // Warning: evaluates x times!
196 # define bswap_constant_16(x) ((((x) >> 8) & 0xff) | (((x)&0xff) << 8))
197 # define bswap_constant_32(x) \
198 ((((x)&0xff000000) >> 24) | (((x)&0x00ff0000) >> 8) \
199 | (((x)&0x0000ff00) << 8) | (((x)&0x000000ff) << 24))
200 # define bswap_constant_64(x) \
201 ((((x)&0xff00000000000000ULL) >> 56) \
202 | (((x)&0x00ff000000000000ULL) >> 40) \
203 | (((x)&0x0000ff0000000000ULL) >> 24) \
204 | (((x)&0x000000ff00000000ULL) >> 8) \
205 | (((x)&0x00000000ff000000ULL) << 8) \
206 | (((x)&0x0000000000ff0000ULL) << 24) \
207 | (((x)&0x000000000000ff00ULL) << 40) \
208 | (((x)&0x00000000000000ffULL) << 56))
209
210 # define le16toh(x) (x)
211 # define htole32(x) (x)
212 # define le32toh(x) (x)
213 # define htole64(x) (x)
214 # define le64toh(x) (x)
215 # define htobe16(x) bswap_constant_16 (x)
216 # define htobe32(x) bswap_constant_32 (x)
217 # define htobe64(x) bswap_constant_64 (x)
218 # define be64toh(x) bswap_constant_64 (x)
219 #endif
220
221 #ifdef ENABLE_MIMALLOC
222 # include <mimalloc-override.h>
223 #endif
224
225 /* Used warning suppressions:
226 CLANG_DIAG_IGNORE (-Wpragma-pack)
227 CLANG_DIAG_IGNORE (-Wmissing-prototypes) - also in gcc since 2.95, but not
228 needed CLANG_DIAG_RESTORE
229
230 GCC80_DIAG_IGNORE (-Wmaybe-uninitialized)
231 GCC80_DIAG_IGNORE (-Wstringop-truncation)
232 GCC80_DIAG_IGNORE (-Wstringop-overflow)
233 GCC46_DIAG_IGNORE (-Wformat-nonliteral) + GCC46_DIAG_RESTORE
234 GCC46_DIAG_IGNORE (-Wmissing-field-initializers) 4.7.1
235 GCC30_DIAG_IGNORE (-Wformat-nonliteral) w/o
236 GCC31_DIAG_IGNORE (-Wdeprecated-declarations)
237 GCC30_DIAG_IGNORE (-Wshadow)
238 */
239 #if defined(__GNUC__)
240 # define _GNUC_VERSION ((__GNUC__ * 100) + __GNUC_MINOR__)
241 # define CC_DIAG_PRAGMA(x) _Pragma (# x)
242 #else
243 # define _GNUC_VERSION 0
244 # define CC_DIAG_PRAGMA(x)
245 #endif
246
247 #define _STR(s) #s
248 #define _XSTR(s) _STR (s)
249 // #pragma message("_GNUC_VERSION " _XSTR(_GNUC_VERSION))
250
251 // clang-specifics (rarely needed, as they mimic GCC diagnostics closely, even
252 // down to bugs)
253 #if defined(__clang__) || defined(__clang)
254 # define HAVE_CLANG
255 # define CLANG_DIAG_IGNORE(x) \
256 _Pragma ("clang diagnostic push") \
257 CC_DIAG_PRAGMA (clang diagnostic ignored #x)
258 # define CLANG_DIAG_RESTORE _Pragma ("clang diagnostic pop")
259 #elif defined(__GNUC__)
260 # define CLANG_DIAG_IGNORE(w)
261 # define CLANG_DIAG_RESTORE
262 #else
263 // MSVC has the __pragma() macro instead
264 # define CLANG_DIAG_IGNORE(w)
265 # define CLANG_DIAG_RESTORE
266 #endif
267
268 /* for GCC14_DIAG_IGNORE (-Wanalyzer-allocation-size) or -Wanalyzer-malloc-leak
269 https://cwe.mitre.org/data/definitions/131.html
270 */
271 #if _GNUC_VERSION >= 1400
272 # define GCC14_DIAG_IGNORE(x) \
273 _Pragma ("GCC diagnostic push") CC_DIAG_PRAGMA (GCC diagnostic ignored #x)
274 # define GCC14_DIAG_RESTORE _Pragma ("GCC diagnostic pop")
275 #else
276 # define GCC14_DIAG_IGNORE(w)
277 # define GCC14_DIAG_RESTORE
278 #endif
279
280 /* for GCC80_DIAG_IGNORE (-Wstringop-truncation)
281 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88780
282 */
283 #if _GNUC_VERSION >= 800
284 # define GCC80_DIAG_IGNORE(x) \
285 _Pragma ("GCC diagnostic push") CC_DIAG_PRAGMA (GCC diagnostic ignored #x)
286 # define GCC80_DIAG_RESTORE _Pragma ("GCC diagnostic pop")
287 #else
288 # define GCC80_DIAG_IGNORE(w)
289 # define GCC80_DIAG_RESTORE
290 #endif
291
292 /* for GCC46_DIAG_IGNORE (-Wdeprecated-declarations) or (-Wformat-nonliteral),
293 stacked inside functions.
294 clang 10.2 defines gcc compat version 4.2 though (402) */
295 #if _GNUC_VERSION >= 460 || (defined(HAVE_CLANG) && _GNUC_VERSION >= 400)
296 # define HAVE_CC_DIAG_STACK
297 # define GCC46_DIAG_IGNORE(x) \
298 _Pragma ("GCC diagnostic push") CC_DIAG_PRAGMA (GCC diagnostic ignored #x)
299 # define GCC46_DIAG_RESTORE _Pragma ("GCC diagnostic pop")
300 #else
301 # undef HAVE_CC_DIAG_STACK
302 # define GCC46_DIAG_IGNORE(w)
303 # define GCC46_DIAG_RESTORE
304 #endif
305
306 /* For GCC30_DIAG_IGNORE (-Wformat-nonliteral) outside functions */
307 #if _GNUC_VERSION >= 300 && !defined HAVE_CC_DIAG_STACK
308 # define GCC30_DIAG_IGNORE(x) CC_DIAG_PRAGMA (GCC diagnostic ignored # x)
309 #else
310 # define GCC30_DIAG_IGNORE(w)
311 #endif
312 /* for GCC31_DIAG_IGNORE (-Wdeprecated-declarations) outside functions */
313 #if _GNUC_VERSION >= 310 && !defined HAVE_CC_DIAG_STACK
314 # define GCC31_DIAG_IGNORE(x) CC_DIAG_PRAGMA (GCC diagnostic ignored # x)
315 #else
316 # define GCC31_DIAG_IGNORE(w)
317 #endif
318 /* for GCC33_DIAG_IGNORE (-Wswitch-enum) outside functions
319 -Wswitch-enum appeared first with gcc 3.3.6 */
320 #if _GNUC_VERSION >= 330 && !defined HAVE_CC_DIAG_STACK
321 # define GCC33_DIAG_IGNORE(x) CC_DIAG_PRAGMA (GCC diagnostic ignored # x)
322 #else
323 # define GCC33_DIAG_IGNORE(w)
324 #endif
325
326 #ifndef __has_feature
327 # define __has_feature(x) 0
328 #endif
329
330 /* */
331 #if defined(__AFL_COMPILER) && defined(__clang__)
332 # define AFL_GCC_TOOBIG __attribute__ ((optnone))
333 # define AFL_GCC_POP
334 #elif defined(__AFL_COMPILER) && defined(__GNUC__)
335 # define AFL_GCC_TOOBIG \
336 _Pragma ("GCC push_options") \
337 _Pragma ("GCC optimize (\"-fno-var-tracking-assignments\")")
338 # define AFL_GCC_POP _Pragma ("GCC pop_options")
339 #else
340 # define AFL_GCC_TOOBIG
341 # define AFL_GCC_POP
342 #endif
343
344 /* The __nonnull function attribute marks pointer arguments which
345 must not be NULL. */
346 #if _GNUC_VERSION >= 303 && !defined(__cplusplus)
347 # undef __nonnull
348 # define __nonnull(params) __attribute__ ((__nonnull__ params))
349 # define __nonnull_all __attribute__ ((__nonnull__))
350 # define HAVE_NONNULL
351 #else
352 # ifndef __nonnull
353 # define __nonnull(params)
354 # undef HAVE_NONNULL
355 # else
356 # define HAVE_NONNULL
357 # endif
358 # define __nonnull_all
359 #endif
360
361 #if HAVE_FUNC_ATTRIBUTE_ALIGNED
362 # define ATTRIBUTE_ALIGNED(num) __attribute__ ((aligned (num)))
363 #elif defined(_MSC_VER)
364 # define ATTRIBUTE_ALIGNED(num) __declspec(align (num))
365 #else
366 # define ATTRIBUTE_ALIGNED(num)
367 #endif
368
369 #ifdef HAVE_FUNC_ATTRIBUTE_MALLOC
370 # define ATTRIBUTE_MALLOC __attribute__ ((malloc))
371 #else
372 # define ATTRIBUTE_MALLOC
373 #endif
374
375 #ifdef HAVE_FUNC_ATTRIBUTE_RETURNS_NONNULL
376 # define RETURNS_NONNULL __attribute__ ((returns_nonnull))
377 #else
378 # define RETURNS_NONNULL
379 #endif
380
381 #ifdef HAVE_FUNC_ATTRIBUTE_NORETURN
382 # define ATTRIBUTE_NORETURN __attribute__ ((noreturn))
383 #elif defined(_MSC_VER)
384 # define ATTRIBUTE_NORETURN __declspec(noreturn)
385 #else
386 # define ATTRIBUTE_NORETURN
387 #endif
388
389 #if defined(_WIN32) && defined(HAVE_FUNC_ATTRIBUTE_MS_FORMAT) \
390 && !defined(__USE_MINGW_ANSI_STDIO)
391 # define ATTRIBUTE_FORMAT(x, y) __attribute__ ((format (ms_printf, x, y)))
392 #elif defined HAVE_FUNC_ATTRIBUTE_GNU_FORMAT
393 # define ATTRIBUTE_FORMAT(x, y) __attribute__ ((format (gnu_printf, x, y)))
394 #elif defined HAVE_FUNC_ATTRIBUTE_FORMAT
395 # define ATTRIBUTE_FORMAT(x, y) __attribute__ ((format (printf, x, y)))
396 #else
397 # define ATTRIBUTE_FORMAT(x, y)
398 #endif
399
400 #ifndef EXPORT
401 # if defined(_WIN32) && defined(ENABLE_SHARED)
402 # ifdef DLL_EXPORT
403 # define EXPORT __declspec(dllexport)
404 # else
405 # define EXPORT __declspec(dllimport)
406 # endif
407 # elif defined HAVE_ATTRIBUTE_VISIBILITY_DEFAULT
408 # define EXPORT __attribute__ ((visibility ("default")))
409 # else
410 # define EXPORT
411 # endif
412 #endif
413
414 #undef CAN_ACIS_IN_DS_DATA
415 #undef CAN_ACIS_HISTORY
416 #define TODO_ENCODER HANDLER (OUTPUT, "TODO: Encoder\n");
417 #define TODO_DECODER HANDLER (OUTPUT, "TODO: Decoder\n");
418
419 #ifndef _WIN32
420 # define STRFTIME_DATE "%F %T"
421 # define STRFTIME_TIME "%T"
422 #else
423 /* windows/mingw misses those C99 formats */
424 # define STRFTIME_DATE "%Y-%m-%d %X"
425 # define STRFTIME_TIME "%X"
426 #endif
427
428 // Exporters are more common in the spec format, in_json and in_dxf are not
429 // using it. So default to the encode-to format. dec_macros needs to override
430 // them. See importer.h for the other way: For decode, in_json, in_dxf.
431 #define VERSION(v) \
432 cur_ver = v; \
433 if (dat->version == v)
434 #define NOT_VERSION(v) \
435 cur_ver = v; \
436 if (dat->version != v)
437 #define VERSIONS(v1, v2) \
438 cur_ver = v1; \
439 if (dat->version >= v1 && dat->version <= v2)
440 #define OTHER_VERSIONS else
441 #define PRE(v) \
442 cur_ver = v; \
443 if (dat->version < v)
444 #define SINCE(v) \
445 cur_ver = v; \
446 if (dat->version >= v)
447 #define PRIOR_VERSIONS else
448 #define UNTIL(v) \
449 cur_ver = v; \
450 if (dat->version <= v)
451 #define LATER_VERSIONS else
452 #define RESET_VER cur_ver = dat->version;
453
454 #define DEBUG_POS
455 #define DEBUG_HERE
456 #define DEBUG_POS_OBJ
457 #define DEBUG_HERE_OBJ
458
459 #define SAFENAME(name) (name) ? (name) : ""
460 #define SAFEDXFNAME (obj && obj->dxfname ? obj->dxfname : "")
461 #define ARRAY_SIZE(arr) (int)(sizeof (arr) / sizeof ((arr)[0]))
462 #define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
463 #define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
464
465 /**
466 Data types (including compressed forms) used through the project
467 */
468
469 // keep in sync with common.c dwg_bits_name
470 typedef enum DWG_BITS
471 {
472 BITS_UNKNOWN,
473 BITS_RC, /** raw char (not compressed) */
474 BITS_RS, /** raw 2-byte short (not compressed, big-endian) */
475 BITS_RL, /** raw 4-byte long (not compressed, big-endian) */
476 BITS_B, /** bit (1 or 0) */
477 BITS_BB, /** special 2-bit code (entmode in entities, for instance) */
478 BITS_3B, /** special 3-bit code R24+ */
479 BITS_4BITS, /** 4 bits, r2000+ for VIEWMODE */
480 BITS_BS, /** bitshort */
481 BITS_BL, /** bitlong uint32_t */
482 BITS_BLd, /** signed bitlong int32_t */
483 BITS_RLL, /** raw 8-byte long long (not compressed, big-endian) */
484 BITS_RD, /** raw double (not compressed, big-endian) */
485 BITS_BD, /** bitdouble */
486 BITS_MC, /** modular char */
487 BITS_UMC, /** unsigned modular char, max 4 bytes (handlestream_size) */
488 BITS_MS, /** modular short */
489 BITS_TV, /** text value, -r2007 */
490 BITS_TU, /** Unicode text (bitshort character length, followed by
491 UCS-2 string). Unicode text is read from the
492 “string stream” within the object data. r2007+ */
493 BITS_T, /** text, version dependent: TV or TU */
494 BITS_TF, /** fixed-length text */
495 BITS_T32, /** String32 type */
496 BITS_TU32, /** StringU32 type (FileDepList.features) */
497 BITS_HANDLE, /** handle reference (see the HANDLE REFERENCES section) */
498 BITS_BE, /** BitExtrusion */
499 BITS_DD, /** BitDouble With Default */
500 BITS_BT, /** BitThickness */
501 BITS_BOT, /** Bit object type: 2010+ (BB + 1-2RC) */
502 BITS_BLL, /** bitlonglong R24+ */
503 BITS_TIMEBLL, /** time long.long */
504 BITS_CMC, /** CmColor value */
505 BITS_ENC, /** Entity CmColor value */
506 BITS_2RD, /** 2 raw doubles **/
507 BITS_3RD, /** 3 raw doubles **/
508 BITS_2BD, /** 2D point (2 bitdoubles) **/
509 BITS_3BD, /** 3D point (3 bitdoubles) **/
510 BITS_2DD, /** 2 doubles with default **/
511 BITS_3DD, /** 3 doubles with default **/
512 BITS_CRC,
513 BITS_CRC64,
514 BITS_RLLd
515 } Dwg_Bits;
516
517 /* Globals inside the lib */
518 #ifndef COMMON_C
519 extern const char version_codes[DWG_VERSIONS][7];
520 extern const char *dwg_bits_name[];
521 extern const unsigned char dwg_bits_size[];
522 #endif
523
524 /**
525 * Index of sentinels into sentinels[]
526 */
527 typedef enum DWG_SENTINEL
528 {
529 DWG_SENTINEL_HEADER_END = 0,
530 DWG_SENTINEL_THUMBNAIL_BEGIN,
531 DWG_SENTINEL_THUMBNAIL_END,
532 DWG_SENTINEL_VARIABLE_BEGIN,
533 DWG_SENTINEL_VARIABLE_END,
534 DWG_SENTINEL_CLASS_BEGIN,
535 DWG_SENTINEL_CLASS_END,
536 DWG_SENTINEL_2NDHEADER_BEGIN,
537 DWG_SENTINEL_2NDHEADER_END,
538 DWG_SENTINEL_R11_ENTITIES_BEGIN,
539 DWG_SENTINEL_R11_ENTITIES_END,
540 DWG_SENTINEL_R11_BLOCK_BEGIN,
541 DWG_SENTINEL_R11_BLOCK_END,
542 DWG_SENTINEL_R11_LAYER_BEGIN,
543 DWG_SENTINEL_R11_LAYER_END,
544 DWG_SENTINEL_R11_STYLE_BEGIN,
545 DWG_SENTINEL_R11_STYLE_END,
546 DWG_SENTINEL_R11_LTYPE_BEGIN,
547 DWG_SENTINEL_R11_LTYPE_END,
548 DWG_SENTINEL_R11_VIEW_BEGIN,
549 DWG_SENTINEL_R11_VIEW_END,
550 DWG_SENTINEL_R11_UCS_BEGIN,
551 DWG_SENTINEL_R11_UCS_END,
552 DWG_SENTINEL_R11_VPORT_BEGIN,
553 DWG_SENTINEL_R11_VPORT_END,
554 DWG_SENTINEL_R11_APPID_BEGIN,
555 DWG_SENTINEL_R11_APPID_END,
556 DWG_SENTINEL_R11_DIMSTYLE_BEGIN,
557 DWG_SENTINEL_R11_DIMSTYLE_END,
558 DWG_SENTINEL_R11_VX_BEGIN,
559 DWG_SENTINEL_R11_VX_END,
560 DWG_SENTINEL_R11_BLOCK_ENTITIES_BEGIN,
561 DWG_SENTINEL_R11_BLOCK_ENTITIES_END,
562 DWG_SENTINEL_R11_EXTRA_ENTITIES_BEGIN,
563 DWG_SENTINEL_R11_EXTRA_ENTITIES_END,
564 DWG_SENTINEL_R11_AUXHEADER_BEGIN,
565 DWG_SENTINEL_R11_AUXHEADER_END
566 } Dwg_Sentinel;
567
568 const unsigned char *dwg_sentinel (const Dwg_Sentinel sentinel_id);
569 // used by unit-tests
570 EXPORT char *strrplc (const char *s, const char *from,
571 const char *to) __nonnull_all;
572
573 #define strEQ(s1, s2) !strcmp ((s1), (s2))
574 #define strNE(s1, s2) (strcmp ((s1), (s2)) != 0)
575 #define strEQc(s1, s2) !strcmp ((s1), s2 "")
576 #define strNEc(s1, s2) (strcmp ((s1), s2 "") != 0)
577
578 #define memBEGIN(s1, s2, len) (strlen (s1) >= len && !memcmp (s1, s2, len))
579 #define memBEGINc(s1, s2) \
580 (strlen (s1) >= sizeof (s2 "") - 1 && !memcmp (s1, s2, sizeof (s2 "") - 1))
581
582 #ifndef M_PI
583 # define M_PI 3.14159265358979323846
584 #endif
585 #ifndef M_PI_2
586 # define M_PI_2 1.57079632679489661923132169163975144
587 #endif
588 #define rad2deg(ang) (ang) * 90.0 / M_PI_2
589 #define deg2rad(ang) (ang) * M_PI_2 / 90.0
590
591 #if !defined(HAVE_MEMMEM) || defined(COMMON_TEST_C)
592 // only if _GNU_SOURCE
593 void *my_memmem (const void *h0, size_t k, const void *n0, size_t l)
594 __nonnull ((1, 3));
595 # define memmem my_memmem
596 #elif !defined(_GNU_SOURCE) && defined(IS_DECODER) && !defined(__linux__)
597 /* HAVE_MEMMEM and _GNU_SOURCE are unreliable on non-Linux systems.
598 This fails on FreeBSD and macos.
599 Rather declare it by ourselves, and don't use _GNU_SOURCE. */
600 void *memmem (const void *h0, size_t k, const void *n0, size_t l)
601 __nonnull ((1, 3));
602 #endif
603
604 // push to handle vector at the end. It really is unshift.
605 #define PUSH_HV(_obj, numfield, hvfield, ref) \
606 { \
607 _obj->hvfield = (BITCODE_H *)realloc ( \
608 _obj->hvfield, (_obj->numfield + 1) * sizeof (BITCODE_H)); \
609 _obj->hvfield[_obj->numfield] = ref; \
610 LOG_TRACE ("%s[%d] = " FORMAT_REF " [H]\n", #hvfield, _obj->numfield, \
611 ARGS_REF (_obj->hvfield[_obj->numfield])); \
612 _obj->numfield++; \
613 }
614
615 // no need to free global handles, just the HV.
616 // returns the last
617 #define POP_HV(_obj, numfield, hvfield) _obj->hvfield[--_obj->numfield]
618 // returns the first
619 #define SHIFT_HV(_obj, numfield, hvfield) \
620 shift_hv (_obj->hvfield, &_obj->numfield)
621 BITCODE_H shift_hv (BITCODE_H *hv, BITCODE_BL *num_p) __nonnull_all;
622 // deletes an entry from an HV ("handle vector") at index i
623 void delete_hv (BITCODE_H *entries, BITCODE_BS *num_entriesp,
624 BITCODE_BS index) __nonnull_all;
625
626 // used in dwg.spec
627 Dwg_Object *
628 dwg_find_first_type (const Dwg_Data *restrict dwg,
629 const enum DWG_OBJECT_TYPE type) __nonnull_all;
630 Dwg_Object *dwg_find_last_type (const Dwg_Data *restrict dwg,
631 const enum DWG_OBJECT_TYPE type) __nonnull_all;
632 Dwg_Handle *
633 dwg_find_first_type_handle (const Dwg_Data *restrict dwg,
634 const enum DWG_OBJECT_TYPE type) __nonnull_all;
635 // from dwg.c
636 void dwg_calc_hookline_on (Dwg_Entity_LEADER *_obj);
637
638 // <path-to>/dxf.ext => copy of "dxf", "ext"
639 // Returns a malloc'ed copy of basename, and
640 // sets ext to the char behind the last "." of filepath
641 char *split_filepath (const char *filepath, char **extp) __nonnull_all;
642
643 const struct dwg_versions *dwg_version_struct (const Dwg_Version_Type version);
644 /* Returns the AC header magic string [6] */
645 const char *dwg_version_codes (const Dwg_Version_Type version);
646 /* Finds version from the magic char[6] header and the matching
647 dwg_version number. */
648 Dwg_Version_Type dwg_version_hdr_type2 (const char *hdr,
649 unsigned dwg_version) __nonnull_all;
650
651 // converts TIMEBLL to struct tm. useful for asctime(tm) or strftime
652 struct tm *cvt_TIMEBLL (struct tm *tm, BITCODE_TIMEBLL date) __nonnull_all;
653
654 /* Exported functions not in the API */
655 const char *dwg_ref_tblname (const Dwg_Data *restrict dwg,
656 Dwg_Object_Ref *restrict ref,
657 int *alloced) __nonnull_all;
658 const char *dwg_ref_objname (const Dwg_Data *restrict dwg,
659 Dwg_Object_Ref *restrict ref) __nonnull_all;
660
661 int dwg_sections_init (Dwg_Data *dwg) __nonnull_all;
662
663 /* in seconds */
664 long tm_offset (void);
665 void dwg_log_proxyflag (const int _loglevel, const int maxlevel,
666 const BITCODE_BS flag);
667 void dwg_log_dataflags (const int _loglevel, const int maxlevel,
668 const BITCODE_RC flag);
669 // in encode, but also in dwg.spec
670 void
671 dwg_convert_LTYPE_strings_area (const Dwg_Data *restrict dwg,
672 Dwg_Object_LTYPE *restrict _obj) __nonnull_all;
673
674 // in the public API, but we don't use that for most internal modules
675 #if !defined _DWG_API_H_ && !defined _DWG_API_C && !defined DYNAPI_TEST_C \
676 && !defined ADD_TEST_C && !defined DXF_TEST_C
677 bool dwg_is_valid_tag (const char *tag) __nonnull_all;
678 #endif
679
680 bool dwg_has_eed_appid (Dwg_Object_Object *restrict obj,
681 const BITCODE_RLL absref) __nonnull_all;
682
683 #endif