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