1 /*****************************************************************************/ 2 /* LibreDWG - free implementation of the DWG file format */ 3 /* */ 4 /* Copyright (C) 2009-2021 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 #ifdef __XSI_VISIBLE 25 # undef __XSI_VISIBLE /* redefined in config.h */ 26 #endif 27 #include "config.h" 28 #include <stddef.h> 29 #include <stdint.h> 30 #include <inttypes.h> 31 #include "dwg.h" 32 33 /* Used warning suppressions: 34 CLANG_DIAG_IGNORE (-Wpragma-pack) 35 CLANG_DIAG_IGNORE (-Wmissing-prototypes) - also in gcc since 2.95, but not 36 needed CLANG_DIAG_RESTORE 37 38 GCC46_DIAG_IGNORE (-Wformat-nonliteral) + GCC46_DIAG_RESTORE 39 GCC30_DIAG_IGNORE (-Wformat-nonliteral) w/o 40 GCC31_DIAG_IGNORE (-Wdeprecated-declarations) 41 GCC30_DIAG_IGNORE (-Wshadow) 42 */ 43 #if defined(__GNUC__) 44 # define _GNUC_VERSION ((__GNUC__ * 100) + __GNUC_MINOR__) 45 # define CC_DIAG_PRAGMA(x) _Pragma (#x) 46 #else 47 # define _GNUC_VERSION 0 48 # define CC_DIAG_PRAGMA(x) 49 #endif 50 51 /* 52 #define _STR(x) #x 53 #define STR(x)_STR(x) 54 #pragma message("_GNUC_VERSION " STR(_GNUC_VERSION)) 55 */ 56 57 // clang-specifics (rarely needed, as they mimic GCC dignostics closely, even down to bugs) 58 #if defined(__clang__) || defined(__clang) 59 # define HAVE_CLANG 60 # define CLANG_DIAG_IGNORE(x) \ 61 _Pragma ("clang diagnostic push") \ 62 CC_DIAG_PRAGMA (clang diagnostic ignored #x) 63 # define CLANG_DIAG_RESTORE _Pragma ("clang diagnostic pop") 64 #elif defined(__GNUC__) 65 # define CLANG_DIAG_IGNORE(w) 66 # define CLANG_DIAG_RESTORE 67 #else 68 // MSVC has the __pragma() macro instead 69 # define CLANG_DIAG_IGNORE(w) 70 # define CLANG_DIAG_RESTORE 71 #endif 72 73 /* for GCC46_DIAG_IGNORE (-Wdeprecated-declarations) or (-Wformat-nonliteral), 74 stacked inside functions. 75 clang 10.2 defines gcc compat version 4.2 though (402) */ 76 #if _GNUC_VERSION >= 460 || (defined(HAVE_CLANG) && _GNUC_VERSION >= 400) 77 # define HAVE_CC_DIAG_STACK 78 # define GCC46_DIAG_IGNORE(x) \ 79 _Pragma ("GCC diagnostic push") \ 80 CC_DIAG_PRAGMA (GCC diagnostic ignored #x) 81 # define GCC46_DIAG_RESTORE _Pragma ("GCC diagnostic pop") 82 #else 83 # undef HAVE_CC_DIAG_STACK 84 # define GCC46_DIAG_IGNORE(w) 85 # define GCC46_DIAG_RESTORE 86 #endif 87 88 /* For GCC30_DIAG_IGNORE (-Wformat-nonliteral) outside functions */ 89 #if _GNUC_VERSION >= 300 && !defined HAVE_CC_DIAG_STACK 90 # define GCC30_DIAG_IGNORE(x) CC_DIAG_PRAGMA (GCC diagnostic ignored #x) 91 #else 92 # define GCC30_DIAG_IGNORE(w) 93 #endif 94 /* for GCC31_DIAG_IGNORE (-Wdeprecated-declarations) outside functions */ 95 #if _GNUC_VERSION >= 310 && !defined HAVE_CC_DIAG_STACK 96 # define GCC31_DIAG_IGNORE(x) CC_DIAG_PRAGMA (GCC diagnostic ignored #x) 97 #else 98 # define GCC31_DIAG_IGNORE(w) 99 #endif 100 /* for GCC33_DIAG_IGNORE (-Wswitch-enum) outside functions 101 -Wswitch-enum appeared first with gcc 3.3.6 102 */ 103 #if _GNUC_VERSION >= 330 && !defined HAVE_CC_DIAG_STACK 104 # define GCC33_DIAG_IGNORE(x) CC_DIAG_PRAGMA (GCC diagnostic ignored #x) 105 #else 106 # define GCC33_DIAG_IGNORE(w) 107 #endif 108 109 #ifndef __has_feature 110 # define __has_feature(x) 0 111 #endif 112 113 /* */ 114 #if defined(__AFL_COMPILER) && defined(__clang__) 115 # define AFL_GCC_TOOBIG __attribute__((optnone)) 116 # define AFL_GCC_POP 117 #elif defined(__AFL_COMPILER) && defined(__GNUC__) 118 # define AFL_GCC_TOOBIG \ 119 _Pragma ("GCC push_options") \ 120 _Pragma ("GCC optimize (\"-fno-var-tracking-assignments\")") 121 # define AFL_GCC_POP \ 122 _Pragma ("GCC pop_options") 123 #else 124 # define AFL_GCC_TOOBIG 125 # define AFL_GCC_POP 126 #endif 127 128 /* The __nonnull function attribute marks pointer arguments which 129 must not be NULL. */ 130 #if _GNUC_VERSION >= 303 && !defined(__cplusplus) 131 # undef __nonnull 132 # define __nonnull(params) __attribute__ ((__nonnull__ params)) 133 # define __nonnull_all __attribute__ ((__nonnull__)) 134 # define HAVE_NONNULL 135 #else 136 # define __nonnull(params) 137 # define __nonnull_all 138 # undef HAVE_NONNULL 139 #endif 140 141 #ifdef HAVE_FUNC_ATTRIBUTE_MALLOC 142 # define ATTRIBUTE_MALLOC __attribute__ ((malloc)) 143 #else 144 # define ATTRIBUTE_MALLOC 145 #endif 146 147 #ifdef HAVE_FUNC_ATTRIBUTE_RETURNS_NONNULL 148 # define RETURNS_NONNULL __attribute__ ((returns_nonnull)) 149 #else 150 # define RETURNS_NONNULL 151 #endif 152 153 #ifdef HAVE_FUNC_ATTRIBUTE_NORETURN 154 # define ATTRIBUTE_NORETURN __attribute__ ((noreturn)) 155 #else 156 # define ATTRIBUTE_NORETURN 157 #endif 158 159 #ifndef EXPORT 160 # if defined(_WIN32) && defined(ENABLE_SHARED) 161 # ifdef DLL_EXPORT 162 # define EXPORT __declspec(dllexport) 163 # else 164 # define EXPORT __declspec(dllimport) 165 # endif 166 # elif defined HAVE_ATTRIBUTE_VISIBILITY_DEFAULT 167 # define EXPORT __attribute__ ((visibility ("default"))) 168 # else 169 # define EXPORT 170 # endif 171 #endif 172 173 #undef CAN_ACIS_IN_DS_DATA 174 #undef CAN_ACIS_HISTORY 175 #define TODO_ENCODER HANDLER (OUTPUT, "TODO: Encoder\n"); 176 #define TODO_DECODER HANDLER (OUTPUT, "TODO: Decoder\n"); 177 178 // Exporters are more common in the spec format, in_json and in_dxf are not using it. 179 // So default to the encode-to format. dec_macros needs to override them. 180 // See importer.h for the other way: For decode, in_json, in_dxf. 181 #define VERSION(v) \ 182 cur_ver = v; \ 183 if (dat->version == v) 184 #define NOT_VERSION(v) \ 185 cur_ver = v; \ 186 if (dat->version != v) 187 #define VERSIONS(v1, v2) \ 188 cur_ver = v1; \ 189 if (dat->version >= v1 && dat->version <= v2) 190 #define OTHER_VERSIONS else 191 #define PRE(v) \ 192 cur_ver = v; \ 193 if (dat->version < v) 194 #define SINCE(v) \ 195 cur_ver = v; \ 196 if (dat->version >= v) 197 #define PRIOR_VERSIONS else 198 #define UNTIL(v) \ 199 cur_ver = v; \ 200 if (dat->version <= v) 201 #define LATER_VERSIONS else 202 #define RESET_VER cur_ver = dat->version; 203 204 #define DEBUG_POS 205 #define DEBUG_HERE 206 #define DEBUG_POS_OBJ 207 #define DEBUG_HERE_OBJ 208 209 #define SAFENAME(name) (name) ? (name) : "" 210 #define SAFEDXFNAME (obj && obj->dxfname ? obj->dxfname : "") 211 #define ARRAY_SIZE(arr) (int)(sizeof (arr) / sizeof ((arr)[0])) 212 #define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) 213 #define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) 214 215 /** 216 Data types (including compressed forms) used through the project 217 */ 218 // keep in sync with common.c dwg_bits_name 219 typedef enum DWG_BITS 220 { 221 BITS_UNKNOWN, 222 BITS_RC, /** raw char (not compressed) */ 223 BITS_RS, /** raw 2-byte short (not compressed, big-endian) */ 224 BITS_RL, /** raw 4-byte long (not compressed, big-endian) */ 225 BITS_B, /** bit (1 or 0) */ 226 BITS_BB, /** special 2-bit code (entmode in entities, for instance) */ 227 BITS_3B, /** special 3-bit code R24+ */ 228 BITS_4BITS, /** 4 bits, r2000+ for VIEWMODE */ 229 BITS_BS, /** bitshort */ 230 BITS_BL, /** bitlong uint32_t */ 231 BITS_BLd, /** signed bitlong int32_t */ 232 BITS_RLL, /** raw 8-byte long long (not compressed, big-endian) */ 233 BITS_RD, /** raw double (not compressed, big-endian) */ 234 BITS_BD, /** bitdouble */ 235 BITS_MC, /** modular char */ 236 BITS_UMC, /** unsigned modular char, max 4 bytes (handlestream_size) */ 237 BITS_MS, /** modular short */ 238 BITS_TV, /** text value, -r2007 */ 239 BITS_TU, /** Unicode text (bitshort character length, followed by 240 UCS-2 string). Unicode text is read from the 241 “string stream” within the object data. r2007+ */ 242 BITS_T, /** text, version dependent: TV or TU */ 243 BITS_TF, /** fixed-length text */ 244 BITS_T32, /** String32 type */ 245 BITS_TU32, /** StringU32 type (FileDepList.features) */ 246 BITS_HANDLE, /** handle reference (see the HANDLE REFERENCES section) */ 247 BITS_BE, /** BitExtrusion */ 248 BITS_DD, /** BitDouble With Default */ 249 BITS_BT, /** BitThickness */ 250 BITS_BOT, /** Bit object type: 2010+ (BB + 1-2RC) */ 251 BITS_BLL, /** bitlonglong R24+ */ 252 BITS_TIMEBLL, /** time long.long */ 253 BITS_CMC, /** CmColor value */ 254 BITS_ENC, /** Entity CmColor value */ 255 BITS_2RD, /** 2 raw doubles **/ 256 BITS_3RD, /** 3 raw doubles **/ 257 BITS_2BD, /** 2D point (2 bitdoubles) **/ 258 BITS_3BD, /** 3D point (3 bitdoubles) **/ 259 BITS_2DD, /** 2 doubles with default **/ 260 BITS_3DD, /** 3 doubles with default **/ 261 BITS_CRC, 262 BITS_CRC64 263 } Dwg_Bits; 264 265 /* Globals inside the lib */ 266 extern const char version_codes[DWG_VERSIONS][7]; 267 extern const char *dwg_bits_name[]; 268 extern const unsigned char dwg_bits_size[]; 269 270 /** 271 * References of sentinels 272 */ 273 typedef enum DWG_SENTINEL 274 { 275 DWG_SENTINEL_HEADER_END, 276 DWG_SENTINEL_THUMBNAIL_BEGIN, 277 DWG_SENTINEL_THUMBNAIL_END, 278 DWG_SENTINEL_VARIABLE_BEGIN, 279 DWG_SENTINEL_VARIABLE_END, 280 DWG_SENTINEL_CLASS_BEGIN, 281 DWG_SENTINEL_CLASS_END, 282 DWG_SENTINEL_SECOND_HEADER_BEGIN, 283 DWG_SENTINEL_SECOND_HEADER_END 284 } Dwg_Sentinel; 285 286 unsigned char *dwg_sentinel (Dwg_Sentinel sentinel); 287 char *strrplc (const char *s, const char *from, const char *to); 288 289 #define strEQ(s1, s2) !strcmp ((s1), (s2)) 290 #define strNE(s1, s2) strcmp ((s1), (s2)) 291 #define strEQc(s1, s2) !strcmp ((s1), s2 "") 292 #define strNEc(s1, s2) strcmp ((s1), s2 "") 293 294 #define memBEGIN(s1, s2, len) (strlen (s1) >= len && !memcmp (s1, s2, len)) 295 #define memBEGINc(s1, s2) \ 296 (strlen (s1) >= sizeof (s2 "") - 1 && !memcmp (s1, s2, sizeof (s2 "") - 1)) 297 298 #ifndef M_PI 299 # define M_PI 3.14159265358979323846 300 #endif 301 #ifndef M_PI_2 302 # define M_PI_2 1.57079632679489661923132169163975144 303 #endif 304 #define rad2deg(ang) (ang) * 90.0 / M_PI_2 305 #define deg2rad(ang) (ang) * M_PI_2 / 90.0 306 307 #if !defined(HAVE_MEMMEM) || defined(COMMON_TEST_C) 308 // only if _GNU_SOURCE 309 void *my_memmem (const void *h0, size_t k, const void *n0, size_t l) __nonnull((1, 3)); 310 #define memmem my_memmem 311 #elif !defined(_GNU_SOURCE) && defined(IS_DECODER) 312 /* HAVE_MEMMEM and _GNU_SOURCE are unreliable on non-Linux systems. 313 This fails on FreeBSD and macos. 314 Rather declare it by ourselves, and don't use _GNU_SOURCE. */ 315 void *memmem (const void *h0, size_t k, const void *n0, size_t l) __nonnull((1, 3)); 316 #endif 317 318 // push to handle vector at the end. It really is unshift. 319 #define PUSH_HV(_obj, numfield, hvfield, ref) \ 320 { \ 321 _obj->hvfield = (BITCODE_H *)realloc ( \ 322 _obj->hvfield, (_obj->numfield + 1) * sizeof (BITCODE_H)); \ 323 _obj->hvfield[_obj->numfield] = ref; \ 324 LOG_TRACE ("%s[%d] = " FORMAT_REF " [H]\n", #hvfield, _obj->numfield, \ 325 ARGS_REF (_obj->hvfield[_obj->numfield])); \ 326 _obj->numfield++; \ 327 } 328 329 // no need to free global handles, just the HV. 330 // returns the last 331 #define POP_HV(_obj, numfield, hvfield) _obj->hvfield[--_obj->numfield] 332 // returns the first 333 #define SHIFT_HV(_obj, numfield, hvfield) shift_hv (_obj->hvfield, &_obj->numfield) 334 BITCODE_H shift_hv (BITCODE_H *hv, BITCODE_BL *num_p); 335 336 // used in dwg.spec 337 Dwg_Handle *dwg_find_first_type_handle (Dwg_Data *restrict dwg, 338 enum DWG_OBJECT_TYPE type); 339 340 // <path-to>/dxf.ext => copy of "dxf", "ext" 341 // Returns a malloc'ed copy of basename, and 342 // sets ext to the char behind the last "." of filepath 343 char *split_filepath (const char *filepath, char **extp); 344 345 #endif 346