1 /* ex: ft=c: -*- mode: c; -*- */
2 /*****************************************************************************/
3 /* LibreDWG - free implementation of the DWG file format */
4 /* */
5 /* Copyright (C) 2020 Free Software Foundation, Inc. */
6 /* */
7 /* This library is free software, licensed under the terms of the GNU */
8 /* General Public License as published by the Free Software Foundation, */
9 /* either version 3 of the License, or (at your option) any later version. */
10 /* You should have received a copy of the GNU General Public License */
11 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
12 /*****************************************************************************/
13
14 /* compare against dxf values, generated from examples/unknown */
15 /* written by: Reini Urban */
16
17 #define DXF_TEST_C
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <math.h>
22
23 #include "config.h"
24 #ifdef HAVE_UNISTD_H
25 # include <unistd.h>
26 #endif
27 #include "../../programs/my_stat.h"
28 #include "common.h"
29 #include "decode.h"
30 #include "tests_common.h"
31 #include "dwg.h"
32 #include "dwg_api.h"
33
34 int g_counter;
35 #define MAX_COUNTER 10
36 int g_max_count;
37 int g_all;
38
39 void object_alias (char *restrict name);
40 void entity_alias (char *restrict name);
41 ATTRIBUTE_MALLOC char *dwg_dynapi_subclass_name (const char *restrict type);
42 int dwg_dynapi_subclass_size (const char *restrict name);
43
44 #include "../../examples/unknown.h"
45
46 static struct _unknown_dxf unknown_dxf[] = {
47 // see log_unknown_dxf.pl
48 #include "../../examples/alldxf_0.inc"
49 { NULL, NULL, 0, "", 0, 0, 0, 0, 0, 0, 0, NULL }
50 };
51
52 #include "../../examples/alldxf_1.inc"
53
54 static void
55 test_subclass (const Dwg_Data *restrict dwg, const void *restrict ptr,
56 const struct _unknown_field *restrict f,
57 const Dwg_DYNAPI_field *restrict fp,
58 const char *restrict subclass, const char *restrict fieldname,
59 const char *restrict key, int index)
60 {
61 Dwg_DYNAPI_field field;
62 enum RESBUF_VALUE_TYPE vtype;
63 Dwg_Version_Type dwg_version = dwg->header.version;
64
65 if (!ptr)
66 {
67 fail ("test_subclass %s.%s: empty ptr", subclass, key);
68 return;
69 }
70 if (strEQc (fp->type, "CMC"))
71 {
72 BITCODE_CMC color;
73 if (dwg_dynapi_subclass_value (ptr, subclass, key, &color, &field))
74 {
75 BITCODE_BS i = (BITCODE_BS)strtol (f->value, NULL, 10);
76 if (i == color.index)
77 {
78 if (g_counter > g_max_count)
79 pass ();
80 else
81 ok ("%s[%d].%s: %s", fieldname, index, key, f->value);
82 }
83 else if (field.type)
84 fail ("%s[%d].%s: %d <=> \"%s\" [%s]", fieldname, index, key,
85 (int)color.index, f->value, field.type);
86 else
87 {
88 if (g_counter > g_max_count)
89 pass ();
90 else
91 ok ("%s[%d].%s: %d <=> \"%s\" [CMC] (TODO)", fieldname, index,
92 key, (int)color.index, f->value);
93 }
94 }
95 return;
96 }
97 vtype = dwg_resbuf_value_type (f->code);
98 if (vtype == DWG_VT_REAL && fp->size >= 16)
99 goto DWG_VT_POINT3D;
100 if (vtype == DWG_VT_INT8 && fp->size == 1 && strEQc (fp->type, "B"))
101 goto DWG_VT_BOOL;
102 if ((vtype == DWG_VT_BOOL || vtype == DWG_VT_INT16) && fp->size == 1
103 && strEQc (fp->type, "RC"))
104 goto DWG_VT_INT8;
105 if (vtype == DWG_VT_INT8 && fp->size == 2)
106 goto DWG_VT_INT16;
107 if (vtype == DWG_VT_INT16 && fp->size == 4)
108 goto DWG_VT_INT32;
109 if (vtype == DWG_VT_INT32 && fp->size == 8)
110 goto DWG_VT_INT64;
111 switch (vtype)
112 {
113 case DWG_VT_STRING:
114 {
115 char *value;
116 int isnew = 0;
117 if (dwg_dynapi_subclass_value (ptr, subclass, key, &value, &field))
118 {
119 // convert to UTF8
120 if (value && dwg_version >= R_2007
121 && strNE (field.type, "TF")) /* not TF */
122 {
123 value = bit_convert_TU ((BITCODE_TU)value);
124 if (!value) // some conversion error, invalid wchar (nyi)
125 {
126 fail ("%s[%d].%s: NULL [STRING %s]", fieldname, index, key,
127 field.type);
128 }
129 else
130 {
131 isnew = 1;
132 }
133 }
134 if (!value || strEQ (value, f->value))
135 {
136 if (g_counter > g_max_count)
137 pass ();
138 else
139 ok ("%s[%d].%s: %s", fieldname, index, key, value);
140 }
141 else
142 fail ("%s[%d].%s: %s [STRING %s]", fieldname, index, key, value,
143 field.type);
144 }
145 if (isnew)
146 free (value);
147 }
148 break;
149 case DWG_VT_POINT3D:
150 DWG_VT_POINT3D:
151 {
152 BITCODE_3BD pt;
153 if (dwg_dynapi_subclass_value (ptr, subclass, key, &pt, &field))
154 {
155 double d = strtod (f->value, NULL);
156 double ptv;
157 int offset = f->code;
158 if (strstr (field.type, "_1"))
159 {
160 while (offset > 10) // 10,11,12
161 offset -= 10;
162 if (offset == 2 && field.size > 2 * sizeof (double))
163 ptv = pt.z;
164 else if (offset == 1)
165 ptv = pt.y;
166 else
167 ptv = pt.x;
168 }
169 else // 10/20/30
170 {
171 offset = offset % 100;
172 if (offset >= 30 && field.size > 2 * sizeof (double))
173 ptv = pt.z;
174 else if (offset >= 20)
175 ptv = pt.y;
176 else
177 ptv = pt.x;
178 }
179 if (fabs (ptv - d) < 1e-6)
180 {
181 if (g_counter > g_max_count)
182 pass ();
183 else
184 ok ("%s[%d].%s: %f [%s %d]", fieldname, index, key, ptv,
185 field.type, f->code);
186 }
187 else
188 fail ("%s[%d].%s: %f <=> \"%s\" [%s %d]", fieldname, index, key,
189 ptv, f->value, field.type, f->code);
190 }
191 }
192 break;
193 case DWG_VT_REAL:
194 {
195 double value;
196 if (dwg_dynapi_subclass_value (ptr, subclass, key, &value, &field))
197 {
198 double d = strtod (f->value, NULL);
199 if (f->code >= 50 && f->code < 59)
200 d = deg2rad (d);
201 if (fabs (value - d) < 1e-6)
202 {
203 if (g_counter > g_max_count)
204 pass ();
205 else
206 ok ("%s[%d].%s: %f", fieldname, index, key, value);
207 }
208 else
209 fail ("%s[%d].%s: %f <=> \"%s\" [REAL %s]", fieldname, index,
210 key, value, f->value, field.type);
211 }
212 }
213 break;
214 case DWG_VT_BOOL:
215 DWG_VT_BOOL:
216 {
217 BITCODE_B value;
218 if (dwg_dynapi_subclass_value (ptr, subclass, key, &value, &field))
219 {
220 BITCODE_B i = (BITCODE_B)strtol (f->value, NULL, 10);
221 if (i == value)
222 {
223 if (g_counter > g_max_count)
224 pass ();
225 else
226 ok ("%s[%d].%s: %d", fieldname, index, key, value);
227 }
228 else
229 fail ("%s[%d].%s: %d <=> \"%s\" [BOOL %s]", fieldname, index,
230 key, value, f->value, field.type);
231 }
232 }
233 break;
234 case DWG_VT_INT8:
235 DWG_VT_INT8:
236 {
237 BITCODE_RC value;
238 if (dwg_dynapi_subclass_value (ptr, subclass, key, &value, &field))
239 {
240 BITCODE_RC i = (BITCODE_RC)strtol (f->value, NULL, 10);
241 if (i == value)
242 {
243 if (g_counter > g_max_count)
244 pass ();
245 else
246 ok ("%s[%d].%s: %d", fieldname, index, key, value);
247 }
248 else if (field.type)
249 fail ("%s[%d].%s: %d <=> \"%s\" [INT8 %s]", fieldname, index,
250 key, value, f->value, field.type);
251 else
252 {
253 if (g_counter > g_max_count)
254 pass ();
255 else
256 ok ("%s[%d].%s: %d <=> \"%s\" [INT8] (TODO)", fieldname,
257 index, key, value, f->value);
258 }
259 }
260 }
261 break;
262 case DWG_VT_INT16:
263 DWG_VT_INT16:
264 {
265 BITCODE_BS value;
266 if (dwg_dynapi_subclass_value (ptr, subclass, key, &value, &field))
267 {
268 BITCODE_BS i = (BITCODE_BS)strtol (f->value, NULL, 10);
269 if (i == value)
270 {
271 if (g_counter > g_max_count)
272 pass ();
273 else
274 ok ("%s[%d].%s: %d", fieldname, index, key, (int)value);
275 }
276 else if (field.type)
277 fail ("%s[%d].%s: %d <=> \"%s\" [INT16 %s]", fieldname, index,
278 key, (int)value, f->value, field.type);
279 else
280 {
281 if (g_counter > g_max_count)
282 pass ();
283 else
284 ok ("%s[%d].%s: %d <=> \"%s\" [INT16] (TODO)", fieldname,
285 index, key, (int)value, f->value);
286 }
287 }
288 }
289 break;
290 case DWG_VT_INT32:
291 DWG_VT_INT32:
292 {
293 BITCODE_BL value;
294 if (dwg_dynapi_subclass_value (ptr, subclass, key, &value, &field))
295 {
296 long l = strtol (f->value, NULL, 10);
297 BITCODE_BL i = (BITCODE_BL)l;
298 if (strEQc (key, "rgb") && i == (value & 0xffffff))
299 {
300 if (g_counter > g_max_count)
301 pass ();
302 else
303 ok ("%s[%d].%s: 0x%x", fieldname, index, key,
304 (unsigned)value);
305 }
306 else if (i == value)
307 {
308 if (g_counter > g_max_count)
309 pass ();
310 else
311 ok ("%s[%d].%s: %u", fieldname, index, key, (unsigned)value);
312 }
313 else if (field.type)
314 fail ("%s[%d].%s: %u <=> \"%s\" [INT32 %s]", fieldname, index,
315 key, (unsigned)value, f->value, field.type);
316 else
317 {
318 if (g_counter > g_max_count)
319 pass ();
320 else
321 ok ("%s[%d].%s: %u <=> \"%s\" [INT32] (TODO)", fieldname,
322 index, key, (unsigned)value, f->value);
323 }
324 }
325 }
326 break;
327 case DWG_VT_INT64:
328 DWG_VT_INT64:
329 {
330 BITCODE_RLL value;
331 if (dwg_dynapi_subclass_value (ptr, subclass, key, &value, &field))
332 {
333 BITCODE_RLL i = (BITCODE_RLL)strtol (f->value, NULL, 10);
334 if (i == value)
335 {
336 if (g_counter > g_max_count)
337 pass ();
338 else
339 ok ("%s[%d].%s: %ld", fieldname, index, key, (long)value);
340 }
341 else if (field.type)
342 fail ("%s[%d].%s: %ld <=> \"%s\" [INT64]", fieldname, index, key,
343 (long)value, f->value);
344 else
345 {
346 if (g_counter > g_max_count)
347 pass ();
348 else
349 ok ("%s[%d].%s: %ld <=> \"%s\" [INT64] (TODO)", fieldname,
350 index, key, (long)value, f->value);
351 }
352 }
353 }
354 break;
355 case DWG_VT_BINARY:
356 break;
357 case DWG_VT_HANDLE:
358 {
359 BITCODE_H value;
360 if (dwg_dynapi_subclass_value (ptr, subclass, key, &value, &field))
361 {
362 unsigned long l;
363 sscanf (f->value, "%lX", &l);
364 if (l == value->absolute_ref || l == value->handleref.value)
365 {
366 if (g_counter > g_max_count)
367 pass ();
368 else
369 ok ("%s[%d].%s: %s", fieldname, index, key, f->value);
370 }
371 else
372 fail ("%s[%d].%s: %lX <=> \"%s\" [H]", fieldname, index, key, l,
373 f->value);
374 }
375 }
376 break;
377 case DWG_VT_OBJECTID:
378 case DWG_VT_INVALID:
379 default:
380 break;
381 }
382 }
383
384 static int
385 DIMASSOC_index (const Dwg_Object *restrict obj, int sub_i)
386 {
387 // check associativity bitmask for the index
388 Dwg_Object_DIMASSOC *_obj = obj->tio.object->tio.DIMASSOC;
389 while (!(_obj->associativity & (1 << sub_i)) && sub_i < 4)
390 sub_i++;
391 return sub_i;
392 }
393
394 static int
395 test_object (const Dwg_Data *restrict dwg, const Dwg_Object *restrict obj,
396 const struct _unknown_dxf *restrict dxf,
397 const char *restrict name)
398 {
399 int isnew;
400 const struct _unknown_field *f = dxf->fields;
401 int sub_i = 0;
402 char firstkey[80];
403
404 *firstkey = '\0';
405 g_counter++;
406
407 // check all fields against dxf->fields
408 for (; f->value; f++)
409 {
410 Dwg_DYNAPI_field field;
411 const Dwg_DYNAPI_field *fp, *fp1;
412 enum RESBUF_VALUE_TYPE vtype;
413 if (!f->name || !*f->name)
414 continue;
415 // support subclass, as in in_json
416 if (strchr (f->name, '.'))
417 {
418 char *subf = strdup (f->name);
419 char *key = strchr (subf, '.');
420 char *subclass;
421 char *p;
422 char *ptr;
423
424 *key = '\0';
425 key++;
426 if (!*firstkey)
427 {
428 strcpy (firstkey, key);
429 if (strEQc (name, "DIMASSOC"))
430 sub_i = DIMASSOC_index (obj, sub_i);
431 }
432 else if (strEQ (key, firstkey)) // next index, like ref[1]
433 {
434 if (strEQc (name, "DIMASSOC"))
435 {
436 sub_i = DIMASSOC_index (obj, sub_i + 1);
437 if (sub_i > 3)
438 break;
439 }
440 else
441 sub_i++;
442 }
443 // unused
444 if ((p = strchr (subf, '['))) // ref[0].osnap_type
445 *p = '\0';
446 // generalize. lookup type of subclass field
447 if (!(fp1 = dwg_dynapi_entity_field (name, subf)))
448 {
449 free (subf);
450 continue;
451 }
452 subclass = dwg_dynapi_subclass_name (fp1->type);
453 if (!subclass)
454 {
455 free (subf);
456 continue;
457 }
458 fp = dwg_dynapi_subclass_field (subclass, key);
459 if (!fp)
460 {
461 free (subclass);
462 free (subf);
463 continue;
464 }
465 // embedded or reference?
466 if (fp1->is_malloc) // vector
467 {
468 // ptr = ref[i].key
469 int subsize = sub_i ? dwg_dynapi_subclass_size (subclass) : 0;
470 ptr = *(char **)((char *)obj->tio.object->tio.APPID
471 + fp1->offset); // deref
472 ptr += (sub_i * subsize); // index offset
473 }
474 else
475 { // embedded. no deref, and also no index offset. ptr = &ref.key
476 ptr = &((char *)obj->tio.object->tio.APPID)[fp1->offset];
477 }
478 if (ptr)
479 test_subclass (dwg, ptr, f, fp, subclass, subf, key, sub_i);
480 free (subclass);
481 free (subf);
482 continue;
483 }
484 else if (!(fp = dwg_dynapi_entity_field (name, f->name)))
485 continue;
486 if (strEQc (fp->type, "CMC"))
487 {
488 BITCODE_CMC color;
489 if (dwg_dynapi_entity_value (obj->tio.object->tio.APPID, name,
490 f->name, &color, &field))
491 {
492 BITCODE_BS i = (BITCODE_BS)strtol (f->value, NULL, 10);
493 if (i == color.index)
494 {
495 if (g_counter > g_max_count)
496 pass ();
497 else
498 ok ("%s.%s: %s", name, f->name, f->value);
499 }
500 else if (field.type)
501 fail ("%s.%s: %d <=> \"%s\" [%s %d]", name, f->name,
502 (int)color.index, f->value, field.type, field.dxf);
503 else
504 {
505 if (g_counter > g_max_count)
506 pass ();
507 else
508 ok ("%s.%s: %d <=> \"%s\" [CMC] (TODO)", name, f->name,
509 (int)color.index, f->value);
510 }
511 }
512 continue;
513 }
514 // TODO: inlined array support, as with subfields
515 vtype = dwg_resbuf_value_type (f->code);
516 if (vtype == DWG_VT_REAL && fp->size >= 16)
517 goto DWG_VT_POINT3D;
518 if (vtype == DWG_VT_INT8 && fp->size == 1 && strEQc (fp->type, "B"))
519 goto DWG_VT_BOOL;
520 if (vtype == DWG_VT_INT16 && fp->size == 1 && strEQc (fp->type, "RC"))
521 goto DWG_VT_INT8;
522 if (vtype == DWG_VT_INT8 && fp->size == 2)
523 goto DWG_VT_INT16;
524 if (vtype == DWG_VT_INT16 && fp->size == 4)
525 goto DWG_VT_INT32;
526 if (vtype == DWG_VT_INT16 && fp->size == 1)
527 goto DWG_VT_INT8;
528 if (vtype == DWG_VT_INT32 && fp->size == 8)
529 goto DWG_VT_INT64;
530 switch (vtype)
531 {
532 case DWG_VT_STRING:
533 {
534 char *value = NULL;
535 if (fp->is_malloc
536 && dwg_dynapi_entity_utf8text (obj->tio.object->tio.APPID,
537 name, f->name, &value, &isnew,
538 &field))
539 {
540 if (!value || strEQ (value, f->value))
541 {
542 if (g_counter > g_max_count)
543 pass ();
544 else
545 ok ("%s.%s: %s", name, f->name, value);
546 }
547 else
548 fail ("%s.%s: %s [%s %d] STRING", name, f->name, value,
549 field.type, field.dxf);
550 }
551 if (isnew && value)
552 free (value);
553 }
554 break;
555 case DWG_VT_POINT3D:
556 DWG_VT_POINT3D:
557 {
558 BITCODE_3BD pt;
559 if (fp->is_malloc
560 && dwg_dynapi_entity_value (obj->tio.object->tio.APPID, name,
561 f->name, &pt, &field))
562 {
563 double d = strtod (f->value, NULL);
564 double ptv;
565 int offset = f->code;
566 if (strstr (field.type, "_1"))
567 {
568 while (offset > 10) // 10,11,12
569 offset -= 10;
570 if (offset == 2 && field.size > 2 * sizeof (double))
571 ptv = pt.z;
572 else if (offset == 1)
573 ptv = pt.y;
574 else
575 ptv = pt.x;
576 }
577 else // 10/20/30
578 {
579 offset = offset % 100;
580 if (offset >= 30 && field.size > 2 * sizeof (double))
581 ptv = pt.z;
582 else if (offset >= 20)
583 ptv = pt.y;
584 else
585 ptv = pt.x;
586 }
587 if (fabs (ptv - d) < 1e-6)
588 {
589 if (g_counter > g_max_count)
590 pass ();
591 else
592 ok ("%s.%s: %f [%s %d]", name, f->name, ptv, field.type,
593 f->code);
594 }
595 else
596 fail ("%s.%s: %f <=> \"%s\" [%s %d]", name, f->name, ptv,
597 f->value, field.type, f->code);
598 }
599 }
600 break;
601 case DWG_VT_REAL:
602 {
603 double value;
604 if (fp->is_malloc
605 && dwg_dynapi_entity_value (obj->tio.object->tio.APPID, name,
606 f->name, &value, &field))
607 {
608 double d = strtod (f->value, NULL);
609 if (f->code >= 50 && f->code < 59)
610 d = deg2rad (d);
611 if (fabs (value - d) < 1e-6)
612 {
613 if (g_counter > g_max_count)
614 pass ();
615 else
616 ok ("%s.%s: %f", name, f->name, value);
617 }
618 else
619 fail ("%s.%s: %f <=> \"%s\" [%s %d] REAL", name, f->name,
620 value, f->value, field.type, field.dxf);
621 }
622 }
623 break;
624 case DWG_VT_BOOL:
625 DWG_VT_BOOL:
626 {
627 BITCODE_B value;
628 if (fp->is_malloc
629 && dwg_dynapi_entity_value (obj->tio.object->tio.APPID, name,
630 f->name, &value, &field))
631 {
632 BITCODE_B i = (BITCODE_B)strtol (f->value, NULL, 10);
633 if (i == value)
634 {
635 if (g_counter > g_max_count)
636 pass ();
637 else
638 ok ("%s.%s: %d", name, f->name, value);
639 }
640 else
641 fail ("%s.%s: %d <=> \"%s\" [%s %d] BOOL", name, f->name,
642 value, f->value, field.type, field.dxf);
643 }
644 }
645 break;
646 case DWG_VT_INT8:
647 DWG_VT_INT8:
648 {
649 BITCODE_RC value;
650 if (fp->is_malloc
651 && dwg_dynapi_entity_value (obj->tio.object->tio.APPID, name,
652 f->name, &value, &field))
653 {
654 BITCODE_RC i = (BITCODE_RC)strtol (f->value, NULL, 10);
655 if (i == value)
656 {
657 if (g_counter > g_max_count)
658 pass ();
659 else
660 ok ("%s.%s: %d", name, f->name, value);
661 }
662 else if (field.type)
663 fail ("%s.%s: %d <=> \"%s\" [%s %d] INT8", name, f->name,
664 value, f->value, field.type, field.dxf);
665 else
666 {
667 if (g_counter > g_max_count)
668 pass ();
669 else
670 ok ("%s.%s: %d <=> \"%s\" INT8 (TODO)", name, f->name,
671 value, f->value);
672 }
673 }
674 }
675 break;
676 case DWG_VT_INT16:
677 DWG_VT_INT16:
678 {
679 BITCODE_BS value;
680 if (fp->is_malloc
681 && dwg_dynapi_entity_value (obj->tio.object->tio.APPID, name,
682 f->name, &value, &field))
683 {
684 BITCODE_BS i = (BITCODE_BS)strtol (f->value, NULL, 10);
685 if (i == value)
686 {
687 if (g_counter > g_max_count)
688 pass ();
689 else
690 ok ("%s.%s: %d", name, f->name, (int)value);
691 }
692 else if (field.type)
693 fail ("%s.%s: %d <=> \"%s\" [%s %d] INT16", name, f->name,
694 (int)value, f->value, field.type, field.dxf);
695 else
696 {
697 if (g_counter > g_max_count)
698 pass ();
699 else
700 ok ("%s.%s: %d <=> \"%s\" INT16 (TODO)", name, f->name,
701 (int)value, f->value);
702 }
703 }
704 }
705 break;
706 case DWG_VT_INT32:
707 DWG_VT_INT32:
708 {
709 BITCODE_BL value;
710 if (fp->is_malloc
711 && dwg_dynapi_entity_value (obj->tio.object->tio.APPID, name,
712 f->name, &value, &field))
713 {
714 long l = strtol (f->value, NULL, 10);
715 BITCODE_BL i = (BITCODE_BL)l;
716 if (strEQc (f->name, "rgb") && i == (value & 0xffffff))
717 {
718 if (g_counter > g_max_count)
719 pass ();
720 else
721 ok ("%s.%s: 0x%x", name, f->name, (unsigned)value);
722 }
723 else if (i == value)
724 {
725 if (g_counter > g_max_count)
726 pass ();
727 else
728 ok ("%s.%s: %u", name, f->name, (unsigned)value);
729 }
730 else if (field.type)
731 fail ("%s.%s: %u <=> \"%s\" [%s %d] INT32", name, f->name,
732 (unsigned)value, f->value, field.type, field.dxf);
733 else
734 {
735 if (g_counter > g_max_count)
736 pass ();
737 else
738 ok ("%s.%s: %u <=> \"%s\" INT32 (TODO)", name, f->name,
739 (unsigned)value, f->value);
740 }
741 }
742 }
743 break;
744 case DWG_VT_INT64:
745 DWG_VT_INT64:
746 {
747 BITCODE_RLL value;
748 if (fp->is_malloc
749 && dwg_dynapi_entity_value (obj->tio.object->tio.APPID, name,
750 f->name, &value, &field))
751 {
752 BITCODE_RLL i = (BITCODE_RLL)strtol (f->value, NULL, 10);
753 if (i == value)
754 {
755 if (g_counter > g_max_count)
756 pass ();
757 else
758 ok ("%s.%s: %ld", name, f->name, (long)value);
759 }
760 else if (field.type)
761 fail ("%s.%s: %ld <=> \"%s\" [%s %d] INT64", name, f->name,
762 (long)value, f->value, field.type, field.dxf);
763 else
764 {
765 if (g_counter > g_max_count)
766 pass ();
767 else
768 ok ("%s.%s: %ld <=> \"%s\" INT64 (TODO)", name, f->name,
769 (long)value, f->value);
770 }
771 }
772 }
773 break;
774 case DWG_VT_BINARY:
775 break;
776 case DWG_VT_HANDLE:
777 {
778 BITCODE_H value;
779 if (fp->is_malloc
780 && dwg_dynapi_entity_value (obj->tio.object->tio.APPID, name,
781 f->name, &value, &field))
782 {
783 unsigned long l;
784 sscanf (f->value, "%lX", &l);
785 if (l == value->absolute_ref || l == value->handleref.value)
786 {
787 if (g_counter > g_max_count)
788 pass ();
789 else
790 ok ("%s.%s: %s", name, f->name, f->value);
791 }
792 else
793 fail ("%s.%s: %lX <=> \"%s\" [H %d]", name, f->name, l,
794 f->value, field.dxf);
795 }
796 }
797 break;
798 case DWG_VT_OBJECTID:
799 case DWG_VT_INVALID:
800 default:
801 break;
802 }
803 }
804 return failed;
805 }
806
807 static int
808 test_dxf (const struct _unknown_dxf *dxf, const char *restrict name,
809 const char *restrict dwgfile)
810 {
811 int error = 0;
812 static char prev_dwgfile[128];
813 static Dwg_Data dwg;
814 BITCODE_BL i;
815 char *trace;
816 int tracelevel = 0;
817
818 trace = getenv ("LIBREDWG_TRACE");
819 if (trace)
820 tracelevel = atoi (trace);
821
822 loglevel = is_make_silent () ? 0 : MAX (tracelevel, 2);
823 LOG_TRACE ("%s %X %s\n", dxf->name, dxf->handle, dwgfile);
824 num = passed = failed = 0;
825
826 if (dwg.num_objects && strEQ (dwgfile, prev_dwgfile))
827 ;
828 else
829 {
830 if (dwg.num_objects && dwg.header.version > R_INVALID)
831 dwg_free (&dwg);
832 dwg.opts = tracelevel;
833 if (dwg_read_file (dwgfile, &dwg) >= DWG_ERR_CRITICAL)
834 {
835 dwg_free (&dwg);
836 return 1;
837 }
838 }
839 strcpy (prev_dwgfile, dwgfile);
840
841 // find the object
842 for (i = 0; i < dwg.num_objects; i++)
843 {
844 if (dwg.object[i].handle.value == dxf->handle)
845 {
846 if (dwg.object[i].fixedtype >= DWG_TYPE_UNKNOWN_ENT)
847 break;
848 if (strNE (dwg.object[i].dxfname, dxf->name))
849 LOG_WARN ("Invalid handle 0x%X for %s", dxf->handle, dxf->name)
850 else
851 error += test_object (&dwg, &dwg.object[i], dxf, name);
852 break;
853 }
854 }
855 /* This value is the return value for `main',
856 so clamp it to either 0 or 1. */
857 return error ? 1 : 0;
858 }
859
860 int
861 main (int argc, char *argv[])
862 {
863 int i = 1, error = 0;
864 struct _unknown_dxf *dxf;
865 char *class = NULL;
866 char *file = NULL;
867 char name[80];
868 char olddxf[80];
869 int big = 0;
870 int is_docker = 0;
871 char *docker;
872 // clang-format off
873 #include "../../examples/alldxf_2.inc"
874 // clang-format on
875
876 docker = getenv ("DOCKER");
877 if (docker && strNE (docker, "0"))
878 is_docker = 1;
879 g_max_count = MAX_COUNTER;
880 g_all = 0;
881 name[0] = '\0';
882 olddxf[0] = '\0';
883 if (argc > 2 && !strcmp (argv[i], "--class"))
884 {
885 class = argv[++i];
886 ++i;
887 }
888 if (argc - i >= 2 && !strcmp (argv[i], "--file"))
889 {
890 file = argv[++i];
891 ++i;
892 }
893 if (argc - i >= 1 && !strcmp (argv[i], "-a"))
894 {
895 ++i;
896 g_all = 1;
897 g_max_count = 1000;
898 }
899 if (argc - i >= 1 && !strcmp (argv[i], "--big"))
900 {
901 ++i;
902 big = 1;
903 }
904
905 g_counter = 0;
906 for (dxf = &unknown_dxf[0]; dxf->name; dxf++)
907 {
908 const char *dxffile = dxf->dxf;
909 struct stat attrib;
910 size_t len = strlen (dxffile);
911 char *dwgfile = strdup (dxffile);
912 char *s = strrchr (dwgfile, '.');
913 *(s + 2) = 'w';
914 *(s + 3) = 'g';
915
916 // display ok values only for the first 6 object types per file
917 if (strNE (name, dxf->name) && strNE (olddxf, dxf->dxf))
918 g_counter = 0;
919 if (!big && strstr (dxffile, "/test-big/"))
920 {
921 free (dwgfile);
922 continue;
923 }
924
925 strcpy (olddxf, dxf->dxf);
926 strcpy (name, dxf->name);
927 if (!is_dwg_object (name) && !is_dwg_entity (name))
928 {
929 object_alias (name);
930 if (!is_dwg_object (name))
931 {
932 strcpy (name, dxf->name);
933 entity_alias (name);
934 if (!is_dwg_entity (name) && !class)
935 {
936 free (dwgfile);
937 if (!g_counter) // use --enable-debug
938 LOG_WARN ("Unhandled %s", dxf->name)
939 continue;
940 }
941 }
942 }
943 if (class && strNE (class, name))
944 {
945 free (dwgfile);
946 continue;
947 }
948 if (file && strNE (file, dwgfile))
949 {
950 free (dwgfile);
951 continue;
952 }
953 // GH #268. skip 2018/Helix.dwg. podman works fine.
954 if (is_docker && strEQ (dxffile, "test/test-data/2018/Helix.dxf"))
955 {
956 LOG_ERROR ("Skip %s in docker", dwgfile)
957 free (dwgfile);
958 continue;
959 }
960 if (stat (dwgfile, &attrib)) // not found
961 {
962 char path[80];
963 char *top_srcdir = getenv ("top_srcdir");
964 // fixup wrong alldxf_0.inc paths
965 if (len > 3 && dwgfile[0] == '.' && dwgfile[1] == '.'
966 && dwgfile[2] == '/')
967 memmove (dwgfile, &dwgfile[3], len - 2); // include the final \0
968 if (top_srcdir)
969 {
970 strcpy (path, top_srcdir);
971 strcat (path, "/");
972 }
973 else
974 strcpy (path, "../../../");
975 strcat (path, dwgfile);
976 if (stat (path, &attrib))
977 LOG_WARN ("%s not found\n", path)
978 else
979 error += test_dxf (dxf, name, path);
980 }
981 else
982 error += test_dxf (dxf, name, dwgfile);
983 free (dwgfile);
984 }
985 // so far all unknown objects are debugging or unstable. ignore all errors
986 return 0;
987 }