1 #include "../../src/config.h"
2 #define _DEFAULT_SOURCE
3 #define _BSD_SOURCE
4 #define _NETBSD_SOURCE
5 #define __BSD_VISIBLE 1
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <math.h>
11 #include <sys/stat.h>
12 #ifdef __APPLE__
13 #  define _DARWIN_C_SOURCE /* for DT_DIR */
14 #endif
15 #include <dirent.h>
16 #include "../../src/common.h"
17 #include "../../src/classes.h"
18 static int silent;
19 #include "tests_common.h"
20 
21 #include "dwg.h"
22 #include "dwg_api.h"
23 
24 dwg_data g_dwg;
25 const char *stability;
26 int g_counter;
27 #define MAX_COUNTER 6
28 int g_countmax = MAX_COUNTER;
29 
30 // in radians. angles are not normalized. max observed: 10.307697 in ELLIPSE.end_angle
31 #define MAX_ANGLE 12.57
32 
33 // needs Dwg_Version_Type dwg_version = obj->parent->header.version;
34 #undef PRE
35 #undef VERSION
36 #undef VERSIONS
37 #undef UNTIL
38 #undef SINCE
39 #define VERSION(version) if (dwg_version == version)
40 #define VERSIONS(v1, v2)   if (dwg_version >= v1 && dwg_version <= v2)
41 #define PRE(version)   if (dwg_version < version)
42 #define UNTIL(version) if (dwg_version <= version)
43 #define SINCE(version) if (dwg_version >= version)
44 #define LATER_VERSIONS else
45 
46 /// test a DWG file
47 int test_code (const char *path, const char *filename, int cov);
48 int test_code_nodist (const char *path, const char *filename, int cov);
49 
50 /// test all DWG's in a subdir
51 int test_subdirs (const char *dirname, int cov);
52 
53 /// Return the name of a handle
54 char *handle_name (const Dwg_Data *restrict dwg, Dwg_Object_Ref *restrict hdl);
55 
56 /// iterate over objects of a block
57 void output_BLOCK_HEADER (dwg_object_ref *ref);
58 
59 /// Check the dwg type and calls output_process
60 void output_object (dwg_object *obj);
61 
62 /// blocks to be iterated over
63 void output_test (dwg_data *dwg);
64 
65 void output_process (dwg_object *obj);
66 
67 /// Low Level processing function declaration
68 void low_level_process (dwg_object *obj);
69 
70 /// API based processing function declaration
71 void api_process (dwg_object *obj);
72 
73 void api_common_entity (dwg_object *obj);
74 
75 void api_common_object (dwg_object *obj);
76 
77 /// API based printing function declaration
78 void print_api (dwg_object *obj);
79 
80 /// Low level printing function declaration
81 void print_low_level (dwg_object *obj);
82 
83 /// Main function
84 int
main(int argc,char * argv[])85 main (int argc, char *argv[])
86 {
87   char *input = getenv ("INPUT");
88   char *dir = NULL;
89   int error = 0;
90   int i = 1, cov = 1;
91   //#ifdef USE_TRACING
92   char *trace = getenv ("LIBREDWG_TRACE");
93   silent = is_make_silent();
94   if (trace)
95     loglevel = atoi (trace);
96   else
97     loglevel = silent ? 0 : 2;
98   //#endif
99 
100 #ifdef DWG_TYPE
101   if (is_type_stable (DWG_TYPE))
102     stability = "stable";
103   else if (is_type_unstable (DWG_TYPE))
104     stability = "unstable";
105   else if (is_type_debugging (DWG_TYPE))
106     stability = "debugging";
107   else if (is_type_unhandled (DWG_TYPE))
108     stability = "unhandled";
109 #endif
110 
111   if (argc > i)
112     {
113       // don't warn/error on no coverage. for unit_testing_all.sh
114       if (strEQc (argv[i], "-n"))
115         {
116           cov = 0;
117           i++;
118         }
119       // --all, not stopping at 6
120       else if (strEQc (argv[i], "-an"))
121         {
122           g_countmax = 1000;
123           cov = 0;
124           i++;
125         }
126       else if (strEQc (argv[i], "-a"))
127         {
128           g_countmax = 1000;
129           i++;
130         }
131       // process subdirs
132       if (argc > i && *argv[i] != '-')
133         dir = argv[i];
134     }
135 
136   if (!input)
137     {
138       char **ptr;
139       struct stat attrib;
140       const char *const files[]
141           = { "example_2000.dwg", "example_2004.dwg", "example_2007.dwg",
142               "example_2010.dwg", "example_2013.dwg", "example_2018.dwg",
143               "example_r14.dwg",
144               //"2000/PolyLine2D.dwg",
145               //"2007/PolyLine3D.dwg",
146               NULL };
147       const char *prefix = "../test-data";
148 
149       if (dir)
150         {
151           if (!stat (dir, &attrib) &&
152               S_ISDIR (attrib.st_mode))
153 #ifndef HAVE_SCANDIR
154             fprintf (stderr, "dir argument not supported yet on this platform "
155                              "(missing scandir)\n");
156 #else
157             return test_subdirs (dir, cov);
158 #endif
159         }
160 
161       /* ../configure out-of-tree. find srcdir */
162       if (stat (prefix, &attrib))
163         prefix = "../../../test/test-data";
164       if (stat (prefix, &attrib)) /* dir not found. one more level up */
165         prefix = "../../../../test/test-data";
166 
167       for (ptr = (char **)&files[0]; *ptr; ptr++)
168         {
169           if (stat (*ptr, &attrib))
170             {
171               char tmp[80];
172               strcpy (tmp, prefix);
173               strcat (tmp, "/");
174               strcat (tmp, *ptr);
175               if (stat (tmp, &attrib))
176                 fprintf (stderr, "Env var INPUT not defined, %s not found\n",
177                          tmp);
178               else
179                 error += test_code (prefix, *ptr, cov);
180             }
181           else
182             error += test_code (prefix, *ptr, cov);
183         }
184       // if no coverage
185       if (!numpassed () && !numfailed ())
186         {
187           char tmp[80];
188           if (DWG_TYPE == DWG_TYPE_POLYLINE_2D ||
189               DWG_TYPE == DWG_TYPE_SEQEND ||
190               DWG_TYPE == DWG_TYPE_VERTEX_2D ||
191               DWG_TYPE == DWG_TYPE_CSACDOCUMENTOPTIONS ||
192               DWG_TYPE == DWG_TYPE_LAYOUTPRINTCONFIG)
193             {
194               error += test_code (prefix, "2000/PolyLine2D.dwg", cov);
195             }
196           if (DWG_TYPE == DWG_TYPE_POLYLINE_3D ||
197               DWG_TYPE == DWG_TYPE_VERTEX_3D)
198             {
199               error += test_code (prefix, "2000/PolyLine3D.dwg", cov);
200               error += test_code (prefix, "2004/PolyLine3D.dwg", cov);
201               error += test_code (prefix, "2018/PolyLine3D.dwg", cov);
202             }
203           if (DWG_TYPE == DWG_TYPE_POLYLINE_MESH ||
204               DWG_TYPE == DWG_TYPE_VERTEX_MESH ||
205               DWG_TYPE == DWG_TYPE_TRACE ||
206               DWG_TYPE == DWG_TYPE_DIMENSION_ANG3PT ||
207               DWG_TYPE == DWG_TYPE_DIMENSION_DIAMETER ||
208               DWG_TYPE == DWG_TYPE_DIMENSION_RADIUS ||
209               DWG_TYPE == DWG_TYPE_OLE2FRAME)
210             {
211               error += test_code (prefix, "2000/TS1.dwg", cov);
212             }
213           if (DWG_TYPE == DWG_TYPE_IMAGE ||
214               DWG_TYPE == DWG_TYPE_IMAGEDEF ||
215               DWG_TYPE == DWG_TYPE_IMAGEDEF_REACTOR ||
216               DWG_TYPE == DWG_TYPE_LEADER)
217             {
218               error += test_code (prefix, "2000/Leader.dwg", cov);
219               error += test_code (prefix, "2004/Leader.dwg", cov);
220               error += test_code (prefix, "2018/Leader.dwg", cov);
221             }
222           if (DWG_TYPE == DWG_TYPE_HATCH)
223             {
224               error += test_code (prefix, "2004/HatchG.dwg", cov);
225             }
226           if (DWG_TYPE == DWG_TYPE_BODY)
227             {
228               error += test_code_nodist (prefix,
229                                   "../test-old/2000/from_cadforum.cz/"
230                                   "Transformer_Oil_Filling_Chamber.dwg",
231                                   cov);
232               error += test_code_nodist (
233                   prefix,
234                   "../test-old/r14/from_cadforum.cz/plaza_light_dual.dwg",
235                   cov);
236             }
237           if (DWG_TYPE == DWG_TYPE_UCS)
238             {
239               error += test_code_nodist (prefix, "r14/plaza_light_dual.dwg",
240                                          cov);
241             }
242           if (DWG_TYPE == DWG_TYPE_SHAPE)
243             {
244               error += test_code_nodist (
245                   prefix, "../test-old/r13/from_lx_viewer/small.dwg", cov);
246             }
247           if (DWG_TYPE == DWG_TYPE_MINSERT)
248             {
249               error += test_code_nodist (
250                   prefix, "../test-old/r13/from_lx_viewer/small.dwg", cov);
251               error += test_code_nodist (prefix, "2000/passenger_drone.dwg", cov);
252               error += test_code_nodist (prefix, "2018/MInsert.dwg", cov);
253             }
254           if (DWG_TYPE == DWG_TYPE_PDFUNDERLAY ||
255               DWG_TYPE == DWG_TYPE_PDFDEFINITION)
256             {
257               error += test_code (prefix, "2004/Underlay.dwg", cov);
258             }
259           if (DWG_TYPE == DWG_TYPE_LIGHT ||
260               DWG_TYPE == DWG_TYPE_VISUALSTYLE)
261             {
262               error += test_code_nodist (prefix, "2004/Visualstyle.dwg", cov);
263               error += test_code_nodist (prefix, "2018/Visualstyle.dwg", cov);
264             }
265           if (DWG_TYPE == DWG_TYPE_GEODATA)
266             {
267               error += test_code (prefix, "2010/gh209_1.dwg", cov);
268             }
269           if (DWG_TYPE == DWG_TYPE_PLOTSETTINGS)
270             {
271               error += test_code_nodist (prefix, "2013/gh109_1.dwg", cov);
272             }
273           if (DWG_TYPE == DWG_TYPE_DBCOLOR)
274             {
275               error += test_code_nodist (prefix, "2004/dbcolor.dwg", cov);
276               error += test_code_nodist (prefix, "2004/Truecolor.dwg", cov);
277             }
278           if (DWG_TYPE == DWG_TYPE_HELIX)
279             {
280               error += test_code (prefix, "2004/Helix.dwg", cov);
281               error += test_code (prefix, "2018/Helix.dwg", cov);
282               error += test_code_nodist (prefix, "2000/work.dwg", cov);
283             }
284           if (DWG_TYPE == DWG_TYPE_ASSOCPLANESURFACEACTIONBODY ||
285               DWG_TYPE == DWG_TYPE_ASSOCACTION ||
286               DWG_TYPE == DWG_TYPE_ASSOCDEPENDENCY ||
287               DWG_TYPE == DWG_TYPE_ASSOCEDGEACTIONPARAM ||
288               DWG_TYPE == DWG_TYPE_ASSOCEXTRUDEDSURFACEACTIONBODY ||
289               DWG_TYPE == DWG_TYPE_ASSOCLOFTEDSURFACEACTIONBODY ||
290               DWG_TYPE == DWG_TYPE_ASSOCPATHACTIONPARAM ||
291               DWG_TYPE == DWG_TYPE_ASSOCPERSSUBENTMANAGER ||
292               DWG_TYPE == DWG_TYPE_ASSOCREVOLVEDSURFACEACTIONBODY ||
293               DWG_TYPE == DWG_TYPE_ASSOCSWEPTSURFACEACTIONBODY ||
294               DWG_TYPE == DWG_TYPE_EXTRUDEDSURFACE ||
295               DWG_TYPE == DWG_TYPE_LOFTEDSURFACE ||
296               DWG_TYPE == DWG_TYPE_NURBSURFACE ||
297               DWG_TYPE == DWG_TYPE_REVOLVEDSURFACE ||
298               DWG_TYPE == DWG_TYPE_SWEPTSURFACE ||
299               DWG_TYPE == DWG_TYPE_MESH)
300             {
301               error += test_code (prefix, "2004/Surface.dwg", cov);
302               error += test_code_nodist (prefix, "2018/Surface.dwg", cov);
303             }
304           if (DWG_TYPE == DWG_TYPE_PLANESURFACE)
305             {
306               error += test_code (prefix, "2004/Surface.dwg", cov);
307               error += test_code_nodist (
308                   prefix, "2010/visualization_-_conference_room.dwg", cov);
309               error += test_code_nodist (
310                   prefix, "2010/visualization_-_aerial.dwg", cov);
311             }
312           if (DWG_TYPE == DWG_TYPE_ASSOCNETWORK)
313             {
314               error += test_code (prefix, "2000/Constraints.dwg", cov);
315               error += test_code (prefix, "2004/Constraints.dwg", cov);
316               error += test_code (prefix, "2007/Constraints.dwg", cov);
317               error += test_code (prefix, "2010/Constraints.dwg", cov);
318               error += test_code (prefix, "2013/Constraints.dwg", cov);
319             }
320           if (DWG_TYPE == DWG_TYPE_BLKREFOBJECTCONTEXTDATA)
321             {
322               error += test_code_nodist (prefix, "2004/Visualstyle.dwg", cov);
323               error += test_code_nodist (prefix, "2018/Visualstyle.dwg", cov);
324               error += test_code_nodist (prefix, "2010/ACI_20160321_A_30_east.dwg",
325                                          cov);
326             }
327           if (DWG_TYPE == DWG_TYPE_LEADEROBJECTCONTEXTDATA)
328             {
329               error += test_code (prefix, "2000/Leader.dwg", cov);
330               error += test_code (prefix, "2004/Leader.dwg", cov);
331               error += test_code (prefix, "2013/gh55-ltype.dwg", cov);
332             }
333           if (DWG_TYPE == DWG_TYPE_IDBUFFER)
334             {
335               error += test_code_nodist (prefix, "r14/missing_xref.dwg", cov);
336             }
337           if (DWG_TYPE == DWG_TYPE_MLEADEROBJECTCONTEXTDATA ||
338               DWG_TYPE == DWG_TYPE_MTEXTOBJECTCONTEXTDATA ||
339               DWG_TYPE == DWG_TYPE_TEXTOBJECTCONTEXTDATA)
340             {
341               error += test_code_nodist (prefix, "2010/ACI_20160321_A_30_east.dwg",
342                                   cov);
343             }
344           if (DWG_TYPE == DWG_TYPE_MTEXTATTRIBUTEOBJECTCONTEXTDATA)
345             {
346               error += test_code (prefix, "2013/gh44-error.dwg", cov);
347               error += test_code_nodist (prefix, "2013/gh55-ltype.dwg", cov);
348               error += test_code_nodist (prefix, "2010/ACI_20160321_A_30_east.dwg",
349                                   cov);
350               error += test_code_nodist (prefix, "2018/ACI_20160321_A_30_east.dwg",
351                                   cov);
352               error += test_code_nodist (prefix,
353                   "../test-old/2018/from_autocad_2021/Annotation - Metric.dwg",
354                   cov);
355               error += test_code_nodist (prefix,
356                   "../test-old/2018/from_autocad_2021/Annotation - Imperial.dwg",
357                   cov);
358               error += test_code_nodist (prefix,
359                   "../test-old/2018/from_autocad_2021/Civil - Metric.dwg",
360                   cov);
361               error += test_code_nodist (prefix,
362                   "../test-old/2018/from_autocad_2021/Civil - Imperial.dwg",
363                   cov);
364               error += test_code_nodist (prefix,
365                   "../test-old/2018/from_autocad_2021/Electrical - Metric.dwg",
366                   cov);
367               error += test_code_nodist (prefix,
368                   "../test-old/2018/from_autocad_2021/Electrical - Imperial.dwg",
369                   cov);
370               error += test_code_nodist (prefix,
371                   "../test-old/2018/from_autocad_2021/Mechanical - Metric.dwg",
372                   cov);
373               error += test_code_nodist (prefix,
374                   "../test-old/2018/from_autocad_2021/Mechanical - Imperial.dwg",
375                   cov);
376               error += test_code_nodist (prefix,
377                   "../test-old/2018/from_autocad_2021/Structural - Metric.dwg",
378                   cov);
379               error += test_code_nodist (prefix,
380                   "../test-old/2018/from_autocad_2021/Structural - Imperial.dwg",
381                   cov);
382             }
383           if (DWG_TYPE == DWG_TYPE_FIELD || DWG_TYPE == DWG_TYPE_FIELDLIST)
384             {
385               error += test_code (prefix, "2000/TS1.dwg", cov);
386               error += test_code_nodist (prefix, "2010/5151-024.dwg", cov);
387             }
388           if (DWG_TYPE == DWG_TYPE_DATALINK)
389             {
390               error += test_code_nodist (prefix, "2010/5151-019.dwg", cov);
391               error += test_code_nodist (prefix, "2010/5151-022.dwg", cov);
392               error += test_code_nodist (prefix, "2010/5151-023.dwg", cov);
393               error += test_code_nodist (prefix, "2010/5151-024.dwg", cov);
394             }
395           if (DWG_TYPE == DWG_TYPE_DATATABLE)
396             {
397               error += test_code (prefix, "2000/TS1.dwg", cov);
398               error += test_code_nodist (prefix, "r13/TS1.dwg", cov);
399               error += test_code_nodist (prefix, "2004/fr05_b101_ref.dwg", cov);
400             }
401           if (DWG_TYPE == DWG_TYPE_SORTENTSTABLE)
402             {
403               error += test_code (prefix, "2000/PolyLine2D.dwg", cov);
404               error += test_code (prefix, "2004/Surface.dwg", cov);
405               error += test_code (prefix, "r13/PolyLine2D.dwg", cov);
406               error += test_code (prefix, "2004/Publish.dwg", cov);
407             }
408           if (DWG_TYPE == DWG_TYPE_SUN)
409             {
410               error += test_code_nodist (prefix, "2000/2.dwg", cov);
411               error += test_code_nodist (prefix, "2000/3.dwg", cov);
412               error += test_code_nodist (prefix, "2000/4.dwg", cov);
413               error += test_code_nodist (prefix, "2000/5.dwg", cov);
414             }
415           if (DWG_TYPE == DWG_TYPE_SPATIAL_FILTER)
416             {
417               error += test_code (prefix, "2013/gh44-error.dwg", cov);
418               if (g_countmax == 1000) // only with -a
419                 error += test_code_nodist (prefix, "../test-big/2007/big.dwg",
420                                            cov);
421             }
422           if (DWG_TYPE == DWG_TYPE_SECTIONOBJECT ||
423               DWG_TYPE == DWG_TYPE_SECTION_MANAGER ||
424               DWG_TYPE == DWG_TYPE_SECTION_SETTINGS)
425             {
426               error += test_code (prefix, "2018/LiveSection1.dwg", cov);
427             }
428           if (DWG_TYPE == DWG_TYPE_ACSH_BOOLEAN_CLASS ||
429               DWG_TYPE == DWG_TYPE_ACSH_BOX_CLASS ||
430               DWG_TYPE == DWG_TYPE_ACSH_BREP_CLASS ||
431               DWG_TYPE == DWG_TYPE_ACSH_CHAMFER_CLASS ||
432               DWG_TYPE == DWG_TYPE_ACSH_CYLINDER_CLASS ||
433               DWG_TYPE == DWG_TYPE_ACSH_EXTRUSION_CLASS ||
434               DWG_TYPE == DWG_TYPE_ACSH_FILLET_CLASS ||
435               DWG_TYPE == DWG_TYPE_ACSH_HISTORY_CLASS ||
436               DWG_TYPE == DWG_TYPE_ACSH_SWEEP_CLASS ||
437               DWG_TYPE == DWG_TYPE_ACSH_TORUS_CLASS ||
438               DWG_TYPE == DWG_TYPE_ACSH_WEDGE_CLASS)
439             {
440               error += test_code (prefix, "2007/ATMOS-DC22S.dwg", cov);
441               error += test_code_nodist (prefix, "2013/JW.dwg", cov);
442             }
443           if (DWG_TYPE == DWG_TYPE_ACSH_CONE_CLASS)
444             {
445               error += test_code (prefix, "2000/Cone.dwg", cov);
446             }
447           if (DWG_TYPE == DWG_TYPE_ACSH_LOFT_CLASS ||
448               DWG_TYPE == DWG_TYPE_ACSH_EXTRUSION_CLASS ||
449               DWG_TYPE == DWG_TYPE_ACSH_REVOLVE_CLASS ||
450               DWG_TYPE == DWG_TYPE_ACSH_SWEEP_CLASS ||
451               DWG_TYPE == DWG_TYPE_SKYLIGHT_BACKGROUND ||
452               DWG_TYPE == DWG_TYPE_MENTALRAYRENDERSETTINGS ||
453               DWG_TYPE == DWG_TYPE_RENDERGLOBAL)
454             {
455               error += test_code_nodist (
456                   prefix, "2010/visualization_-_condominium_with_skylight.dwg",
457                   cov);
458             }
459           if (DWG_TYPE == DWG_TYPE_ACSH_PYRAMID_CLASS)
460             {
461               error += test_code_nodist (prefix, "2000/Pyramid.dwg", cov);
462             }
463           if (DWG_TYPE == DWG_TYPE_ACSH_SPHERE_CLASS)
464             {
465               error += test_code_nodist (prefix, "2000/sphere.dwg", cov);
466               error += test_code_nodist (
467                   prefix, "2010/visualization_-_aerial.dwg", cov);
468             }
469           if (DWG_TYPE == DWG_TYPE_ASSOCVARIABLE ||
470               DWG_TYPE == DWG_TYPE_ASSOCVALUEDEPENDENCY ||
471               DWG_TYPE == DWG_TYPE_ASSOCGEOMDEPENDENCY ||
472               DWG_TYPE == DWG_TYPE_ASSOC2DCONSTRAINTGROUP ||
473               DWG_TYPE == DWG_TYPE_DYNAMICBLOCKPROXYNODE ||
474               DWG_TYPE == DWG_TYPE_BLOCKBASEPOINTPARAMETER ||
475               DWG_TYPE == DWG_TYPE_BLOCKFLIPACTION ||
476               DWG_TYPE == DWG_TYPE_BLOCKFLIPGRIP ||
477               DWG_TYPE == DWG_TYPE_BLOCKFLIPPARAMETER ||
478               DWG_TYPE == DWG_TYPE_BLOCKLINEARPARAMETER ||
479               DWG_TYPE == DWG_TYPE_BLOCKLINEARGRIP ||
480               DWG_TYPE == DWG_TYPE_BLOCKLOOKUPGRIP ||
481               DWG_TYPE == DWG_TYPE_BLOCKREPRESENTATION ||
482               DWG_TYPE == DWG_TYPE_BLOCKROTATEACTION ||
483               DWG_TYPE == DWG_TYPE_BLOCKROTATIONPARAMETER ||
484               DWG_TYPE == DWG_TYPE_BLOCKROTATIONGRIP ||
485               DWG_TYPE == DWG_TYPE_ASSOCDIMDEPENDENCYBODY)
486             {
487               error += test_code (prefix, "2018/Dynblocks.dwg", cov);
488               error += test_code_nodist (prefix, "2004/Dynblocks.dwg", cov);
489             }
490           if (DWG_TYPE == DWG_TYPE_ASSOCARRAYACTIONBODY ||
491               DWG_TYPE == DWG_TYPE_ASSOCDIMDEPENDENCYBODY)
492             {
493               error += test_code_nodist (prefix, "2004/planetarygear.dwg", cov);
494             }
495           if (DWG_TYPE == DWG_TYPE_ASSOC3POINTANGULARDIMACTIONBODY)
496             {
497               error += test_code_nodist (prefix,
498                  "../test-old/2013/from_cadforum.cz/TwistRibbnConstThick_2.dwg", cov);
499             }
500           if (DWG_TYPE == DWG_TYPE_BLOCKSCALEACTION ||
501               DWG_TYPE == DWG_TYPE_BLOCKMOVEACTION ||
502               DWG_TYPE == DWG_TYPE_BLOCKSTRETCHACTION)
503             {
504               error += test_code (prefix, "2018/Dynblocks.dwg", cov);
505               error += test_code_nodist (prefix, "2010/sun_and_sky_demo.dwg", cov);
506             }
507           if (DWG_TYPE == DWG_TYPE_BLOCKARRAYACTION)
508             {
509               error += test_code_nodist (
510                   prefix, "../test-old/2004/from_uloz.to/Klánovice_RD_A.dwg",
511                   cov);
512             }
513           if (DWG_TYPE == DWG_TYPE_DGNDEFINITION)
514             {
515               error += test_code_nodist (
516                   prefix, "../test-old/2004/from_uloz.to/Klánovice_RD_A_situace.dwg",
517                   cov);
518             }
519           if (DWG_TYPE == DWG_TYPE_BLOCKPOLARGRIP ||
520               DWG_TYPE == DWG_TYPE_BLOCKPOLARPARAMETER ||
521               DWG_TYPE == DWG_TYPE_BLOCKPOLARSTRETCHACTION)
522             {
523               error += test_code_nodist (
524                   prefix,
525                   "../test-old/2018/from_autocad_2021/Annotation - Metric.dwg",
526                   cov);
527               error += test_code_nodist (prefix,
528                                          "../test-old/2018/from_autocad_2021/"
529                                          "Annotation - Imperial.dwg",
530                                          cov);
531             }
532           if (DWG_TYPE == DWG_TYPE_BLOCKVISIBILITYPARAMETER ||
533               DWG_TYPE == DWG_TYPE_BLOCKVISIBILITYGRIP ||
534               DWG_TYPE == DWG_TYPE_BLOCKGRIPLOCATIONCOMPONENT)
535             {
536               error += test_code (prefix, "2018/Dynblocks.dwg", cov);
537               error += test_code (prefix, "2013/gh44-error.dwg", cov);
538             }
539           if (DWG_TYPE == DWG_TYPE_BLOCKHORIZONTALCONSTRAINTPARAMETER ||
540               DWG_TYPE == DWG_TYPE_BLOCKVERTICALCONSTRAINTPARAMETER ||
541               DWG_TYPE == DWG_TYPE_BLOCKPARAMDEPENDENCYBODY)
542             // missing BLOCKRADIALCONSTRAINTPARAMETER BLOCKALIGNEDCONSTRAINTPARAMETER
543             //   BLOCKDIAMETRICCONSTRAINTPARAMETER BLOCKLINEARCONSTRAINTPARAMETER
544             //   BLOCKANGULARCONSTRAINTPARAMETER
545             {
546               error += test_code_nodist (
547                   prefix,
548                   "../test-old/2000/1/Ashraf_Basic_File-1_Feet_input_2.dwg",
549                   cov);
550             }
551           if (DWG_TYPE == DWG_TYPE_BLOCKALIGNMENTPARAMETER ||
552               DWG_TYPE == DWG_TYPE_BLOCKALIGNMENTGRIP)
553             {
554               error += test_code (prefix, "2018/Dynblocks.dwg", cov);
555               error += test_code_nodist (prefix, "2013/flipped.dwg", cov);
556             }
557           if (DWG_TYPE == DWG_TYPE_DYNAMICBLOCKPURGEPREVENTER)
558             {
559               error += test_code_nodist (prefix, "2013/gh55-ltype.dwg", cov);
560               error += test_code_nodist (prefix, "2007/anchor_dynamic_block.dwg", cov);
561               error += test_code_nodist (prefix, "2010/sun_and_sky_demo.dwg", cov);
562             }
563           if (DWG_TYPE == DWG_TYPE_EVALUATION_GRAPH ||
564               DWG_TYPE == DWG_TYPE_BLOCKGRIPLOCATIONCOMPONENT ||
565               DWG_TYPE == DWG_TYPE_BLOCKPOINTPARAMETER ||
566               DWG_TYPE == DWG_TYPE_ALDIMOBJECTCONTEXTDATA ||
567               DWG_TYPE == DWG_TYPE_MTEXTOBJECTCONTEXTDATA)
568             {
569               error += test_code (prefix, "2013/gh44-error.dwg", cov);
570               error += test_code_nodist (
571                   prefix, "2007/blocks_and_tables_-_metric.dwg", cov);
572             }
573           if (DWG_TYPE == DWG_TYPE_BLOCKLOOKUPACTION ||
574               DWG_TYPE == DWG_TYPE_BLOCKLOOKUPPARAMETER ||
575               DWG_TYPE == DWG_TYPE_BLOCKLOOKUPGRIP ||
576               DWG_TYPE == DWG_TYPE_BLOCKXYPARAMETER)
577             {
578               error += test_code_nodist (prefix, "2010/sun_and_sky_demo.dwg", cov);
579             }
580           if (DWG_TYPE == DWG_TYPE_BLOCKXYGRIP)
581             {
582               error += test_code_nodist (prefix, "2010/sun_and_sky_demo.dwg",
583                                          cov);
584               error += test_code_nodist (
585                   prefix, "2007/blocks_and_tables_-_metric.dwg", cov);
586               error += test_code_nodist (
587                   prefix, "2007/blocks_and_tables_-_imperial.dwg", cov);
588             }
589           if (DWG_TYPE == DWG_TYPE_VBA_PROJECT)
590             {
591               error += test_code_nodist (
592                   prefix, // but here in section not in object
593                   "../test-old/2013/from_upcommons.upc.edu/DRAWINGS.dwg", cov);
594             }
595           if (DWG_TYPE == DWG_TYPE_RAPIDRTRENDERSETTINGS)
596             {
597               error += test_code (prefix, "2013/gh44-error.dwg", cov);
598               error += test_code (prefix, "2013/gh109_1.dwg", cov);
599               error += test_code_nodist (prefix, "2013/JW.dwg", cov);
600               error += test_code_nodist (prefix, "2013/gh55-ltype.dwg", cov);
601               error += test_code_nodist (prefix, "2013/stelprdb1144445.dwg", cov);
602               error += test_code_nodist (prefix, "2013/nrcs141p2_034463.dwg", cov);
603               error += test_code_nodist (prefix, "2018/redwg1.dwg", cov);
604               if (g_countmax == 1000) // only with -a
605                 error += test_code_nodist (
606                     prefix, "../test-big/2004/double_free_example.dwg", cov);
607             }
608           if (DWG_TYPE == DWG_TYPE_RENDERENVIRONMENT)
609             {
610               error += test_code_nodist (
611                   prefix, "../test-old/2007/from_uloz.to/VBK_MODEL1.dwg", cov);
612             }
613           if (DWG_TYPE == DWG_TYPE_RENDERENTRY)
614             {
615               error += test_code_nodist (prefix, "2007/ATMOS-DC22S.dwg", cov);
616               error += test_code_nodist (
617                   prefix, "2010/visualization_-_conference_room.dwg", cov);
618             }
619           if (DWG_TYPE == DWG_TYPE_POINTCLOUDCOLORMAP)
620             {
621               if (g_countmax == 1000) // only with -a
622                 error += test_code_nodist (prefix,
623                     "../test-big/2004/double_free_example.dwg", cov);
624             }
625           if (DWG_TYPE == DWG_TYPE_RASTERVARIABLES)
626             {
627               error += test_code_nodist (prefix, "2000/passenger_drone.dwg", cov);
628               error += test_code_nodist (prefix, "2004/PLANO_MASSANASSA.dwg", cov);
629               error += test_code_nodist (prefix, "2007/SALLE_DES_MACHINES.dwg", cov);
630               error += test_code_nodist (prefix, "2013/nrcs141p2_034463.dwg", cov);
631             }
632           if (DWG_TYPE == DWG_TYPE_SPATIAL_INDEX)
633             {
634               error += test_code_nodist (
635                   prefix,
636                   "../test-old/2004/from_uloz.to/00_005_POHLADY_Kl_A.dwg",
637                   cov);
638             }
639           if (DWG_TYPE == DWG_TYPE_OBJECT_PTR)
640             {
641               error += test_code_nodist (
642                   prefix, "../test-old/r13c3/from_autocad_r14/asesmp.dwg",
643                   cov);
644             }
645           if (DWG_TYPE == DWG_TYPE_ACMECOMMANDHISTORY ||
646               DWG_TYPE == DWG_TYPE_ACMESCOPE ||
647               DWG_TYPE == DWG_TYPE_ACMESTATEMGR)
648             {
649               error += test_code_nodist (prefix, "2013/JW.dwg", cov);
650               error += test_code_nodist (
651                   prefix,
652                   "../test-old/2010/AutoCAD_Mechanical_2019/Wheel_casing.dwg",
653                   cov);
654               error += test_code_nodist (
655                   prefix, "../test-old/2010/AutoCAD_Mechanical_2019/tray.dwg",
656                   cov);
657               error += test_code_nodist (
658                   prefix,
659                   "../test-old/2010/AutoCAD_Mechanical_2019/"
660                   "Trolley_Structure.dwg",
661                   cov);
662               error += test_code_nodist (
663                   prefix,
664                   "../test-old/2010/AutoCAD_Mechanical_2019/"
665                   "robot_handling_cell.dwg",
666                   cov);
667               error += test_code_nodist (
668                   prefix,
669                   "../test-old/2010/AutoCAD_Mechanical_2019/Pump_wheel.dwg",
670                   cov);
671               error += test_code_nodist (
672                   prefix,
673                   "../test-old/2010/AutoCAD_Mechanical_2019/Pump_cover.dwg",
674                   cov);
675               error += test_code_nodist (
676                   prefix,
677                   "../test-old/2010/AutoCAD_Mechanical_2019/LEVER_DETAIL.dwg",
678                   cov);
679               error += test_code_nodist (
680                   prefix,
681                   "../test-old/2010/AutoCAD_Mechanical_2019/GRIPPER.dwg", cov);
682               error += test_code_nodist (
683                   prefix,
684                   "../test-old/2010/AutoCAD_Mechanical_2019/"
685                   "GRIPPER_ASSEMBLY_NEW.dwg",
686                   cov);
687               error += test_code_nodist (
688                   prefix,
689                   "../test-old/2010/AutoCAD_Mechanical_2019/"
690                   "Gear_Pump_Subassy.dwg",
691                   cov);
692               error += test_code_nodist (
693                   prefix,
694                   "../test-old/2010/AutoCAD_Mechanical_2019/Drive_shaft.dwg",
695                   cov);
696               error += test_code_nodist (
697                   prefix,
698                   "../test-old/2010/AutoCAD_Mechanical_2019/Bottom_plate.dwg",
699                   cov);
700               error += test_code_nodist (
701                   prefix, "../test-old/2013/from_uloz.to/model-mechanical.dwg",
702                   cov);
703               error += test_code_nodist (
704                   prefix, "../test-old/2010/from_cadforum.cz/AMSTLSHAP2D.dwg",
705                   cov);
706             }
707           if (   DWG_TYPE == DWG_TYPE_ASSOCBLENDSURFACEACTIONBODY
708               || DWG_TYPE == DWG_TYPE_ASSOCEXTENDSURFACEACTIONBODY
709               || DWG_TYPE == DWG_TYPE_ASSOCFILLETSURFACEACTIONBODY
710               || DWG_TYPE == DWG_TYPE_ASSOCNETWORKSURFACEACTIONBODY
711               || DWG_TYPE == DWG_TYPE_ASSOCOFFSETSURFACEACTIONBODY
712               || DWG_TYPE == DWG_TYPE_ASSOCPATCHSURFACEACTIONBODY
713               || DWG_TYPE == DWG_TYPE_ASSOCTRIMSURFACEACTIONBODY
714               || DWG_TYPE == DWG_TYPE_SOLID_BACKGROUND
715               || DWG_TYPE == DWG_TYPE_IBL_BACKGROUND
716               || DWG_TYPE == DWG_TYPE_IMAGE_BACKGROUND
717               || DWG_TYPE == DWG_TYPE_GRADIENT_BACKGROUND
718               || DWG_TYPE == DWG_TYPE_GROUND_PLANE_BACKGROUND
719               || DWG_TYPE == DWG_TYPE_CAMERA
720               || DWG_TYPE == DWG_TYPE_DUMMY
721               || DWG_TYPE == DWG_TYPE_INDEX
722               || DWG_TYPE == DWG_TYPE_LARGE_RADIAL_DIMENSION
723               || DWG_TYPE == DWG_TYPE_LAYER_INDEX
724               || DWG_TYPE == DWG_TYPE_LAYERFILTER
725               || DWG_TYPE == DWG_TYPE_LIGHTLIST
726               || DWG_TYPE == DWG_TYPE_LONG_TRANSACTION
727               || DWG_TYPE == DWG_TYPE_OLEFRAME
728               || DWG_TYPE == DWG_TYPE_PROXY_ENTITY
729               || DWG_TYPE == DWG_TYPE_PROXY_OBJECT
730               || DWG_TYPE == DWG_TYPE_RENDERSETTINGS
731               || DWG_TYPE == DWG_TYPE_DGNUNDERLAY
732               || DWG_TYPE == DWG_TYPE_DWFUNDERLAY
733               || DWG_TYPE == DWG_TYPE_DWFDEFINITION
734               || DWG_TYPE == DWG_TYPE_ANGDIMOBJECTCONTEXTDATA
735               || DWG_TYPE == DWG_TYPE_ANNOTSCALEOBJECTCONTEXTDATA
736               || DWG_TYPE == DWG_TYPE_ARCALIGNEDTEXT
737               || DWG_TYPE == DWG_TYPE_ASSOCMLEADERACTIONBODY
738               || DWG_TYPE == DWG_TYPE_ASSOCARRAYMODIFYACTIONBODY
739               || DWG_TYPE == DWG_TYPE_ASSOCEDGECHAMFERACTIONBODY
740               || DWG_TYPE == DWG_TYPE_ASSOCEDGEFILLETACTIONBODY
741               || DWG_TYPE == DWG_TYPE_ASSOCRESTOREENTITYSTATEACTIONBODY
742               || DWG_TYPE == DWG_TYPE_ASSOCORDINATEDIMACTIONBODY
743               || DWG_TYPE == DWG_TYPE_ASSOCROTATEDDIMACTIONBODY
744               || DWG_TYPE == DWG_TYPE_ASSOCACTIONPARAM
745               || DWG_TYPE == DWG_TYPE_ASSOCASMBODYACTIONPARAM
746               || DWG_TYPE == DWG_TYPE_ASSOCCOMPOUNDACTIONPARAM
747               || DWG_TYPE == DWG_TYPE_ASSOCFACEACTIONPARAM
748               || DWG_TYPE == DWG_TYPE_ASSOCOBJECTACTIONPARAM
749               || DWG_TYPE == DWG_TYPE_ASSOCPOINTREFACTIONPARAM
750               || DWG_TYPE == DWG_TYPE_ASSOCARRAYMODIFYPARAMETERS
751               || DWG_TYPE == DWG_TYPE_ASSOCARRAYPATHPARAMETERS
752               || DWG_TYPE == DWG_TYPE_ASSOCARRAYPOLARPARAMETERS
753               || DWG_TYPE == DWG_TYPE_ASSOCARRAYRECTANGULARPARAMETERS
754               || DWG_TYPE == DWG_TYPE_CONTEXTDATAMANAGER
755               || DWG_TYPE == DWG_TYPE_CURVEPATH
756               || DWG_TYPE == DWG_TYPE_DMDIMOBJECTCONTEXTDATA
757               || DWG_TYPE == DWG_TYPE_FCFOBJECTCONTEXTDATA
758               || DWG_TYPE == DWG_TYPE_GEOMAPIMAGE
759               || DWG_TYPE == DWG_TYPE_GEOPOSITIONMARKER
760               || DWG_TYPE == DWG_TYPE_MOTIONPATH
761               || DWG_TYPE == DWG_TYPE_MPOLYGON
762               || DWG_TYPE == DWG_TYPE_NAVISWORKSMODEL
763               || DWG_TYPE == DWG_TYPE_NAVISWORKSMODELDEF
764               || DWG_TYPE == DWG_TYPE_ORDDIMOBJECTCONTEXTDATA
765               || DWG_TYPE == DWG_TYPE_PARTIAL_VIEWING_INDEX
766               || DWG_TYPE == DWG_TYPE_POINTCLOUD
767               || DWG_TYPE == DWG_TYPE_POINTCLOUDEX
768               || DWG_TYPE == DWG_TYPE_POINTCLOUDDEF
769               || DWG_TYPE == DWG_TYPE_POINTCLOUDDEFEX
770               || DWG_TYPE == DWG_TYPE_POINTCLOUDDEF_REACTOR
771               || DWG_TYPE == DWG_TYPE_POINTCLOUDDEF_REACTOR_EX
772               || DWG_TYPE == DWG_TYPE_POINTPATH
773               || DWG_TYPE == DWG_TYPE_POLARGRIPENTITY
774               || DWG_TYPE == DWG_TYPE_RADIMOBJECTCONTEXTDATA
775               || DWG_TYPE == DWG_TYPE_RADIMLGOBJECTCONTEXTDATA
776               || DWG_TYPE == DWG_TYPE_RTEXT
777               || DWG_TYPE == DWG_TYPE_SUNSTUDY
778               || DWG_TYPE == DWG_TYPE_TVDEVICEPROPERTIES
779               || DWG_TYPE == DWG_TYPE_VISIBILITYPARAMETERENTITY
780               || DWG_TYPE == DWG_TYPE_VISIBILITYGRIPENTITY
781               || DWG_TYPE == DWG_TYPE_ALIGNMENTPARAMETERENTITY
782               || DWG_TYPE == DWG_TYPE_BASEPOINTPARAMETERENTITY
783               || DWG_TYPE == DWG_TYPE_BLOCKALIGNEDCONSTRAINTPARAMETER
784               || DWG_TYPE == DWG_TYPE_BLOCKANGULARCONSTRAINTPARAMETER
785               || DWG_TYPE == DWG_TYPE_BLOCKDIAMETRICCONSTRAINTPARAMETER
786               || DWG_TYPE == DWG_TYPE_BLOCKLINEARCONSTRAINTPARAMETER
787               || DWG_TYPE == DWG_TYPE_BLOCKPROPERTIESTABLE
788               || DWG_TYPE == DWG_TYPE_BLOCKPROPERTIESTABLEGRIP
789               || DWG_TYPE == DWG_TYPE_BLOCKRADIALCONSTRAINTPARAMETER
790               || DWG_TYPE == DWG_TYPE_BLOCKUSERPARAMETER
791               || DWG_TYPE == DWG_TYPE_FLIPPARAMETERENTITY
792               || DWG_TYPE == DWG_TYPE_LINEARPARAMETERENTITY
793               || DWG_TYPE == DWG_TYPE_POINTPARAMETERENTITY
794               || DWG_TYPE == DWG_TYPE_ROTATIONPARAMETERENTITY
795               || DWG_TYPE == DWG_TYPE_XYPARAMETERENTITY
796               )
797             {
798               ; // missing
799             }
800         }
801 #ifdef DWG_TYPE
802       if (cov && !numpassed () && !numfailed ())
803         printf ("TODO no coverage for %s\n", dwg_type_name (DWG_TYPE));
804 #endif
805     }
806   else
807     error = test_code (NULL, input, cov);
808 
809   return error;
810 }
811 
812 /// test all DWG's in all subdirs. not on windows yet
813 int
test_subdirs(const char * dir,int cov)814 test_subdirs (const char *dir, int cov)
815 {
816   int error = 0, n;
817   struct stat attrib;
818   struct dirent **namelist;
819 
820 #ifdef HAVE_SCANDIR
821   n = scandir (dir, &namelist, NULL, NULL);
822   if (n < 0)
823     {
824       perror ("scandir");
825       exit (1);
826     }
827   while (n--)
828     {
829       char *elem = namelist[n]->d_name;
830 
831       if (namelist[n]->d_type == DT_DIR && *elem != '.')
832         {
833           char path[256];
834           path[255] = '\0';
835           strncpy (path, dir, 254);
836           strncat (path, "/", 254);
837           strncat (path, elem, 254);
838           path[255] = '\0';
839 
840           error += test_subdirs (path, cov);
841         }
842       if (namelist[n]->d_type == DT_REG &&
843           (strstr (elem, ".dwg") || strstr (elem, ".DWG")))
844         {
845           error += test_code (dir, elem, cov);
846         }
847 
848       free (namelist[n]);
849     }
850   free (namelist);
851 #endif
852   return error;
853 }
854 
855 #ifdef IS_RELEASE
856 /* Do not test not distributed DWG's.
857    This would skip existing files, but still report FAIL.
858 */
test_code_nodist(const char * dir,const char * filename,int cov)859 int test_code_nodist (const char *dir, const char *filename, int cov)
860 {
861   return 0;
862 }
863 #else
test_code_nodist(const char * dir,const char * filename,int cov)864 int test_code_nodist (const char *dir, const char *filename, int cov)
865 {
866   return test_code (dir, filename, cov);
867 }
868 #endif
869 
870 /// test a DWG file
871 int
test_code(const char * dir,const char * filename,int cov)872 test_code (const char *dir, const char *filename, int cov)
873 {
874   int error;
875   char path[256];
876   struct stat attrib;
877 
878   path[255] = '\0';
879   if (dir)
880     {
881       strncpy (path, dir, 254);
882       strncat (path, "/", 254);
883       strncat (path, filename, 254);
884     }
885   else
886     strncpy (path, filename, 254);
887   path[255] = '\0';
888 
889 #ifdef DWG_TYPE
890   // only process if no coverage yet, or when we are crossing the unicode
891   // boundary.
892   if (strstr (path, "2018") || strstr (path, "2007")
893       || (!numpassed () && !numfailed ()))
894     {
895       if (cov)
896         LOG_INFO ("Testing with %s:\n", path)
897     }
898   else if (cov)
899     {
900       LOG_INFO ("Skipping %s:\n", path)
901       return 0;
902     }
903   if (stat (path, &attrib))
904     {
905       LOG_INFO ("file not found:\n")
906       return 0;
907     }
908 #endif
909   error = dwg_read_file (path, &g_dwg);
910   if (error < DWG_ERR_CRITICAL)
911     {
912       output_test (&g_dwg);
913       dwg_free (&g_dwg);
914     }
915   /* This value is the return value for `main',
916      so clamp it to either 0 or 1.  */
917   error = (error >= DWG_ERR_CRITICAL || numfailed () > 0) ? 1 : 0;
918 #ifdef DWG_TYPE
919   if (is_type_unstable (DWG_TYPE) || is_type_debugging (DWG_TYPE))
920     {
921       if (cov && error)
922         LOG_INFO ("%s failed (TODO: unstable)\n", path);
923       return 0;
924     }
925   else // some exceptions, because we dont want to publish all our test-cases.
926        // test-data is already too big.
927     if (DWG_TYPE == DWG_TYPE_IDBUFFER ||
928         DWG_TYPE == DWG_TYPE_ACSH_SPHERE_CLASS ||
929         DWG_TYPE == DWG_TYPE_BLOCKGRIPLOCATIONCOMPONENT ||
930         DWG_TYPE == DWG_TYPE_BLOCKBASEPOINTPARAMETER
931         )
932       {
933         if (cov && error)
934           LOG_INFO ("%s failed (TODO: skipped)\n", path);
935         return 0;
936       }
937 #endif
938   if (cov && error)
939     LOG_WARN ("%s failed", path);
940   return error;
941 }
942 
943 /// Iterate over the objects in a block
944 void
output_BLOCK_HEADER(dwg_object_ref * ref)945 output_BLOCK_HEADER (dwg_object_ref *ref)
946 {
947   dwg_object *hdr, *obj;
948   int error;
949   g_counter = 0;
950 
951   if (!ref)
952     return;
953   hdr = dwg_ref_get_object (ref, &error);
954   if (!hdr)
955     return;
956 
957   obj = get_first_owned_entity (hdr);
958   while (obj)
959     {
960       output_object (obj);
961       if (dwg_obj_has_subentity (obj))
962         {
963           Dwg_Object *owner = obj;
964           obj = get_first_owned_subentity (owner);
965           while (obj)
966             {
967               output_object (obj);
968               obj = get_next_owned_subentity (owner, obj);
969             }
970           obj = get_next_owned_entity (hdr, owner);
971         }
972       else
973         obj = get_next_owned_entity (hdr, obj);
974     }
975 }
976 
977 /// Iterate over both modelspace and paperspace blocks
978 /// And if nothing found, over all other blocks.
979 void
output_test(dwg_data * dwg)980 output_test (dwg_data *dwg)
981 {
982   int error;
983   dwg_object *obj;
984   dwg_obj_block_header *_hdr;
985   dwg_obj_block_control *_ctrl;
986   dwg_object_ref *ref, **hdr_refs;
987 
988   if (!dwg)
989     return;
990 #ifdef USE_DEPRECATED_API
991   dwg_api_init_version (dwg);
992 #endif
993   _hdr = dwg_get_block_header (dwg, &error);
994   if (!_hdr || error)
995     return;
996   _ctrl = dwg_block_header_get_block_control (_hdr, &error);
997   if (!_ctrl || error)
998     return;
999 
1000 #ifndef DWG_TYPE
1001   /* process all owned entities */
1002   ref = dwg_obj_block_control_get_model_space (_ctrl, &error);
1003   if (!error)
1004     {
1005       LOG_INFO ("mspace\n");
1006       output_BLOCK_HEADER (ref);
1007     }
1008   ref = dwg_obj_block_control_get_paper_space (_ctrl, &error);
1009   if (!error)
1010     {
1011       LOG_INFO ("pspace\n");
1012       output_BLOCK_HEADER (ref);
1013     }
1014 #endif
1015 
1016 #ifdef DWG_TYPE
1017   if (DWG_TYPE == DWG_TYPE_BLOCK_CONTROL)
1018     {
1019       for (unsigned i = 0; i < dwg->num_objects; i++)
1020         {
1021           obj = &dwg->object[i];
1022           LOG_TRACE ("  %s [%d]\n", obj->name, obj->index);
1023           if (obj->fixedtype == DWG_TYPE)
1024             {
1025               g_counter++;
1026               LOG_INFO ("  %s [%d] (%s)\n", obj->name, obj->index, stability);
1027               output_process (obj);
1028             }
1029         }
1030     }
1031   else
1032     {
1033       obj = &dwg->object[0];
1034       while ((obj = dwg_next_object (obj)))
1035         {
1036           LOG_TRACE ("  %s [%d]\n", obj->name, obj->index);
1037           // printf ("%s [%d]\n", obj->name, obj->index);
1038           if (obj->fixedtype == DWG_TYPE)
1039             {
1040               g_counter++;
1041               LOG_INFO ("  %s [%d] (%s)\n", obj->name, obj->index, stability);
1042               output_process (obj);
1043             }
1044         }
1045     }
1046   /* also process blocks? we better find DWGs with these */
1047   if (!numpassed () && !numfailed ())
1048     {
1049       /* and now also all subtypes and entities in blocks */
1050       unsigned int j;
1051       unsigned int num_hdr_objs
1052           = dwg_obj_block_control_get_num_entries (_ctrl, &error);
1053       if (error || !num_hdr_objs)
1054         return;
1055       hdr_refs = dwg_obj_block_control_get_block_headers (_ctrl, &error);
1056       if (error)
1057         return;
1058       for (j = 0; j < num_hdr_objs; j++)
1059         {
1060           if (hdr_refs[j])
1061             output_BLOCK_HEADER (hdr_refs[j]);
1062         }
1063       free (hdr_refs);
1064     }
1065 #endif
1066 }
1067 
1068 /// Main output function that prints to the terminal
1069 void
output_process(dwg_object * obj)1070 output_process (dwg_object *obj)
1071 {
1072   // print_low_level (obj);
1073   print_api (obj);
1074 }
1075 
1076 #ifdef DWG_TYPE
1077 void
output_object(dwg_object * obj)1078 output_object (dwg_object *obj)
1079 {
1080   if (!obj)
1081     {
1082       LOG_INFO ("object is NULL\n");
1083       return;
1084     }
1085   LOG_TRACE ("  %s [%d]\n", obj->name, obj->index);
1086   if (obj->fixedtype == DWG_TYPE)
1087     {
1088       g_counter++;
1089       output_process (obj);
1090     }
1091 }
1092 #endif
1093 
1094 /// Low level printing function (ignored)
1095 void
print_low_level(dwg_object * obj)1096 print_low_level (dwg_object *obj)
1097 {
1098   printf ("\n");
1099   printf ("Printed via low level access:\n");
1100   // low_level_process (obj);
1101   printf ("\n");
1102 }
1103 
1104 /// API based printing function
1105 void
print_api(dwg_object * obj)1106 print_api (dwg_object *obj)
1107 {
1108 #ifdef DWG_TYPE
1109   LOG_INFO ("Unit-testing type %d %s [%d] (%s):\n", DWG_TYPE, obj->name, g_counter,
1110             stability);
1111 #else
1112   LOG_INFO ("Test dwg_api and dynapi [%d]:\n", g_counter);
1113 #endif
1114   api_process (obj);
1115 
1116   if (obj->supertype == DWG_SUPERTYPE_ENTITY &&
1117       obj->fixedtype != DWG_TYPE_UNKNOWN_ENT)
1118     api_common_entity (obj);
1119   else if (obj->supertype == DWG_SUPERTYPE_OBJECT &&
1120            obj->fixedtype != DWG_TYPE_UNKNOWN_OBJ)
1121     api_common_object (obj);
1122   if (g_counter <= g_countmax)
1123     LOG_INFO ("\n");
1124 }
1125 
1126 #define CHK_COMMON_TYPE(ent, field, type)                                     \
1127   {                                                                           \
1128     if (dwg_dynapi_common_value (ent, #field, &field, NULL))                  \
1129       {                                                                       \
1130         if (field == ent->parent->field)                                      \
1131           pass (); /*(#field ":\t" FORMAT_##type, field);*/                   \
1132         else                                                                  \
1133           fail (#field ":\t" FORMAT_##type, field);                           \
1134       }                                                                       \
1135     else                                                                      \
1136       fail (#field);                                                          \
1137   }
1138 #define CHK_COMMON_TYPE2(ent, field, type, value)                             \
1139   {                                                                           \
1140     if (dwg_dynapi_common_value (ent, #field, &value, NULL))                  \
1141       {                                                                       \
1142         if (value == ent->parent->field)                                      \
1143           pass (); /*(#field ":\t" FORMAT_##type, value);*/                   \
1144         else                                                                  \
1145           fail (#field ":\t" FORMAT_##type, value);                           \
1146       }                                                                       \
1147     else                                                                      \
1148       fail (#field);                                                          \
1149   }
1150 
1151 #define CHK_COMMON_H(ent, field)                                              \
1152   {                                                                           \
1153     if (!dwg_dynapi_common_value (ent, #field, &field, NULL))                 \
1154       fail (#field);                                                          \
1155     else if (!field)                                                          \
1156       pass ();                                                                \
1157     else                                                                      \
1158       {                                                                       \
1159         char *_hdlname = dwg_dynapi_handle_name (dwg, field);                 \
1160         if (field == (BITCODE_H)ent->parent->field)                           \
1161           {                                                                   \
1162             if (g_counter > g_countmax)                                       \
1163               pass ();                                                        \
1164             else                                                              \
1165               ok (#field ": %s " FORMAT_REF, _hdlname ? _hdlname : "",        \
1166                   ARGS_REF (field));                                          \
1167           }                                                                   \
1168         else                                                                  \
1169           fail (#field ": %s " FORMAT_REF, _hdlname ? _hdlname : "",          \
1170                 ARGS_REF (field));                                            \
1171         if (version >= R_2007)                                                \
1172           free (_hdlname);                                                    \
1173       }                                                                       \
1174   }
1175 
1176 #define CHK_COMMON_HV(ent, field, num)                                        \
1177   if (!dwg_dynapi_common_value (ent, #field, &field, NULL))                   \
1178     fail (#field);                                                            \
1179   else if (!field)                                                            \
1180     pass ();                                                                  \
1181   else                                                                        \
1182     {                                                                         \
1183       for (int _i = 0; _i < (int)(num); _i++)                                 \
1184         {                                                                     \
1185           BITCODE_H _hdl = field[_i];                                         \
1186           char *_hdlname = _hdl ? dwg_dynapi_handle_name (dwg, _hdl) : NULL;  \
1187           if (_hdl == ent->parent->field[_i])                                 \
1188             {                                                                 \
1189               if (g_counter > g_countmax)                                     \
1190                 pass ();                                                      \
1191               else                                                            \
1192                 {                                                             \
1193                   if (_hdl)                                                   \
1194                     ok (#field "[%d]: %s " FORMAT_REF, _i, _hdlname ?: "",    \
1195                         ARGS_REF (_hdl));                                     \
1196                   else                                                        \
1197                     ok (#field "[%d]: NULL", _i);                             \
1198                 }                                                             \
1199             }                                                                 \
1200           else                                                                \
1201             {                                                                 \
1202               if (_hdl)                                                       \
1203                 fail (#field "[%d]: %s " FORMAT_REF, _i, _hdlname ?: "",      \
1204                       ARGS_REF (_hdl));                                       \
1205               else                                                            \
1206                 {                                                             \
1207                   if (g_counter > g_countmax)                                 \
1208                     pass ();                                                  \
1209                   else                                                        \
1210                     ok (#field "[%d]: NULL", _i);                             \
1211                 }                                                             \
1212             }                                                                 \
1213           if (_hdlname && version >= R_2007)                                  \
1214             free (_hdlname);                                                  \
1215         }                                                                     \
1216     }
1217 
1218 void
api_common_entity(dwg_object * obj)1219 api_common_entity (dwg_object *obj)
1220 {
1221   BITCODE_BB entmode;
1222   BITCODE_H ownerhandle;
1223   BITCODE_BL num_reactors, num_eed;
1224   BITCODE_H *reactors;
1225   BITCODE_B is_xdic_missing, has_ds_data, preview_exists;
1226   BITCODE_RC linewt;
1227   BITCODE_RL preview_size_rl;
1228   BITCODE_BLL preview_size;
1229   BITCODE_BD ltype_scale;
1230   BITCODE_BS invisible;
1231   BITCODE_H xdicobjhandle;
1232   BITCODE_H prev_entity;
1233   BITCODE_H next_entity;
1234   BITCODE_H layer;
1235   BITCODE_H ltype;
1236   BITCODE_H material;
1237   BITCODE_H shadow;
1238   BITCODE_H plotstyle;
1239   BITCODE_H full_visualstyle;
1240   BITCODE_H face_visualstyle;
1241   BITCODE_H edge_visualstyle;
1242   Dwg_Data *dwg = obj->parent;
1243   Dwg_Version_Type version = obj->parent->header.version;
1244   Dwg_Object_Entity *_ent = obj->tio.entity;
1245   Dwg_Entity_LINE *ent = obj->tio.entity->tio.LINE;
1246 
1247   CHK_COMMON_TYPE (ent, entmode, BB)
1248   CHK_COMMON_TYPE (ent, preview_exists, B)
1249   if (preview_exists)
1250     {
1251       if (version >= R_2010)
1252         CHK_COMMON_TYPE (ent, preview_size, BLL)
1253       else
1254         CHK_COMMON_TYPE2 (ent, preview_size, RL, preview_size_rl);
1255     }
1256   if (entmode == 3 || entmode == 0)
1257     CHK_COMMON_H (ent, ownerhandle);
1258   CHK_COMMON_H (ent, layer);
1259   if (version < R_2000)
1260     {
1261       if (_ent->isbylayerlt)
1262         CHK_COMMON_H (ent, ltype);
1263       if (!_ent->nolinks)
1264         {
1265           CHK_COMMON_H (ent, prev_entity);
1266           CHK_COMMON_H (ent, next_entity);
1267         }
1268     }
1269   else
1270     {
1271       if (_ent->ltype_flags == 3)
1272         CHK_COMMON_H (ent, ltype);
1273     }
1274   CHK_COMMON_TYPE (ent, linewt, RC);
1275   CHK_COMMON_TYPE (ent, ltype_scale, BD);
1276   if (version >= R_2007)
1277     {
1278       if (_ent->material_flags == 3)
1279         CHK_COMMON_H (ent, material);
1280       if (_ent->shadow_flags == 3)
1281         CHK_COMMON_H (ent, shadow);
1282     }
1283   if (version >= R_2000)
1284     {
1285       if (_ent->plotstyle_flags == 3)
1286         CHK_COMMON_H (ent, plotstyle);
1287     }
1288   if (version >= R_2010)
1289     {
1290       if (_ent->has_full_visualstyle)
1291         CHK_COMMON_H (ent, full_visualstyle);
1292       if (_ent->has_face_visualstyle)
1293         CHK_COMMON_H (ent, face_visualstyle);
1294       if (_ent->has_edge_visualstyle)
1295         CHK_COMMON_H (ent, edge_visualstyle);
1296     }
1297   CHK_COMMON_TYPE (ent, invisible, BS);
1298 
1299   CHK_COMMON_TYPE (ent, is_xdic_missing, B);
1300   if (!is_xdic_missing)
1301     CHK_COMMON_H (ent, xdicobjhandle);
1302   CHK_COMMON_TYPE (ent, num_reactors, BL);
1303   CHK_COMMON_HV (ent, reactors, num_reactors);
1304   CHK_COMMON_TYPE (ent, has_ds_data, B);
1305   CHK_COMMON_TYPE (ent, num_eed, BL);
1306 }
1307 
1308 #define _CHK_ENTITY_UTF8TEXT(ent, name, field)                                \
1309   if (dwg_dynapi_entity_utf8text (ent, #name, #field, &field, &isnew, NULL))  \
1310     {                                                                         \
1311       if (g_counter > g_countmax)                                             \
1312         pass ();                                                              \
1313       else                                                                    \
1314         ok (#name "." #field ":\t\"%s\"", field);                             \
1315     }                                                                         \
1316   else                                                                        \
1317     {                                                                         \
1318       Dwg_Version_Type _dwg_version = ent->parent->dwg->header.version;       \
1319       if (_dwg_version < R_2007)                                              \
1320         fail (#name "." #field ":\t\"%s\"", field);                           \
1321       else                                                                    \
1322         fail (#name "." #field ":\t\"%s\"...", field);                        \
1323     }
1324 
1325 #define CHK_ENTITY_UTF8TEXT(ent, name, field)                                 \
1326   _CHK_ENTITY_UTF8TEXT (ent, name, field);                                    \
1327   if (isnew)                                                                  \
1328     free (field)
1329 
1330 #define CHK_ENTITY_TYPE(ent, name, field, typ)                                \
1331   if (!dwg_dynapi_entity_value (ent, #name, #field, &field, NULL))            \
1332     fail (#name "." #field);                                                  \
1333   else                                                                        \
1334     {                                                                         \
1335       if (field == ent->field)                                                \
1336         {                                                                     \
1337           if (g_counter > g_countmax)                                         \
1338             pass ();                                                          \
1339           else                                                                \
1340             ok (#name "." #field ":\t" FORMAT_##typ, field);                  \
1341         }                                                                     \
1342       else                                                                    \
1343         fail (#name "." #field ":\t" FORMAT_##typ " [" #typ "]", field);      \
1344     }
1345 
1346 #define CHK_ENTITY_CMC(ent, name, field)                                      \
1347   if (!dwg_dynapi_entity_value (ent, #name, #field, &field, NULL))            \
1348     fail (#name "." #field);                                                  \
1349   else                                                                        \
1350     {                                                                         \
1351       if (memcmp (&field, &ent->field, sizeof (Dwg_Color)) == 0)              \
1352         {                                                                     \
1353           if (g_counter > g_countmax)                                         \
1354             pass ();                                                          \
1355           else                                                                \
1356             ok (#name "." #field ":\t" FORMAT_BSd, field.index);              \
1357         }                                                                     \
1358       else                                                                    \
1359         fail (#name "." #field ":\t" FORMAT_BSd " [CMC]", field.index);       \
1360     }
1361 
1362 #define CHK_ENTITY_H(ent, name, field)                                        \
1363   {                                                                           \
1364     if (!dwg_dynapi_entity_value (ent, #name, #field, &field, NULL))          \
1365       fail (#name "." #field);                                                \
1366     else if (!field)                                                          \
1367       pass ();                                                                \
1368     else                                                                      \
1369       {                                                                       \
1370         Dwg_Version_Type _version = ent->parent->dwg->header.version;         \
1371         char *_hdlname = dwg_dynapi_handle_name (obj->parent, field);         \
1372         if (field == ent->field)                                              \
1373           {                                                                   \
1374             if (g_counter > g_countmax)                                       \
1375               pass ();                                                        \
1376             else                                                              \
1377               ok (#name "." #field ": %s " FORMAT_REF,                        \
1378                   _hdlname ? _hdlname : "", ARGS_REF (field));                \
1379           }                                                                   \
1380         else                                                                  \
1381           {                                                                   \
1382             fail (#name "." #field ": %s " FORMAT_REF,                        \
1383                   _hdlname ? _hdlname : "", ARGS_REF (field));                \
1384           }                                                                   \
1385         if (_version >= R_2007)                                               \
1386           free (_hdlname);                                                    \
1387       }                                                                       \
1388   }
1389 
1390 #define CHK_ENTITY_HV(ent, name, field, num)                                  \
1391   if (!dwg_dynapi_entity_value (ent, #name, #field, &field, NULL))            \
1392     fail (#name "." #field);                                                  \
1393   else if (!field)                                                            \
1394     pass ();                                                                  \
1395   else                                                                        \
1396     {                                                                         \
1397       Dwg_Version_Type _version = ent->parent->dwg->header.version;           \
1398       for (int _i = 0; _i < (int)(num); _i++)                                 \
1399         {                                                                     \
1400           BITCODE_H _hdl = field[_i];                                         \
1401           char *_hdlname = _hdl ? dwg_dynapi_handle_name (obj->parent, _hdl) : NULL; \
1402           if (_hdl == ent->field[_i])                                         \
1403             {                                                                 \
1404               if (g_counter > g_countmax)                                     \
1405                 pass ();                                                      \
1406               else                                                            \
1407                   if (_hdl)                                                   \
1408                     ok (#field "[%d]: %s " FORMAT_REF, _i, _hdlname ?: "",    \
1409                         ARGS_REF (_hdl));                                     \
1410                   else                                                        \
1411                     ok (#field "[%d]: NULL", _i);                             \
1412             }                                                                 \
1413           else                                                                \
1414             {                                                                 \
1415               if (_hdl)                                                       \
1416                 fail (#field "[%d]: %s " FORMAT_REF, _i, _hdlname ?: "",      \
1417                       ARGS_REF (_hdl));                                       \
1418               else                                                            \
1419                 {                                                             \
1420                   if (g_counter > g_countmax)                                 \
1421                     pass ();                                                  \
1422                   else                                                        \
1423                     ok (#field "[%d]: NULL", _i);                             \
1424                 }                                                             \
1425             }                                                                 \
1426           if (_hdlname && _version >= R_2007)                                 \
1427             free (_hdlname);                                                  \
1428         }                                                                     \
1429     }
1430 
1431 // i must be defined as type of num
1432 #define CHK_ENTITY_VECTOR_TYPE(ent, name, field, num, type)                   \
1433   if (!dwg_dynapi_entity_value (ent, #name, #field, &field, NULL))            \
1434     fail (#name "." #field);                                                  \
1435   else if (!field)                                                            \
1436     pass ();                                                                  \
1437   else                                                                        \
1438     {                                                                         \
1439       for (i = 0; i < (num); i++)                                             \
1440         {                                                                     \
1441           if (ent->field[i] != field[i])                                      \
1442             fail (#name "." #field "[%d]: " FORMAT_##type, i, field[i]);      \
1443           else                                                                \
1444             ok (#name "." #field "[%d]: " FORMAT_##type, i, field[i]);        \
1445         }                                                                     \
1446     }
1447 
1448 #define CHK_ENTITY_VECTOR(ent, name, field, num)                              \
1449   if (!dwg_dynapi_entity_value (ent, #name, #field, &field, NULL))            \
1450     fail (#name "." #field);                                                  \
1451   else if (!field)                                                            \
1452     pass ();                                                                  \
1453   else                                                                        \
1454     {                                                                         \
1455       for (i = 0; i < (num); i++)                                             \
1456         {                                                                     \
1457           if (memcmp (&ent->field[i], &field[i], sizeof (field[i])))          \
1458             fail ("%s.%s[%d]:", #name, #field, i);                            \
1459           else                                                                \
1460             ok ("%s.%s[%d]:", #name, #field, i);                              \
1461         }                                                                     \
1462     }
1463 
1464 // i must be defined as type of num
1465 #define CHK_ENTITY_3DPOINTS(ent, name, field, num)                            \
1466   if (!dwg_dynapi_entity_value (ent, #name, #field, &field, NULL))            \
1467     fail (#name "." #field);                                                  \
1468   else if (!field)                                                            \
1469     pass ();                                                                  \
1470   else                                                                        \
1471     {                                                                         \
1472       for (i = 0; i < (num); i++)                                             \
1473         {                                                                     \
1474           ok ("%s.%s[%d]: (%f, %f, %f)", #name, #field, i, field[i].x,        \
1475               field[i].y, field[i].z);                                        \
1476           if (memcmp (&ent->field[i], &field[i], sizeof (field[i])))          \
1477             fail ("%s.%s[%d]: memcmp", #name, #field, i);                     \
1478         }                                                                     \
1479     }
1480 // i must be defined as type of num
1481 #define CHK_ENTITY_2DPOINTS(ent, name, field, num)                            \
1482   if (!dwg_dynapi_entity_value (ent, #name, #field, &field, NULL))            \
1483     fail (#name "." #field);                                                  \
1484   else if (!field)                                                            \
1485     pass ();                                                                  \
1486   else                                                                        \
1487     {                                                                         \
1488       for (i = 0; i < (num); i++)                                             \
1489         {                                                                     \
1490           ok ("%s.%s[%d]: (%f, %f)", #name, #field, i, field[i].x, field[i].y); \
1491           if (memcmp (&ent->field[i], &field[i], sizeof (field[i])))          \
1492             fail ("%s.%s[%d]: memcmp", #name, #field, i);                     \
1493         }                                                                     \
1494     }
1495 
1496 #define CHK_ENTITY_2RD(ent, name, field)                                      \
1497   if (!dwg_dynapi_entity_value (ent, #name, #field, &field, NULL))            \
1498     fail (#name "." #field);                                                  \
1499   else                                                                        \
1500     {                                                                         \
1501       if (field.x == ent->field.x && field.y == ent->field.y)                 \
1502         {                                                                     \
1503           if (g_counter > g_countmax)                                         \
1504             pass ();                                                          \
1505           else                                                                \
1506             ok (#name "." #field ":\t(%f, %f)", field.x, field.y);            \
1507         }                                                                     \
1508       else                                                                    \
1509         fail (#name "." #field ":\t(%f, %f)", field.x, field.y);              \
1510     }
1511 
1512 #define CHK_ENTITY_3RD(ent, name, field)                                      \
1513   if (!dwg_dynapi_entity_value (ent, #name, #field, &field, NULL))            \
1514     fail (#name "." #field);                                                  \
1515   else                                                                        \
1516     {                                                                         \
1517       if (field.x == ent->field.x && field.y == ent->field.y                  \
1518           && field.z == ent->field.z)                                         \
1519         {                                                                     \
1520           if (g_counter > g_countmax)                                         \
1521             pass ();                                                          \
1522           else                                                                \
1523             ok (#name "." #field ":\t(%f, %f, %f)", field.x, field.y,         \
1524                 field.z);                                                     \
1525         }                                                                     \
1526       else                                                                    \
1527         fail (#name "." #field ":\t(%f, %f, %f)", field.x, field.y, field.z); \
1528     }
1529 
1530 #define CHK_ENTITY_TIMEBLL(ent, name, field)                                  \
1531   if (!dwg_dynapi_entity_value (ent, #name, #field, &field, NULL))            \
1532     fail (#name "." #field);                                                  \
1533   else                                                                        \
1534     ok ("%s.%s " FORMAT_BL "." FORMAT_BL, #name, #field, field.days, field.ms);
1535 
1536 #define CHK_ENTITY_MAX(ent, name, field, type, _max)                          \
1537   if (field > _max)                                                           \
1538     fail ("Invalid " #name "." #field " " FORMAT_##type " > " #_max, field)
1539 
1540 #define _DWGAPI_ENT_NAME(name, field) dwg_ent_##name##_get_##field
1541 #define DWGAPI_ENT_NAME(ent, field) _DWGAPI_ENT_NAME (ent, field)
1542 #define _DWGAPI_OBJ_NAME(name, field) dwg_obj_##name##_get_##field
1543 #define DWGAPI_OBJ_NAME(ent, field) _DWGAPI_OBJ_NAME (ent, field)
1544 #define DWGAPI_ENTOBJ_NAME(ent, field)                                        \
1545   (ent->parent->dwg->object[ent->parent->objid].supertype == DWG_SUPERTYPE_OBJECT  \
1546     ? _DWGAPI_OBJ_NAME (ent, field)                                           \
1547     : _DWGAPI_ENT_NAME (ent, field))
1548 
1549 #ifndef USE_DEPRECATED_API
1550 #  define CHK_ENTITY_UTF8TEXT_W_OLD(ent, name, field)     \
1551   CHK_ENTITY_UTF8TEXT(ent, name, field)
1552 #  define CHK_ENTITY_UTF8TEXT_W_OBJ(ent, name, field)     \
1553   CHK_ENTITY_UTF8TEXT(ent, name, field)
1554 #else
1555 #define CHK_ENTITY_UTF8TEXT_W_OLD(ent, name, field)                           \
1556   _CHK_ENTITY_UTF8TEXT (ent, name, field);                                    \
1557   {                                                                           \
1558     Dwg_Version_Type _dwg_version = ent->parent->dwg->header.version;         \
1559     if (ent->field)                                                           \
1560       {                                                                       \
1561         char *old = DWGAPI_ENT_NAME (ent, field) (ent, &error);               \
1562         if (error || (old && strcmp (old, field)))                            \
1563           fail ("old API dwg_ent_" #ent "_get_" #field ": \"%s\"", old);      \
1564         if (_dwg_version >= R_2007)                                           \
1565           free (old);                                                         \
1566       }                                                                       \
1567     if (isnew)                                                                \
1568       free (field);                                                           \
1569   }
1570 #define CHK_ENTITY_UTF8TEXT_W_OBJ(ent, name, field)                           \
1571   _CHK_ENTITY_UTF8TEXT (ent, name, field);                                    \
1572   {                                                                           \
1573     Dwg_Version_Type _dwg_version = ent->parent->dwg->header.version;         \
1574     if (ent->field)                                                           \
1575       {                                                                       \
1576         char *old = DWGAPI_OBJ_NAME (ent, field) (ent, &error);               \
1577         if (error || (old && strcmp (old, field)))                            \
1578           fail ("old API dwg_obj_" #ent "_get_" #field ": \"%s\"", old);      \
1579         else                                                                  \
1580           pass ();                                                            \
1581         if (_dwg_version >= R_2007)                                           \
1582           free (old);                                                         \
1583       }                                                                       \
1584     if (isnew)                                                                \
1585       free (field);                                                           \
1586   }
1587 #endif
1588 
1589 #ifndef USE_DEPRECATED_API
1590 #  define CHK_ENTITY_TYPE_W_OLD(ent, name, field, type)        \
1591   CHK_ENTITY_TYPE(ent, name, field, type)
1592 #  define CHK_ENTITY_TYPE_W_OBJ(ent, name, field, type)        \
1593   CHK_ENTITY_TYPE(ent, name, field, type)
1594 #else
1595 #define CHK_ENTITY_TYPE_W_OLD(ent, name, field, type)                         \
1596   {                                                                           \
1597     BITCODE_##type old;                                                       \
1598     CHK_ENTITY_TYPE (ent, name, field, type);                                 \
1599     old = DWGAPI_ENT_NAME (ent, field) (ent, &error);                         \
1600     if (error || old != field)                                                \
1601       fail ("old API dwg_ent_" #ent "_get_" #field ": " FORMAT_##type         \
1602             " != " FORMAT_##type,                                             \
1603             old, field);                                                      \
1604     else                                                                      \
1605       pass ();                                                                \
1606   }
1607 
1608 #define CHK_ENTITY_TYPE_W_OBJ(ent, name, field, type)                         \
1609   {                                                                           \
1610     BITCODE_##type old;                                                       \
1611     CHK_ENTITY_TYPE (ent, name, field, type);                                 \
1612     old = DWGAPI_OBJ_NAME (ent, field) (ent, &error);                         \
1613     if (error || old != field)                                                \
1614       fail ("old API dwg_obj_" #ent "_get_" #field ": " FORMAT_##type " != "  \
1615         FORMAT_##type, old, field);                                           \
1616     else                                                                      \
1617       pass ();                                                                \
1618   }
1619 #endif
1620 
1621 #ifndef USE_DEPRECATED_API
1622 #  define CHK_ENTITY_2RD_W_OLD(ent, name, field) CHK_ENTITY_2RD (ent, name, field)
1623 #  define CHK_ENTITY_3RD_W_OLD(ent, name, field) CHK_ENTITY_3RD (ent, name, field)
1624 #else
1625 #define CHK_ENTITY_2RD_W_OLD(ent, name, field)                                \
1626   CHK_ENTITY_2RD (ent, name, field);                                          \
1627   {                                                                           \
1628     dwg_point_2d _pt2d;                                                       \
1629     DWGAPI_ENT_NAME (ent, field) (ent, &_pt2d, &error);                       \
1630     if (error || memcmp (&field, &_pt2d, sizeof (field)))                     \
1631       fail ("old API dwg_ent_" #ent "_get_" #field);                          \
1632     else                                                                      \
1633       pass ();                                                                \
1634   }
1635 #define CHK_ENTITY_3RD_W_OLD(ent, name, field)                         	      \
1636   CHK_ENTITY_3RD (ent, name, field);                                          \
1637   {                                                                           \
1638     dwg_point_3d _pt3d;                                                       \
1639     DWGAPI_ENT_NAME (ent, field) (ent, &_pt3d, &error);                       \
1640     if (error || memcmp (&field, &_pt3d, sizeof (field)))                     \
1641       fail ("old API dwg_ent_" #ent "_get_" #field);                          \
1642     else                                                                      \
1643       pass ();                                                                \
1644   }
1645 #endif
1646 
1647 #define CHK_SUBCLASS_TYPE(ptr, name, field, typ)                              \
1648   {                                                                           \
1649     BITCODE_##typ _value;                                                     \
1650     bool _ok;                                                                 \
1651     if (dwg_dynapi_entity_fields (#name))                                     \
1652       _ok = dwg_dynapi_entity_value (&ptr, #name, #field, &_value, NULL);     \
1653     else                                                                      \
1654       _ok = dwg_dynapi_subclass_value (&ptr, #name, #field, &_value, NULL);   \
1655     if (!_ok)                                                                 \
1656       fail (#name "." #field);                                                \
1657     else                                                                      \
1658       {                                                                       \
1659         if (ptr.field == _value)                                              \
1660           {                                                                   \
1661             if (g_counter > g_countmax)                                       \
1662               pass ();                                                        \
1663             else                                                              \
1664               ok (#name "." #field ":\t" FORMAT_##typ, ptr.field);            \
1665           }                                                                   \
1666         else                                                                  \
1667           fail (#name "." #field ":\t" FORMAT_##typ " [" #typ "]",            \
1668                 ptr.field);                                                   \
1669       }                                                                       \
1670   }
1671 #define CHK_SUBCLASS_3RD(ptr, name, field)                                    \
1672   {                                                                           \
1673     BITCODE_3RD _value;                                                       \
1674     bool _ok;                                                                 \
1675     if (dwg_dynapi_entity_fields (#name))                                     \
1676       _ok = dwg_dynapi_entity_value (&ptr, #name, #field, &_value, NULL);     \
1677     else                                                                      \
1678       _ok = dwg_dynapi_subclass_value (&ptr, #name, #field, &_value, NULL);   \
1679     if (!_ok)                                                                 \
1680       fail (#name "." #field);                                                \
1681     else                                                                      \
1682       {                                                                       \
1683         if (_value.x == ptr.field.x && _value.y == ptr.field.y                \
1684             && _value.z == ptr.field.z)                                       \
1685           {                                                                   \
1686             if (g_counter > g_countmax)                                       \
1687               pass ();                                                        \
1688             else                                                              \
1689               ok (#name "." #field ":\t(%f, %f, %f)", _value.x, _value.y,     \
1690                   _value.z);                                                  \
1691           }                                                                   \
1692         else                                                                  \
1693           fail (#name "." #field ":\t(%f, %f, %f)", _value.x, _value.y,       \
1694                 _value.z);                                                    \
1695       }                                                                       \
1696   }
1697 
1698 #define CHK_SUBCLASS_3DPOINTS(ptr, name, field, num)                          \
1699   {                                                                           \
1700     BITCODE_3RD *_value = NULL;                                               \
1701     bool _ok;                                                                 \
1702     if (dwg_dynapi_entity_fields (#name))                                     \
1703       _ok = dwg_dynapi_entity_value (&ptr, #name, #field, &_value, NULL);     \
1704     else                                                                      \
1705       _ok = dwg_dynapi_subclass_value (&ptr, #name, #field, &_value, NULL);   \
1706     if (!_ok)                                                                 \
1707       fail (#name "." #field);                                                \
1708     else if (!_value)                                                         \
1709       pass ();                                                                \
1710     else                                                                      \
1711       {                                                                       \
1712         for (unsigned _i = 0; _i < (num); _i++)                               \
1713           {                                                                   \
1714             if (_value[_i].x == ptr.field[_i].x                               \
1715                 && _value[_i].y == ptr.field[_i].y                            \
1716                 && _value[_i].z == ptr.field[_i].z)                           \
1717               {                                                               \
1718                 if (g_counter > g_countmax)                                   \
1719                   pass ();                                                    \
1720                 else                                                          \
1721                   ok (#name "." #field "[%d]:\t(%f, %f, %f)", i,              \
1722                       _value[_i].x, _value[_i].y, _value[_i].z);              \
1723               }                                                               \
1724             else                                                              \
1725               fail (#name "." #field "[%d]:\t(%f, %f, %f)", i, _value[_i].x,  \
1726                     _value[_i].y, _value[_i].z);                              \
1727           }                                                                   \
1728       }                                                                       \
1729   }
1730 #define CHK_SUBCLASS_2RD(ptr, name, field)                                    \
1731   {                                                                           \
1732     BITCODE_2RD _value;                                                       \
1733     bool _ok;                                                                 \
1734     if (dwg_dynapi_entity_fields (#name))                                     \
1735       _ok = dwg_dynapi_entity_value (&ptr, #name, #field, &_value, NULL);     \
1736     else                                                                      \
1737       _ok = dwg_dynapi_subclass_value (&ptr, #name, #field, &_value, NULL);   \
1738     if (!_ok)                                                                 \
1739       fail (#name "." #field);                                                \
1740     else                                                                      \
1741       {                                                                       \
1742         if (_value.x == ptr.field.x && _value.y == ptr.field.y)               \
1743           {                                                                   \
1744             if (g_counter > g_countmax)                                       \
1745               pass ();                                                        \
1746             else                                                              \
1747               ok (#name "." #field ":\t(%f, %f)", _value.x, _value.y);        \
1748           }                                                                   \
1749         else                                                                  \
1750           fail (#name "." #field ":\t(%f, %f)", _value.x, _value.y);          \
1751       }                                                                       \
1752   }
1753 #define CHK_SUBCLASS_2DPOINTS(ptr, name, field, num)                          \
1754   {                                                                           \
1755     BITCODE_3RD *_value = NULL;                                               \
1756     bool _ok;                                                                 \
1757     if (dwg_dynapi_entity_fields (#name))                                     \
1758       _ok = dwg_dynapi_entity_value (&ptr, #name, #field, &_value, NULL);     \
1759     else                                                                      \
1760       _ok = dwg_dynapi_subclass_value (&ptr, #name, #field, &_value, NULL);   \
1761     if (!_ok)                                                                 \
1762       fail (#name "." #field);                                                \
1763     else if (!_value)                                                         \
1764       pass ();                                                                \
1765     else                                                                      \
1766       {                                                                       \
1767         for (unsigned _i = 0; _i < (num); _i++)                               \
1768           {                                                                   \
1769             if (_value[_i].x == ptr.field[_i].x                               \
1770                 && _value[_i].y == ptr.field[_i].y)                           \
1771               {                                                               \
1772                 if (g_counter > g_countmax)                                   \
1773                   pass ();                                                    \
1774                 else                                                          \
1775                   ok (#name "." #field "[%d]:\t(%f, %f)", i, _value[_i].x,    \
1776                       _value[_i].y);                                          \
1777               }                                                               \
1778             else                                                              \
1779               fail (#name "." #field "[%d]:\t(%f, %f)", i, _value[_i].x,      \
1780                     _value[_i].y);                                            \
1781           }                                                                   \
1782       }                                                                       \
1783   }
1784 #define CHK_SUBCLASS_H(ptr, name, field)                                      \
1785   {                                                                           \
1786     BITCODE_H _value;                                                         \
1787     bool _ok;                                                                 \
1788     if (dwg_dynapi_entity_fields (#name))                                     \
1789       _ok = dwg_dynapi_entity_value (&ptr, #name, #field, &_value, NULL);     \
1790     else                                                                      \
1791       _ok = dwg_dynapi_subclass_value (&ptr, #name, #field, &_value, NULL);   \
1792     if (!_ok)                                                                 \
1793       fail (#name "." #field);                                                \
1794     else                                                                      \
1795       {                                                                       \
1796         char *_hdlname                                                        \
1797             = _value ? dwg_dynapi_handle_name (obj->parent, _value) : NULL;   \
1798         if (!_value)                                                          \
1799           {                                                                   \
1800             if (!ptr.field)                                                   \
1801               {                                                               \
1802                 if (g_counter > g_countmax)                                   \
1803                   pass ();                                                    \
1804                 else                                                          \
1805                   ok (#name "." #field ":\tNULL");                            \
1806               }                                                               \
1807             else                                                              \
1808               fail (#name "." #field ":\tNULL");                              \
1809           }                                                                   \
1810         else if (memcmp (&ptr.field, &_value, sizeof _value) == 0)            \
1811           {                                                                   \
1812             if (g_counter > g_countmax)                                       \
1813               pass ();                                                        \
1814             else                                                              \
1815               ok (#name "." #field ":\t %s " FORMAT_REF, _hdlname ?: "",      \
1816                   ARGS_REF (_value));                                         \
1817           }                                                                   \
1818         else                                                                  \
1819           fail (#name "." #field ":\t %s " FORMAT_REF, _hdlname ?: "",        \
1820                 ARGS_REF (_value));                                           \
1821         if (_hdlname && dwg_version >= R_2007)                                \
1822           free (_hdlname);                                                    \
1823       }                                                                       \
1824   }
1825 #define CHK_SUBCLASS_HV(ptr, name, field, num)                                \
1826   if (!dwg_dynapi_subclass_value (&ptr, #name, #field, &field, NULL))         \
1827     fail (#name "." #field);                                                  \
1828   else if (!field)                                                            \
1829     pass ();                                                                  \
1830   else                                                                        \
1831     {                                                                         \
1832       for (int _i = 0; _i < (int)(num); _i++)                                 \
1833         {                                                                     \
1834           BITCODE_H _hdl = field[_i];                                         \
1835           if (_hdl == ptr.field[_i])                                          \
1836             {                                                                 \
1837               if (g_counter > g_countmax)                                     \
1838                 pass ();                                                      \
1839               else                                                            \
1840                 ok (#name "." #field "[%d]: " FORMAT_REF, _i,                 \
1841                     ARGS_REF (_hdl));                                         \
1842             }                                                                 \
1843           else                                                                \
1844             {                                                                 \
1845               fail (#name "." #field "[%d]: " FORMAT_REF, _i,                 \
1846                     ARGS_REF (_hdl));                                         \
1847             }                                                                 \
1848         }                                                                     \
1849     }
1850 #define CHK_SUBCLASS_VECTOR_TYPE(ptr, name, field, num, type)                 \
1851   {                                                                           \
1852     BITCODE_##type *_value = NULL;                                            \
1853     bool _ok;                                                                 \
1854     if (dwg_dynapi_entity_fields (#name))                                     \
1855       _ok = dwg_dynapi_entity_value (&ptr, #name, #field, &_value, NULL);     \
1856     else                                                                      \
1857       _ok = dwg_dynapi_subclass_value (&ptr, #name, #field, &_value, NULL);   \
1858     if (!_ok)                                                                 \
1859       fail (#name "." #field);                                                \
1860     else if (!_value)                                                         \
1861       pass ();                                                                \
1862     else                                                                      \
1863       {                                                                       \
1864         for (unsigned _i = 0; _i < (num); _i++)                               \
1865           {                                                                   \
1866             if (_value[_i] == ptr.field[_i])                                  \
1867               {                                                               \
1868                 if (g_counter > g_countmax)                                   \
1869                   pass ();                                                    \
1870                 else                                                          \
1871                   ok (#name "." #field "[%d]:\t " FORMAT_##type, _i,          \
1872                       _value[_i]);                                            \
1873               }                                                               \
1874             else                                                              \
1875               fail (#name "." #field "[%d]:\t " FORMAT_##type, _i,            \
1876                     _value[_i]);                                              \
1877           }                                                                   \
1878       }                                                                       \
1879   }
1880 #define CHK_SUBCLASS_UTF8TEXT(ptr, name, field)                               \
1881   {                                                                           \
1882     BITCODE_TV _value;                                                        \
1883     bool _ok;                                                                 \
1884     if (dwg_dynapi_entity_fields (#name))                                     \
1885       _ok = dwg_dynapi_entity_value (&ptr, #name, #field, &_value, NULL);     \
1886     else                                                                      \
1887       _ok = dwg_dynapi_subclass_value (&ptr, #name, #field, &_value, NULL);   \
1888     if (_ok)                                                                  \
1889       {                                                                       \
1890         if (g_counter > g_countmax)                                           \
1891           pass ();                                                            \
1892         else                                                                  \
1893           ok (#name "." #field ":\t\"%s\"", _value);                          \
1894       }                                                                       \
1895     else                                                                      \
1896       {                                                                       \
1897         if (dwg_version < R_2007)                                             \
1898           fail (#name "." #field ":\t\"%s\"", _value);                        \
1899         else                                                                  \
1900           fail (#name "." #field);                                            \
1901       }                                                                       \
1902   }
1903 #define CHK_SUBCLASS_CMC(ptr, name, field)                                    \
1904   if (!dwg_dynapi_subclass_value (&ptr, #name, #field, &ptr.field, NULL))     \
1905     fail (#name "." #field);                                                  \
1906   else                                                                        \
1907     {                                                                         \
1908       if (g_counter > g_countmax)                                             \
1909         pass ();                                                              \
1910       else                                                                    \
1911         ok (#name "." #field ":\t%d", ptr.field.index);                       \
1912     }
1913 #define CHK_SUBCLASS_MAX(ptr, name, field, type, _max)                        \
1914   if (ptr.field > _max)                                                       \
1915     fail ("Invalid " #name "." #field " " FORMAT_##type " > " #_max, ptr.field)
1916 
1917 
1918 void
api_common_object(dwg_object * obj)1919 api_common_object (dwg_object *obj)
1920 {
1921   BITCODE_H ownerhandle, xdicobjhandle, handleref;
1922   BITCODE_BL num_reactors, num_eed;
1923   BITCODE_H *reactors;
1924   BITCODE_B is_xdic_missing, has_ds_data;
1925   Dwg_Data *dwg = obj->parent;
1926   Dwg_Version_Type version = obj->parent->header.version;
1927   Dwg_Object_Object *obj_obj = obj->tio.object;
1928   Dwg_Object_LAYER *_obj = obj->tio.object->tio.LAYER;
1929 
1930   CHK_COMMON_H (_obj, ownerhandle);
1931   CHK_COMMON_TYPE (_obj, is_xdic_missing, B);
1932   if (!is_xdic_missing)
1933     CHK_COMMON_H (_obj, xdicobjhandle);
1934   CHK_COMMON_TYPE (_obj, num_reactors, BL);
1935   CHK_COMMON_HV (_obj, reactors, num_reactors);
1936   CHK_COMMON_H (_obj, handleref); //?
1937   CHK_COMMON_TYPE (_obj, has_ds_data, B);
1938   CHK_COMMON_TYPE (_obj, num_eed, BL);
1939 }
1940 
1941 #define CHK_EVALEXPR(type)                                                    \
1942   CHK_SUBCLASS_TYPE (_obj->evalexpr, EvalExpr, parentid, BLd);                \
1943   CHK_SUBCLASS_TYPE (_obj->evalexpr, EvalExpr, major, BL);                    \
1944   CHK_SUBCLASS_TYPE (_obj->evalexpr, EvalExpr, minor, BL);                    \
1945   /* variant_DXF type */                                                      \
1946   CHK_SUBCLASS_TYPE (_obj->evalexpr, EvalExpr, value_code, BSd);              \
1947   /* variant_value's */                                                       \
1948   switch (_obj->evalexpr.value_code)                                          \
1949     {                                                                         \
1950     case 40:                                                                  \
1951       CHK_SUBCLASS_TYPE (_obj->evalexpr, EvalExpr, value.num40, BD);          \
1952       break;                                                                  \
1953     case 10:                                                                  \
1954       CHK_SUBCLASS_2RD (_obj->evalexpr, EvalExpr, value.pt2d);                \
1955       break;                                                                  \
1956     case 11:                                                                  \
1957       CHK_SUBCLASS_3RD (_obj->evalexpr, EvalExpr, value.pt3d);                \
1958       break;                                                                  \
1959     case 1:                                                                   \
1960       CHK_SUBCLASS_UTF8TEXT (_obj->evalexpr, EvalExpr, value.text1);          \
1961       break;                                                                  \
1962     case 90:                                                                  \
1963       CHK_SUBCLASS_TYPE (_obj->evalexpr, EvalExpr, value.long90, BL);         \
1964       break;                                                                  \
1965     case 91:                                                                  \
1966       CHK_SUBCLASS_H (_obj->evalexpr, EvalExpr, value.handle91);              \
1967       break;                                                                  \
1968     case 70:                                                                  \
1969       CHK_SUBCLASS_TYPE (_obj->evalexpr, EvalExpr, value.short70, BS);        \
1970       break;                                                                  \
1971     case -9999:                                                               \
1972     default:                                                                  \
1973       break;                                                                  \
1974     }                                                                         \
1975   CHK_SUBCLASS_TYPE (_obj->evalexpr, EvalExpr, nodeid, BL)
1976 
1977 #define CHK_ACSH_HISTORYNODE()                                                \
1978   CHK_SUBCLASS_TYPE (_obj->history_node, ACSH_HistoryNode, major, BL);        \
1979   CHK_SUBCLASS_TYPE (_obj->history_node, ACSH_HistoryNode, minor, BL);        \
1980   /* last 16x nums 40-55 */                                                   \
1981   if (!dwg_dynapi_subclass_value (&_obj->history_node, "ACSH_HistoryNode",    \
1982                                   "trans", &trans, NULL))                     \
1983     fail ("ACSH_HistoryNode.trans");                                          \
1984   else                                                                        \
1985     {                                                                         \
1986       bool good = 1;                                                          \
1987       for (int i = 0; i < 16; i += 4)                                         \
1988         {                                                                     \
1989           for (int j = i; j < i + 4; j++)                                     \
1990             { /* catches nan */                                               \
1991               if (trans[j] != _obj->history_node.trans[j])                    \
1992                 good = 0;                                                     \
1993             }                                                                 \
1994           if (good)                                                           \
1995             ok ("ACSH_HistoryNode.trans[%d]: (%f, %f, %f, %f)", i, trans[i],  \
1996                 trans[i + 1], trans[i + 2], trans[i + 3]);                    \
1997           else                                                                \
1998             fail ("ACSH_HistoryNode.trans[%d]: (%f, %f, %f, %f)", i,          \
1999                   trans[i], trans[i + 1], trans[i + 2], trans[i + 3]);        \
2000         }                                                                     \
2001     }                                                                         \
2002   CHK_SUBCLASS_CMC (_obj->history_node, ACSH_HistoryNode, color);             \
2003   CHK_SUBCLASS_TYPE (_obj->history_node, ACSH_HistoryNode, step_id, BL);      \
2004   CHK_SUBCLASS_H (_obj->history_node, ACSH_HistoryNode, material)
2005 
2006 #define CHK_VALUEPARAM(numfield, valprefix)                                   \
2007   for (unsigned i = 0; i < _obj->numfield; i++)                               \
2008     {                                                                         \
2009       CHK_SUBCLASS_TYPE (_obj->valprefix[i], VALUEPARAM, class_version, BL);  \
2010       CHK_SUBCLASS_UTF8TEXT (_obj->valprefix[i], VALUEPARAM, name);           \
2011       CHK_SUBCLASS_TYPE (_obj->valprefix[i], VALUEPARAM, unit_type, BL);      \
2012       CHK_SUBCLASS_TYPE (_obj->valprefix[i], VALUEPARAM, num_vars, BL);       \
2013       CHK_SUBCLASS_H (_obj->valprefix[i], VALUEPARAM, controlled_objdep);     \
2014       for (unsigned j = 0; j < _obj->valprefix[i].num_vars; j++)              \
2015         {                                                                     \
2016           unsigned dxf = _obj->valprefix[i].vars[j].value.code;               \
2017           CHK_SUBCLASS_TYPE (_obj->valprefix[i].vars[j].value, EvalVariant,   \
2018                              code, BSd);                                      \
2019           switch (dwg_resbuf_value_type (dxf))                                \
2020             {                                                                 \
2021             case DWG_VT_REAL:                                                 \
2022               CHK_SUBCLASS_TYPE (_obj->valprefix[i].vars[j].value,            \
2023                                  EvalVariant, u.bd, BD);                      \
2024               break;                                                          \
2025             case DWG_VT_INT32:                                                \
2026               CHK_SUBCLASS_TYPE (_obj->valprefix[i].vars[j].value,            \
2027                                  EvalVariant, u.bl, BL);                      \
2028               break;                                                          \
2029             case DWG_VT_INT16:                                                \
2030               CHK_SUBCLASS_TYPE (_obj->valprefix[i].vars[j].value,            \
2031                                  EvalVariant, u.bs, BS);                      \
2032               break;                                                          \
2033             case DWG_VT_INT8:                                                 \
2034               CHK_SUBCLASS_TYPE (_obj->valprefix[i].vars[j].value,            \
2035                                  EvalVariant, u.rc, RC);                      \
2036               break;                                                          \
2037             case DWG_VT_STRING:                                               \
2038               CHK_SUBCLASS_UTF8TEXT (_obj->valprefix[i].vars[j].value,        \
2039                                      EvalVariant, u.text);                    \
2040               break;                                                          \
2041             case DWG_VT_HANDLE:                                               \
2042               CHK_SUBCLASS_H (_obj->valprefix[i].vars[j].value, EvalVariant,  \
2043                               u.handle);                                      \
2044               break;                                                          \
2045             case DWG_VT_BINARY:                                               \
2046             case DWG_VT_OBJECTID:                                             \
2047             case DWG_VT_POINT3D:                                              \
2048             case DWG_VT_INVALID:                                              \
2049             case DWG_VT_INT64:                                                \
2050             case DWG_VT_BOOL:                                                 \
2051             default:                                                          \
2052               fail ("Unknown VALUEPARAM.vars[%d].value.code %u", j, dxf);     \
2053             }                                                                 \
2054           CHK_SUBCLASS_H (_obj->valprefix[i], VALUEPARAM, controlled_objdep); \
2055         }                                                                     \
2056     }
2057 
2058 // FIXME TYPE unused
2059 #define CHK_ASSOCPARAMBASEDACTIONBODY(TYPE)                                   \
2060   PRE (R_2013) {                                                              \
2061     CHK_SUBCLASS_TYPE (_obj->pab, ASSOCPARAMBASEDACTIONBODY, version, BL);    \
2062     CHK_SUBCLASS_TYPE (_obj->pab, ASSOCPARAMBASEDACTIONBODY, minor, BL);      \
2063     CHK_SUBCLASS_TYPE (_obj->pab, ASSOCPARAMBASEDACTIONBODY, num_deps, BL);   \
2064     CHK_SUBCLASS_HV (_obj->pab, ASSOCPARAMBASEDACTIONBODY, deps,              \
2065                      _obj->pab.num_deps);                                     \
2066     CHK_SUBCLASS_TYPE (_obj->pab, ASSOCPARAMBASEDACTIONBODY, l4, BL);         \
2067     CHK_SUBCLASS_TYPE (_obj->pab, ASSOCPARAMBASEDACTIONBODY, l5, BL);         \
2068     CHK_SUBCLASS_H (_obj->pab, ASSOCPARAMBASEDACTIONBODY, assocdep);          \
2069     CHK_SUBCLASS_TYPE (_obj->pab, ASSOCPARAMBASEDACTIONBODY, num_values, BL); \
2070     CHK_VALUEPARAM (pab.num_values, pab.values);                              \
2071   }
2072 
2073 #define BLOCKPARAMETER_PropInfo(_prop)                                        \
2074   {                                                                           \
2075     Dwg_BLOCKPARAMETER_connection *connections;                               \
2076     CHK_SUBCLASS_TYPE (_obj->_prop, BLOCKPARAMETER_PropInfo, num_connections, \
2077                        BL);                                                   \
2078     if (!dwg_dynapi_subclass_value (&_obj->_prop, "BLOCKPARAMETER_PropInfo",  \
2079                                     "connections", &connections, NULL))       \
2080       fail ("BLOCKPARAMETER." #_prop ".connections");                         \
2081     else                                                                      \
2082       for (i = 0; i < _obj->_prop.num_connections; i++)                       \
2083         {                                                                     \
2084           CHK_SUBCLASS_TYPE (_obj->_prop.connections[i],                      \
2085                              BLOCKPARAMETER_connection, code, BL);            \
2086           CHK_SUBCLASS_UTF8TEXT (_obj->_prop.connections[i],                  \
2087                                  BLOCKPARAMETER_connection, name);            \
2088         }                                                                     \
2089   }
2090 
2091 // allow old deprecated API
2092 GCC31_DIAG_IGNORE (-Wdeprecated-declarations)
2093 GCC46_DIAG_IGNORE (-Wdeprecated-declarations)
2094