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