(root)/
libredwg-0.13/
src/
common.h
       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