1 /*****************************************************************************/
2 /*  LibreDWG - free implementation of the DWG file format                    */
3 /*                                                                           */
4 /*  Copyright (C) 2018-2020 Free Software Foundation, Inc.                   */
5 /*                                                                           */
6 /*  This library is free software, licensed under the terms of the GNU       */
7 /*  General Public License as published by the Free Software Foundation,     */
8 /*  either version 3 of the License, or (at your option) any later version.  */
9 /*  You should have received a copy of the GNU General Public License        */
10 /*  along with this program.  If not, see <http://www.gnu.org/licenses/>.    */
11 /*****************************************************************************/
12 
13 /*
14  * dwggrep.c: search a string in all text values in a DWG
15  * TODO scan the dwg.spec for all text DXF codes, per object.
16  *
17  * written by Reini Urban
18  */
19 
20 #include "../src/config.h"
21 #include <stdio.h>
22 #include <stdlib.h>
23 #ifdef HAVE_STRCASESTR
24 #  undef __DARWIN_C_LEVEL
25 #  define __DARWIN_C_LEVEL __DARWIN_C_FULL
26 #  ifndef __USE_GNU
27 #    define __USE_GNU
28 #  endif
29 #  ifndef __BSD_VISIBLE
30 #    define __BSD_VISIBLE 1
31 #  endif
32 #  include <string.h>
33 #else
34 #  include <string.h>
35 #  include <ctype.h>
36 #endif
37 #include <getopt.h>
38 #ifdef HAVE_PCRE2_H
39 // use both, 8 and 16 (r2007+)
40 #  define PCRE2_CODE_UNIT_WIDTH 0
41 #  include <pcre2.h>
42 #endif
43 
44 static const int verbose = 0;
45 
46 #include "dwg.h"
47 #include "logging.h"
48 #include "common.h"
49 #include "bits.h"
50 #include "dwg_api.h"
51 
52 #ifndef HAVE_PCRE2_H
53 #  define PCRE2_MULTILINE 1
54 #  define PCRE2_CASELESS 2
55 #  define PCRE2_EXTENDED 3
56 #  define PCRE2_NO_AUTO_CAPTURE 4
57 #  define PCRE2_NO_DOTSTAR_ANCHOR 5
58 #else
59 #  define PCRE2_JIT_MATCH_OPTIONS                                             \
60     (PCRE2_NO_UTF_CHECK | PCRE2_NOTBOL | PCRE2_NOTEOL | PCRE2_NOTEMPTY        \
61      | PCRE2_NOTEMPTY_ATSTART)
62 #  define PCRE2_JIT_COMPILE_OPTIONS (PCRE2_JIT_COMPLETE)
63 #endif
64 
65 char *pattern;
66 char buf[4096];
67 // partial to find substrings, not only complete matches
68 int options
69     = PCRE2_MULTILINE | PCRE2_NO_AUTO_CAPTURE | PCRE2_NO_DOTSTAR_ANCHOR;
70 int opt_count = 0;
71 int opt_text = 0;
72 int opt_blocks = 0;
73 int opt_tables = 0;
74 int opt_filename = 1;
75 short numdxf = 0;
76 short numtype = 0;
77 static short dxf[10];  // ensure zero-fill
78 static char *type[10]; // ensure zero-fill
79 
80 /* the current version per spec block */
81 static unsigned int cur_ver = 0;
82 
83 #ifdef HAVE_PCRE2_H
84 #  undef USE_MATCH_CONTEXT
85 /* pcre2_compile */
86 static pcre2_code_8 *ri8;
87 static pcre2_match_data_8 *match_data8;
88 static pcre2_match_context_8 *match_context8 = NULL;
89 #  ifdef HAVE_PCRE2_16
90 static pcre2_code_16 *ri16;
91 static pcre2_match_data_16 *match_data16;
92 static pcre2_match_context_16 *match_context16 = NULL;
93 #  endif
94 
95 #  ifdef USE_MATCH_CONTEXT
96 static pcre2_jit_stack_8 *jit_stack8 = NULL;
97 static pcre2_compile_context_8 *compile_context8 = NULL;
98 #    ifdef HAVE_PCRE2_16
99 static pcre2_jit_stack_16 *jit_stack16 = NULL;
100 static pcre2_compile_context_16 *compile_context16 = NULL;
101 #    endif
102 #  endif
103 #endif
104 
105 static int
usage(void)106 usage (void)
107 {
108   printf ("\nUsage: dwggrep [-cRr] pattern *.dwg\n");
109   return 1;
110 }
111 static int
opt_version(void)112 opt_version (void)
113 {
114   printf ("dwggrep %s\n", PACKAGE_VERSION);
115   return 0;
116 }
117 static int
help(void)118 help (void)
119 {
120   printf ("\nUsage: dwggrep [OPTIONS]... pattern files\n");
121 #ifdef HAVE_PCRE2_H
122   printf ("Search regex pattern in a list of DWGs.\n\n");
123 #else
124   printf ("Search string (no regex) in a list of DWGs.\n\n");
125 #endif
126   printf ("  -i                        Case-insensitive pattern\n");
127 #ifdef HAVE_PCRE2_H
128   printf ("  -x                        Extended regex pattern\n");
129 #endif
130   printf ("  -c, --count               Print only the count of matched "
131           "elements.\n");
132   printf ("  -h, --no-filename         Print no filename.\n");
133 #if 0
134   printf("  -R, -r, --recursive       Recursively search subdirectories listed.\n");
135 #endif
136   printf (
137       "  -y, --type NAME           Search only NAME entities or objects.\n");
138   printf ("  -d, --dxf NUM             Search only DXF group NUM fields.\n");
139   printf ("  -t, --text                Search only in TEXT-like entities.\n");
140   printf ("  -b, --blocks              Search also in all block definitions.\n");
141   printf("       --tables              Search only in table names.\n");
142 #ifdef HAVE_GETOPT_LONG
143   printf ("      --help                Display this help and exit\n");
144   printf ("      --version             Output version information and exit\n"
145           "\n");
146 #else
147   printf ("  -u                        Display this help and exit\n");
148   printf ("  -v                        Output version information and exit\n"
149           "\n");
150 #endif
151   printf ("GNU LibreDWG online manual: "
152           "<https://www.gnu.org/software/libredwg/>\n");
153   return 0;
154 }
155 
156 static void
print_match(const int is16,const char * restrict filename,const char * restrict entity,const int dxfgroup,char * restrict text)157 print_match (const int is16, const char *restrict filename,
158              const char *restrict entity, const int dxfgroup,
159              char *restrict text)
160 {
161   if (is16)
162     text = bit_convert_TU ((BITCODE_TU)text);
163   printf ("%s %s %d: %s\n", opt_filename ? filename : "", entity, dxfgroup,
164           text);
165   if (is16)
166     free (text);
167 }
168 
169 static int
do_match(const int is16,const char * restrict filename,const char * restrict entity,const int dxfgroup,char * restrict text)170 do_match (const int is16, const char *restrict filename,
171           const char *restrict entity, const int dxfgroup, char *restrict text)
172 {
173 #ifdef HAVE_PCRE2_H
174   int rc;
175 #  ifdef HAVE_PCRE2_16
176   if (is16)
177     rc = pcre2_match_16 (ri16, (PCRE2_SPTR16)text, PCRE2_ZERO_TERMINATED, 0,
178                          PCRE2_JIT_MATCH_OPTIONS,
179                          match_data16,     /* block for storing the result */
180                          match_context16); /* disabled */
181   else
182 #  endif
183     // already converted to UTF-8 before
184     rc = pcre2_match_8 (ri8, (PCRE2_SPTR8)text, PCRE2_ZERO_TERMINATED, 0,
185                         PCRE2_JIT_MATCH_OPTIONS,
186                         match_data8,     /* block for storing the result */
187                         match_context8); /* disabled */
188   if (rc >= 0)
189     {
190       if (!opt_count)
191         print_match (is16, filename, entity, dxfgroup, text);
192       return 1;
193     }
194   else if (rc < -2)
195     { // not PCRE2_ERROR_NOMATCH nor PCRE2_ERROR_PARTIAL
196       pcre2_get_error_message_8 (rc, (PCRE2_UCHAR8 *)buf, 4096);
197       LOG_WARN ("pcre2 match error %s with %s", buf, pattern);
198     }
199   return 0;
200 
201 #else
202 
203   if (options & PCRE2_CASELESS)
204     {
205 #  ifndef HAVE_STRCASESTR
206       int i, len, dmax;
207       char *dest = text;
208       int dlen = dmax = strlen (text);
209       char *src = pattern;
210       int slen = strlen (pattern);
211 
212       while (*dest && dmax)
213         {
214           i = 0;
215           len = slen;
216           dlen = dmax;
217           while (dest[i] && dlen)
218             {
219               if (toupper ((unsigned char)dest[i])
220                   != toupper ((unsigned char)src[i]))
221                 {
222                   break;
223                 }
224               /* move to the next char */
225               i++;
226               len--;
227               dlen--;
228 
229               if (src[i] == '\0' || !len)
230                 {
231                   if (!opt_count)
232                     print_match (is16, filename, entity, dxfgroup, text);
233                   return 1;
234                 }
235             }
236           dest++;
237           dmax--;
238         }
239 #  else
240       if (strcasestr (text, pattern))
241         {
242           if (!opt_count)
243             print_match (is16, filename, entity, dxfgroup, text);
244           return 1;
245         }
246 #  endif
247     }
248   else
249     {
250       if (strstr (text, pattern))
251         {
252           if (!opt_count)
253             print_match (is16, filename, entity, dxfgroup, text);
254           return 1;
255         }
256     }
257   return 0;
258 #endif
259 }
260 
261 // check matching dxfgroup first to avoid costly utf8 conversions
262 #define MATCH_DXF(type, ENTITY, text_field, dxfgroup)                         \
263   if (numdxf)                                                                 \
264     {                                                                         \
265       int dxfok = 0;                                                          \
266       for (int _i = 0; _i < numdxf; _i++)                                     \
267         {                                                                     \
268           if (dxf[_i] == dxfgroup)                                            \
269             {                                                                 \
270               dxfok = 1;                                                      \
271               break;                                                          \
272             }                                                                 \
273         }                                                                     \
274       if (dxfok)                                                              \
275         {                                                                     \
276           MATCH_TYPE (type, ENTITY, text_field, dxfgroup);                    \
277         }                                                                     \
278     }                                                                         \
279   else                                                                        \
280     {                                                                         \
281       MATCH_TYPE (type, ENTITY, text_field, dxfgroup);                        \
282     }
283 
284 // 8bit only
285 #define MATCH_NO16(type, ENTITY, text_field, dxfgroup)                        \
286   text = (char *)obj->tio.type->tio.ENTITY->text_field;                       \
287   if (text && numdxf)                                                         \
288     {                                                                         \
289       int dxfok = 0;                                                          \
290       for (int i = 0; i < numdxf; i++)                                        \
291         {                                                                     \
292           if (dxf[i] == dxfgroup)                                             \
293             {                                                                 \
294               dxfok = 1;                                                      \
295               break;                                                          \
296             }                                                                 \
297         }                                                                     \
298       if (dxfok)                                                              \
299         {                                                                     \
300           found += do_match (0, filename, #ENTITY, dxfgroup, text);           \
301         }                                                                     \
302     }                                                                         \
303   else if (text)                                                              \
304     {                                                                         \
305       found += do_match (0, filename, #ENTITY, dxfgroup, text);               \
306     }
307 
308 #ifdef HAVE_PCRE2_16
309 #  define MATCH_TYPE(type, ENTITY, text_field, dxfgroup)                      \
310     text = (char *)obj->tio.type->tio.ENTITY->text_field;                     \
311     if (text)                                                                 \
312     found += do_match (obj->parent->header.version >= R_2007, filename,       \
313                        #ENTITY, dxfgroup, text)
314 #else
315 #  define MATCH_TYPE(type, ENTITY, text_field, dxfgroup)                      \
316     text = (char *)obj->tio.type->tio.ENTITY->text_field;                     \
317     if (text)                                                                 \
318       {                                                                       \
319         if (obj->parent->header.version >= R_2007)                            \
320           text = bit_convert_TU ((BITCODE_TU)text);                           \
321         found += do_match (obj->parent->header.version >= R_2007, filename,   \
322                            #ENTITY, dxfgroup, text);                          \
323         if (obj->parent->header.version >= R_2007)                            \
324           free (text);                                                        \
325       }
326 #endif
327 
328 #define MATCH_ENTITY(ENTITY, text_field, dxf)                                 \
329   MATCH_DXF (entity, ENTITY, text_field, dxf)
330 #define MATCH_OBJECT(ENTITY, text_field, dxf)                                 \
331   MATCH_DXF (object, ENTITY, text_field, dxf)
332 #define MATCH_TABLE(ENTITY, handle, TABLE, dxf)                               \
333   {                                                                           \
334   }
335 
336 static int
match_TEXT(const char * restrict filename,const Dwg_Object * restrict obj)337 match_TEXT (const char *restrict filename, const Dwg_Object *restrict obj)
338 {
339   char *text;
340   int found = 0;
341   MATCH_ENTITY (TEXT, text_value, 1);
342   if (!opt_text)
343     {
344       MATCH_TABLE (TEXT, style, STYLE, 7);
345     }
346   return found;
347 }
348 
349 static int
match_ARCALIGNEDTEXT(const char * restrict filename,const Dwg_Object * restrict obj)350 match_ARCALIGNEDTEXT (const char *restrict filename, const Dwg_Object *restrict obj)
351 {
352   char *text;
353   int found = 0;
354   MATCH_ENTITY (ARCALIGNEDTEXT, text_value, 1);
355   if (!opt_text)
356     {
357       // ignore the various sizes stored as text
358       MATCH_ENTITY (ARCALIGNEDTEXT, style, 7);
359     }
360   return found;
361 }
362 
363 static int
match_ATTRIB(const char * restrict filename,const Dwg_Object * restrict obj)364 match_ATTRIB (const char *restrict filename, const Dwg_Object *restrict obj)
365 {
366   char *text;
367   int found = 0;
368   // printf("--ATTRIB %lX %s\n", obj->handle.value, filename);
369   MATCH_ENTITY (ATTRIB, text_value, 1);
370   MATCH_ENTITY (ATTRIB, tag, 2);
371   if (!opt_text)
372     {
373       MATCH_TABLE (ATTRIB, style, STYLE, 7);
374     }
375   return found;
376 }
377 
378 static int
match_ATTDEF(const char * restrict filename,const Dwg_Object * restrict obj)379 match_ATTDEF (const char *restrict filename, const Dwg_Object *restrict obj)
380 {
381   char *text;
382   int found = 0;
383   MATCH_ENTITY (ATTDEF, default_value, 1);
384   MATCH_ENTITY (ATTDEF, tag, 2);
385   MATCH_ENTITY (ATTDEF, prompt, 3);
386   return found;
387 }
388 
389 static int
match_MTEXT(const char * restrict filename,const Dwg_Object * restrict obj)390 match_MTEXT (const char *restrict filename, const Dwg_Object *restrict obj)
391 {
392   char *text;
393   int found = 0;
394   MATCH_ENTITY (MTEXT, text, 1);
395   return found;
396 }
397 
398 static int
match_BLOCK(const char * restrict filename,const Dwg_Object * restrict obj)399 match_BLOCK (const char *restrict filename, const Dwg_Object *restrict obj)
400 {
401   char *text;
402   int found = 0;
403   MATCH_ENTITY (BLOCK, name, 2);
404   return found;
405 }
406 
407 static int
match_DIMENSION(const char * restrict filename,const Dwg_Object * restrict obj)408 match_DIMENSION (const char *restrict filename, const Dwg_Object *restrict obj)
409 {
410   char *text;
411   int found = 0;
412   // int is16 = obj->parent->header.version >= R_2007;
413 
414   text = obj->tio.entity->tio.DIMENSION_ORDINATE->user_text;
415   if (text)
416     found += do_match (0, filename, "DIMENSION", 1, text);
417   return found;
418 }
419 
420 static int
match_VIEWPORT(const char * restrict filename,const Dwg_Object * restrict obj)421 match_VIEWPORT (const char *restrict filename, const Dwg_Object *restrict obj)
422 {
423   char *text;
424   int found = 0;
425   MATCH_ENTITY (VIEWPORT, style_sheet, 1);
426   return found;
427 }
428 static int
match_LEADER(const char * restrict filename,const Dwg_Object * restrict obj)429 match_LEADER (const char *restrict filename, const Dwg_Object *restrict obj)
430 {
431   char *text;
432   int found = 0;
433   //MATCH_ENTITY (LEADER, text, 1);
434   return found;
435 }
436 static int
match_MULTILEADER(const char * restrict filename,const Dwg_Object * restrict obj)437 match_MULTILEADER (const char *restrict filename, const Dwg_Object *restrict obj)
438 {
439   char *text;
440   int found = 0;
441   const Dwg_Entity_MULTILEADER *_obj = obj->tio.entity->tio.MULTILEADER;
442   if (_obj->ctx.has_content_txt)
443     {
444       MATCH_ENTITY (MULTILEADER, ctx.content.txt.default_text, 304);
445     }
446   // SUB_FIELD_T (blocklabels[rcount1],label_text, 302);
447   return found;
448 }
449 
450 static int
match_3DSOLID(const char * restrict filename,const Dwg_Object * restrict obj)451 match_3DSOLID (const char *restrict filename, const Dwg_Object *restrict obj)
452 {
453   char *text = NULL;
454   int found = 0;
455   BITCODE_BL j;
456   Dwg_Entity_3DSOLID *_obj;
457 
458   if (!obj || !obj->tio.entity)
459     return 0;
460   _obj = obj->tio.entity->tio._3DSOLID;
461   if (!_obj)
462     return 0;
463   if (_obj->acis_data)
464     {
465       MATCH_NO16 (entity, _3DSOLID, acis_data, 1);
466       // MATCH_ENTITY (_3DSOLID, acis_data, 1);
467       // found += do_match(0, filename, "3DSOLID", 1, (char*)_obj->acis_data);
468     }
469   /*
470   if (!_obj->encr_sat_data) return 0;
471   for (j=0; j<_obj->num_blocks; j++)
472     {
473       //text = _obj->encr_sat_data[j];
474       //if (text)
475       //  found += do_match(0, filename, "3DSOLID", 301, text);
476       MATCH_NO16 (entity, _3DSOLID, encr_sat_data[j], 301);
477     }
478   */
479   return found;
480 }
481 
482 static int
match_DICTIONARY(const char * restrict filename,const Dwg_Object * restrict obj)483 match_DICTIONARY (const char *restrict filename,
484                   const Dwg_Object *restrict obj)
485 {
486   char *text;
487   int found = 0;
488   BITCODE_BL i;
489   Dwg_Object_DICTIONARY *_obj = obj->tio.object->tio.DICTIONARY;
490 
491   for (i = 0; i < _obj->numitems; i++)
492     {
493       MATCH_OBJECT (DICTIONARY, texts[i], 3);
494     }
495   return found;
496 }
497 
498 static int
match_STYLE(const char * restrict filename,const Dwg_Object * restrict obj)499 match_STYLE (const char *restrict filename, const Dwg_Object *restrict obj)
500 {
501   char *text;
502   int found = 0;
503   MATCH_OBJECT (STYLE, name, 2);
504   if (!opt_tables)
505     {
506       MATCH_OBJECT (STYLE, font_file, 3);
507       MATCH_OBJECT (STYLE, bigfont_file, 4);
508     }
509   return found;
510 }
511 
512 static int
match_LTYPE(const char * restrict filename,const Dwg_Object * restrict obj)513 match_LTYPE (const char *restrict filename, const Dwg_Object *restrict obj)
514 {
515   char *text;
516   int found = 0;
517   MATCH_OBJECT (LTYPE, name, 2);
518   MATCH_OBJECT (LTYPE, description, 3);
519   if (!opt_tables)
520     {
521       MATCH_OBJECT (LTYPE, strings_area, 3);
522     }
523   return found;
524 }
525 static int
match_LAYER(const char * restrict filename,const Dwg_Object * restrict obj)526 match_LAYER (const char *restrict filename, const Dwg_Object *restrict obj)
527 {
528   char *text;
529   int found = 0;
530   MATCH_OBJECT (LAYER, name, 2);
531   return found;
532 }
533 static int
match_VIEW(const char * restrict filename,const Dwg_Object * restrict obj)534 match_VIEW (const char *restrict filename, const Dwg_Object *restrict obj)
535 {
536   char *text;
537   int found = 0;
538   MATCH_OBJECT (VIEW, name, 2);
539   return found;
540 }
541 static int
match_VPORT(const char * restrict filename,const Dwg_Object * restrict obj)542 match_VPORT (const char *restrict filename, const Dwg_Object *restrict obj)
543 {
544   char *text;
545   int found = 0;
546   MATCH_OBJECT (VPORT, name, 2);
547   return found;
548 }
549 static int
match_UCS(const char * restrict filename,const Dwg_Object * restrict obj)550 match_UCS (const char *restrict filename, const Dwg_Object *restrict obj)
551 {
552   char *text;
553   int found = 0;
554   MATCH_OBJECT (UCS, name, 2);
555   return found;
556 }
557 static int
match_VX_TABLE_RECORD(const char * restrict filename,const Dwg_Object * restrict obj)558 match_VX_TABLE_RECORD (const char *restrict filename, const Dwg_Object *restrict obj)
559 {
560   char *text;
561   int found = 0;
562   MATCH_OBJECT (VX_TABLE_RECORD, name, 2);
563   return found;
564 }
565 
566 static int
match_DIMSTYLE(const char * restrict filename,const Dwg_Object * restrict obj)567 match_DIMSTYLE (const char *restrict filename, const Dwg_Object *restrict obj)
568 {
569   char *text;
570   int found = 0;
571   MATCH_OBJECT (DIMSTYLE, name, 2);
572   if (!opt_tables)
573     {
574       MATCH_OBJECT (DIMSTYLE, DIMPOST, 3);
575       MATCH_OBJECT (DIMSTYLE, DIMAPOST, 4);
576       MATCH_OBJECT (DIMSTYLE, DIMBLK_T, 5);
577       MATCH_OBJECT (DIMSTYLE, DIMBLK1_T, 6);
578       MATCH_OBJECT (DIMSTYLE, DIMBLK2_T, 7);
579       MATCH_OBJECT (DIMSTYLE, DIMMZS, 0);
580       MATCH_OBJECT (DIMSTYLE, DIMALTMZS, 0);
581     }
582   return found;
583 }
584 
585 static int
match_GROUP(const char * restrict filename,const Dwg_Object * restrict obj)586 match_GROUP (const char *restrict filename, const Dwg_Object *restrict obj)
587 {
588   char *text;
589   int found = 0;
590   MATCH_OBJECT (GROUP, name, 3);
591   return found;
592 }
593 
594 static int
match_MLINESTYLE(const char * restrict filename,const Dwg_Object * restrict obj)595 match_MLINESTYLE (const char *restrict filename,
596                   const Dwg_Object *restrict obj)
597 {
598   char *text;
599   int found = 0;
600   MATCH_OBJECT (MLINESTYLE, name, 2);
601   MATCH_OBJECT (MLINESTYLE, description, 3);
602   return found;
603 }
604 
605 static int
match_DICTIONARYVAR(const char * restrict filename,const Dwg_Object * restrict obj)606 match_DICTIONARYVAR (const char *restrict filename,
607                      const Dwg_Object *restrict obj)
608 {
609   char *text;
610   int found = 0;
611   MATCH_OBJECT (DICTIONARYVAR, strvalue, 1);
612   return found;
613 }
614 
615 static int
match_HATCH(const char * restrict filename,const Dwg_Object * restrict obj)616 match_HATCH (const char *restrict filename, const Dwg_Object *restrict obj)
617 {
618   char *text;
619   int found = 0;
620   MATCH_ENTITY (HATCH, name, 2);
621   MATCH_ENTITY (HATCH, gradient_name, 470);
622   return found;
623 }
624 static int
match_TOLERANCE(const char * restrict filename,const Dwg_Object * restrict obj)625 match_TOLERANCE (const char *restrict filename, const Dwg_Object *restrict obj)
626 {
627   char *text;
628   int found = 0;
629   MATCH_ENTITY (TOLERANCE, text_value, 1);
630   return found;
631 }
632 
633 static int
match_IMAGEDEF(const char * restrict filename,const Dwg_Object * restrict obj)634 match_IMAGEDEF (const char *restrict filename, const Dwg_Object *restrict obj)
635 {
636   char *text;
637   int found = 0;
638   MATCH_OBJECT (IMAGEDEF, file_path, 1);
639   return found;
640 }
641 
642 static int
match_SCALE(const char * restrict filename,const Dwg_Object * restrict obj)643 match_SCALE (const char *restrict filename, const Dwg_Object *restrict obj)
644 {
645   char *text;
646   int found = 0, i;
647   //const Dwg_Object_SCALE *_obj = obj->tio.object->tio.SCALE;
648   MATCH_OBJECT (SCALE, name, 1);
649   return found;
650 }
651 
652 static int
match_LAYER_INDEX(const char * restrict filename,const Dwg_Object * restrict obj)653 match_LAYER_INDEX (const char *restrict filename,
654                    const Dwg_Object *restrict obj)
655 {
656   char *text;
657   int found = 0;
658   BITCODE_BL i;
659   const Dwg_Object_LAYER_INDEX *_obj = obj->tio.object->tio.LAYER_INDEX;
660   for (i = 0; i < _obj->num_entries; i++)
661     {
662       MATCH_OBJECT (LAYER_INDEX, entries[i].name, 8);
663     }
664   return found;
665 }
666 
667 static int
match_LAYOUT(const char * restrict filename,const Dwg_Object * restrict obj)668 match_LAYOUT (const char *restrict filename, const Dwg_Object *restrict obj)
669 {
670   char *text;
671   int found = 0;
672   BITCODE_BL i;
673   const Dwg_Object_LAYOUT *_obj = obj->tio.object->tio.LAYOUT;
674 
675   MATCH_OBJECT (LAYOUT, plotsettings.printer_cfg_file, 1);
676   MATCH_OBJECT (LAYOUT, plotsettings.paper_size, 2);
677   MATCH_OBJECT (LAYOUT, plotsettings.canonical_media_name, 4);
678   MATCH_TABLE (LAYOUT, plotsettings.plotview, VIEW, 6);
679   MATCH_OBJECT (LAYOUT, plotsettings.plotview_name, 6);
680   MATCH_OBJECT (LAYOUT, plotsettings.stylesheet, 7);
681 
682   MATCH_OBJECT (LAYOUT, layout_name, 1);
683   MATCH_TABLE (LAYOUT, block_header, BLOCK, 330);
684   MATCH_TABLE (LAYOUT, active_viewport, VIEWPORT, 331);
685   MATCH_TABLE (LAYOUT, shadeplot, VISUALSTYLE, 333);
686   MATCH_TABLE (LAYOUT, base_ucs, UCS, 346);
687   MATCH_TABLE (LAYOUT, named_ucs, UCS, 345);
688   for (i = 0; i < _obj->num_viewports; i++)
689     {
690       MATCH_TABLE (LAYOUT, viewports[i], VPORT, 0);
691     }
692   return found;
693 }
694 
695 static int
match_FIELD(const char * restrict filename,const Dwg_Object * restrict obj)696 match_FIELD (const char *restrict filename, const Dwg_Object *restrict obj)
697 {
698   char *text;
699   int found = 0;
700   BITCODE_BL i;
701   const Dwg_Object_FIELD *_obj = obj->tio.object->tio.FIELD;
702 
703   MATCH_OBJECT (FIELD, format, 4);
704   MATCH_OBJECT (FIELD, evaluation_error_msg, 300);
705   MATCH_OBJECT (FIELD, value.format_string, 300);
706   MATCH_OBJECT (FIELD, value.value_string, 300);
707   MATCH_OBJECT (FIELD, value_string, 301);
708   for (i = 0; i < _obj->num_childval; i++)
709     {
710       MATCH_OBJECT (FIELD, childval[i].key, 6);
711       MATCH_OBJECT (FIELD, childval[i].value.format_string, 300);
712       MATCH_OBJECT (FIELD, childval[i].value.value_string, 302);
713     }
714   return found;
715 }
716 
717 static int
match_TABLE(const char * restrict filename,const Dwg_Object * restrict obj)718 match_TABLE (const char *restrict filename, const Dwg_Object *restrict obj)
719 {
720   char *text;
721   int found = 0;
722   BITCODE_BL i, j;
723   const Dwg_Entity_TABLE *_obj = obj->tio.entity->tio.TABLE;
724 
725   for (i = 0; i < _obj->num_cells; i++)
726     {
727       if (_obj->cells[i].type == 1)
728         {
729           MATCH_ENTITY (TABLE, cells[i].text_value, 1);
730         }
731       else if (_obj->cells[i].type == 2
732                && _obj->cells[i].additional_data_flag == 1
733                && _obj->cells[i].num_attr_defs)
734         {
735           for (j = 0; j < _obj->cells[i].num_attr_defs; j++)
736             {
737               MATCH_ENTITY (TABLE, cells[i].attr_defs[j].text, 300);
738             }
739         }
740     }
741   return found;
742 }
743 
744 static int
match_TABLECONTENT(const char * restrict filename,const Dwg_Object * restrict obj)745 match_TABLECONTENT (const char *restrict filename,
746                     const Dwg_Object *restrict obj)
747 {
748   char *text;
749   int found = 0;
750   BITCODE_BL i, j, k;
751   const Dwg_Object_TABLECONTENT *_obj = obj->tio.object->tio.TABLECONTENT;
752 
753   MATCH_OBJECT (TABLECONTENT, ldata.name, 1);
754   MATCH_OBJECT (TABLECONTENT, ldata.description, 300);
755   for (i = 0; i < _obj->tdata.num_cols; i++)
756     {
757       MATCH_OBJECT (TABLECONTENT, tdata.cols[i].name, 300);
758     }
759   for (i = 0; i < _obj->tdata.num_rows; i++)
760     {
761       for (j = 0; j < _obj->tdata.rows[i].num_cells; j++)
762         {
763           MATCH_OBJECT (TABLECONTENT, tdata.rows[i].cells[j].tooltip, 300);
764           for (k = 0; k < _obj->tdata.rows[i].cells[j].num_customdata_items;
765                k++)
766             {
767 #define _custom tdata.rows[i].cells[j].customdata_items[k]
768               MATCH_OBJECT (TABLECONTENT, _custom.name, 300);
769               if (_obj->_custom.value.data_type == 4)
770                 {
771                   MATCH_OBJECT (TABLECONTENT, _custom.value.data_string, 302);
772                 }
773 #undef _custom
774             }
775           for (k = 0; k < _obj->tdata.rows[i].cells[j].num_cell_contents; k++)
776             {
777 #define _content tdata.rows[i].cells[j].cell_contents[k]
778               if (_obj->_content.type == 1
779                   && _obj->_content.value.data_type == 4)
780                 {
781                   MATCH_OBJECT (TABLECONTENT, _content.value.data_string, 302);
782                 }
783 #undef _content
784             }
785         }
786     }
787   return found;
788 }
789 
790 static int
match_GEODATA(const char * restrict filename,const Dwg_Object * restrict obj)791 match_GEODATA (const char *restrict filename, const Dwg_Object *restrict obj)
792 {
793   char *text;
794   int found = 0;
795   //const Dwg_Object_GEODATA *_obj = obj->tio.object->tio.GEODATA;
796 
797   MATCH_OBJECT (GEODATA, coord_system_def, 0);
798   MATCH_OBJECT (GEODATA, geo_rss_tag, 302);
799   MATCH_OBJECT (GEODATA, observation_from_tag, 305);
800   MATCH_OBJECT (GEODATA, observation_to_tag, 306);
801   MATCH_OBJECT (GEODATA, observation_coverage_tag, 0);
802   // obsolete
803   MATCH_OBJECT (GEODATA, coord_system_datum, 0);
804   MATCH_OBJECT (GEODATA, coord_system_wkt, 0);
805   return found;
806 }
807 
808 static int
match_GEOPOSITIONMARKER(const char * restrict filename,const Dwg_Object * restrict obj)809 match_GEOPOSITIONMARKER (const char *restrict filename,
810                          const Dwg_Object *restrict obj)
811 {
812   char *text;
813   int found = 0;
814   //const Dwg_Entity_GEOPOSITIONMARKER *_obj = obj->tio.entity->tio.GEOPOSITIONMARKER;
815 
816   MATCH_ENTITY (GEOPOSITIONMARKER, notes, 1);
817   //if enabled
818   //MATCH_ENTITY (GEOPOSITIONMARKER, mtext->tio.entity->tio.MTEXT->text, 3);
819   return found;
820 }
821 
822 static int
match_UNDERLAYDEFINITION(const char * restrict filename,const Dwg_Object * restrict obj)823 match_UNDERLAYDEFINITION (const char *restrict filename,
824                           const Dwg_Object *restrict obj)
825 {
826   char *text;
827   int found = 0;
828   //const Dwg_Object_PDFDEFINITION *_obj = obj->tio.object->tio.PDFDEFINITION;
829 
830   MATCH_OBJECT (PDFDEFINITION, filename, 1);
831   MATCH_OBJECT (PDFDEFINITION, name, 2);
832   return found;
833 }
834 
835 static int
match_VISUALSTYLE(const char * restrict filename,const Dwg_Object * restrict obj)836 match_VISUALSTYLE (const char *restrict filename,
837                    const Dwg_Object *restrict obj)
838 {
839   char *text;
840   int found = 0, i;
841   //const Dwg_Object_VISUALSTYLE *_obj = obj->tio.object->tio.VISUALSTYLE;
842   MATCH_OBJECT (VISUALSTYLE, description, 1);
843   return found;
844 }
845 
846 static int
match_TABLESTYLE(const char * restrict filename,const Dwg_Object * restrict obj)847 match_TABLESTYLE (const char *restrict filename,
848                    const Dwg_Object *restrict obj)
849 {
850   char *text;
851   int found = 0, i;
852   //const Dwg_Object_TABLESTYLE *_obj = obj->tio.object->tio.TABLESTYLE;
853   MATCH_OBJECT (TABLESTYLE, name, 2);
854   return found;
855 }
856 static int
match_LIGHT(const char * restrict filename,const Dwg_Object * restrict obj)857 match_LIGHT (const char *restrict filename, const Dwg_Object *restrict obj)
858 {
859   char *text;
860   int found = 0;
861   //const Dwg_Entity_LIGHT *_obj = obj->tio.entity->tio.LIGHT;
862   MATCH_ENTITY (LIGHT, name, 1);
863   // MATCH_ENTITY (LIGHT, web_file, 1);
864   return found;
865 }
866 
867 static int
match_SUNSTUDY(const char * restrict filename,const Dwg_Object * restrict obj)868 match_SUNSTUDY (const char *restrict filename, const Dwg_Object *restrict obj)
869 {
870   char *text;
871   int found = 0;
872   //const Dwg_Object_SUNSTUDY *_obj = obj->tio.object->tio.SUNSTUDY;
873   MATCH_OBJECT (SUNSTUDY, setup_name, 1);
874   MATCH_OBJECT (SUNSTUDY, description, 2);
875   MATCH_OBJECT (SUNSTUDY, sheet_set_name, 3);
876   return found;
877 }
878 
879 static int
match_LIGHTLIST(const char * restrict filename,const Dwg_Object * restrict obj)880 match_LIGHTLIST (const char *restrict filename, const Dwg_Object *restrict obj)
881 {
882   char *text;
883   int found = 0;
884   const Dwg_Object_LIGHTLIST *_obj = obj->tio.object->tio.LIGHTLIST;
885 
886   for (BITCODE_BL i = 0; i < _obj->num_lights; i++)
887     {
888       MATCH_OBJECT (LIGHTLIST, lights[i].name, 1);
889     }
890   return found;
891 }
892 
893 static int
match_DBCOLOR(const char * restrict filename,const Dwg_Object * restrict obj)894 match_DBCOLOR (const char *restrict filename, const Dwg_Object *restrict obj)
895 {
896   char *text;
897   int found = 0;
898   //const Dwg_Object_DBCOLOR *_obj = obj->tio.object->tio.DBCOLOR;
899   MATCH_OBJECT (DBCOLOR, color.name, 430);
900   MATCH_OBJECT (DBCOLOR, color.book_name, 430);
901   return found;
902 }
903 
904 static int
match_MATERIAL(const char * restrict filename,const Dwg_Object * restrict obj)905 match_MATERIAL (const char *restrict filename, const Dwg_Object *restrict obj)
906 {
907   char *text;
908   int found = 0;
909   //const Dwg_Object_MATERIAL *_obj = obj->tio.object->tio.MATERIAL;
910   MATCH_OBJECT (MATERIAL, name, 1);
911   MATCH_OBJECT (MATERIAL, description, 2);
912   MATCH_OBJECT (MATERIAL, diffusemap.filename, 3);
913   MATCH_OBJECT (MATERIAL, specularmap.filename, 4);
914   MATCH_OBJECT (MATERIAL, reflectionmap.filename, 6);
915   MATCH_OBJECT (MATERIAL, opacitymap.filename, 7);
916   MATCH_OBJECT (MATERIAL, bumpmap.filename, 8);
917   MATCH_OBJECT (MATERIAL, refractionmap.filename, 9);
918   //MATCH_OBJECT (MATERIAL, normalmap.filename, 3);
919   //MATCH_OBJECT (MATERIAL, genprocname, 300);
920   //MATCH_OBJECT (MATERIAL, genprocvaltext, 301);
921   //MATCH_OBJECT (MATERIAL, genprocvalcolorname, 430);
922   return found;
923 }
924 
925 static int
match_PLOTSETTINGS(const char * restrict filename,const Dwg_Object * restrict obj)926 match_PLOTSETTINGS (const char *restrict filename,
927                     const Dwg_Object *restrict obj)
928 {
929   char *text;
930   int found = 0;
931   //const Dwg_Object_PLOTSETTINGS *_obj = obj->tio.object->tio.PLOTSETTINGS;
932   MATCH_OBJECT (PLOTSETTINGS, printer_cfg_file, 1);
933   MATCH_OBJECT (PLOTSETTINGS, paper_size, 2);
934   MATCH_OBJECT (PLOTSETTINGS, canonical_media_name, 4);
935   MATCH_OBJECT (PLOTSETTINGS, plotview_name, 6);
936   MATCH_TABLE (PLOTSETTINGS, VIEW, plotview, 6);
937   MATCH_OBJECT (PLOTSETTINGS, stylesheet, 7);
938   MATCH_TABLE (PLOTSETTINGS, VISUALSTYLE, shadeplot, 333);
939   return found;
940 }
941 static int
match_DIMASSOC(const char * restrict filename,const Dwg_Object * restrict obj)942 match_DIMASSOC (const char *restrict filename,
943                    const Dwg_Object *restrict obj)
944 {
945   char *text;
946   int found = 0;
947   const Dwg_Object_DIMASSOC *_obj = obj->tio.object->tio.DIMASSOC;
948   for (BITCODE_BL i = 0; i < 4; i++)
949     {
950       if (_obj->ref[i].classname)
951         {
952           MATCH_OBJECT (DIMASSOC, ref[i].classname, 0);
953         }
954     }
955   return found;
956 }
957 
958 static int
match_ASSOCOSNAPPOINTREFACTIONPARAM(const char * restrict filename,const Dwg_Object * restrict obj)959 match_ASSOCOSNAPPOINTREFACTIONPARAM (const char *restrict filename,
960                                      const Dwg_Object *restrict obj)
961 {
962   char *text;
963   int found = 0;
964   MATCH_OBJECT (ASSOCOSNAPPOINTREFACTIONPARAM, name, 1);
965   return found;
966 }
967 static int
match_ASSOCACTIONPARAM(const char * restrict filename,const Dwg_Object * restrict obj)968 match_ASSOCACTIONPARAM (const char *restrict filename,
969                         const Dwg_Object *restrict obj)
970 {
971   char *text;
972   int found = 0;
973   MATCH_OBJECT (ASSOCACTIONPARAM, name, 1);
974   return found;
975 }
976 static int
match_ASSOCEDGEACTIONPARAM(const char * restrict filename,const Dwg_Object * restrict obj)977 match_ASSOCEDGEACTIONPARAM (const char *restrict filename,
978                         const Dwg_Object *restrict obj)
979 {
980   char *text;
981   int found = 0;
982   MATCH_OBJECT (ASSOCEDGEACTIONPARAM, name, 1);
983   return found;
984 }
985 static int
match_ASSOCFACEACTIONPARAM(const char * restrict filename,const Dwg_Object * restrict obj)986 match_ASSOCFACEACTIONPARAM (const char *restrict filename,
987                         const Dwg_Object *restrict obj)
988 {
989   char *text;
990   int found = 0;
991   MATCH_OBJECT (ASSOCFACEACTIONPARAM, name, 1);
992   return found;
993 }
994 static int
match_ASSOCOBJECTACTIONPARAM(const char * restrict filename,const Dwg_Object * restrict obj)995 match_ASSOCOBJECTACTIONPARAM (const char *restrict filename,
996                         const Dwg_Object *restrict obj)
997 {
998   char *text;
999   int found = 0;
1000   MATCH_OBJECT (ASSOCOBJECTACTIONPARAM, name, 1);
1001   return found;
1002 }
1003 static int
match_ASSOCPATHACTIONPARAM(const char * restrict filename,const Dwg_Object * restrict obj)1004 match_ASSOCPATHACTIONPARAM (const char *restrict filename,
1005                         const Dwg_Object *restrict obj)
1006 {
1007   char *text;
1008   int found = 0;
1009   MATCH_OBJECT (ASSOCPATHACTIONPARAM, name, 1);
1010   return found;
1011 }
1012 static int
match_ASSOCVERTEXACTIONPARAM(const char * restrict filename,const Dwg_Object * restrict obj)1013 match_ASSOCVERTEXACTIONPARAM (const char *restrict filename,
1014                         const Dwg_Object *restrict obj)
1015 {
1016   char *text;
1017   int found = 0;
1018   MATCH_OBJECT (ASSOCVERTEXACTIONPARAM, name, 1);
1019   return found;
1020 }
1021 
1022 // TODO match on its subclasses which holds the text:
1023 //  ASSOCVARIABLE, EvalVariant
1024 
1025 #define MATCH_AcDbAssocParamBasedActionBody(_type)                            \
1026   for (unsigned i = 0; i < _obj->pab.num_values; i++)                         \
1027   {                                                                           \
1028     MATCH_OBJECT (_type, pab.values[i].name, 1);                              \
1029     for (unsigned j = 0; j < _obj->pab.values[i].num_vars; j++)               \
1030       {                                                                       \
1031         int _dxf = _obj->pab.values[i].vars[j].value.code;                    \
1032         if (dwg_resbuf_value_type (_dxf) == DWG_VT_STRING)                    \
1033           {                                                                   \
1034             MATCH_OBJECT (_type, pab.values[i].vars[j].value.u.text, _dxf);   \
1035           }                                                                   \
1036       }                                                                       \
1037   }
1038 
1039 static int
match_ASSOCMLEADERACTIONBODY(const char * restrict filename,const Dwg_Object * restrict obj)1040 match_ASSOCMLEADERACTIONBODY (const char *restrict filename,
1041                                        const Dwg_Object *restrict obj)
1042 {
1043   char *text;
1044   int found = 0;
1045   const Dwg_Object_ASSOCMLEADERACTIONBODY *_obj
1046       = obj->tio.object->tio.ASSOCMLEADERACTIONBODY;
1047   MATCH_AcDbAssocParamBasedActionBody (ASSOCMLEADERACTIONBODY)
1048   return found;
1049 }
1050 static int
match_ASSOC3POINTANGULARDIMACTIONBODY(const char * restrict filename,const Dwg_Object * restrict obj)1051 match_ASSOC3POINTANGULARDIMACTIONBODY (const char *restrict filename,
1052                                        const Dwg_Object *restrict obj)
1053 {
1054   char *text;
1055   int found = 0;
1056   const Dwg_Object_ASSOC3POINTANGULARDIMACTIONBODY *_obj
1057       = obj->tio.object->tio.ASSOC3POINTANGULARDIMACTIONBODY;
1058   MATCH_AcDbAssocParamBasedActionBody (ASSOC3POINTANGULARDIMACTIONBODY)
1059   return found;
1060 }
1061 static int
match_ASSOCALIGNEDDIMACTIONBODY(const char * restrict filename,const Dwg_Object * restrict obj)1062 match_ASSOCALIGNEDDIMACTIONBODY (const char *restrict filename,
1063                                  const Dwg_Object *restrict obj)
1064 {
1065   char *text;
1066   int found = 0;
1067   const Dwg_Object_ASSOCALIGNEDDIMACTIONBODY *_obj
1068       = obj->tio.object->tio.ASSOCALIGNEDDIMACTIONBODY;
1069   MATCH_AcDbAssocParamBasedActionBody (ASSOCALIGNEDDIMACTIONBODY)
1070   return found;
1071 }
1072 
1073 static int
match_ASSOCORDINATEDIMACTIONBODY(const char * restrict filename,const Dwg_Object * restrict obj)1074 match_ASSOCORDINATEDIMACTIONBODY (const char *restrict filename,
1075                                  const Dwg_Object *restrict obj)
1076 {
1077   char *text;
1078   int found = 0;
1079   const Dwg_Object_ASSOCORDINATEDIMACTIONBODY *_obj
1080       = obj->tio.object->tio.ASSOCORDINATEDIMACTIONBODY;
1081   MATCH_AcDbAssocParamBasedActionBody (ASSOCORDINATEDIMACTIONBODY)
1082   return found;
1083 }
1084 
1085 static int
match_ASSOCROTATEDDIMACTIONBODY(const char * restrict filename,const Dwg_Object * restrict obj)1086 match_ASSOCROTATEDDIMACTIONBODY (const char *restrict filename,
1087                                  const Dwg_Object *restrict obj)
1088 {
1089   char *text;
1090   int found = 0;
1091   const Dwg_Object_ASSOCROTATEDDIMACTIONBODY *_obj
1092       = obj->tio.object->tio.ASSOCROTATEDDIMACTIONBODY;
1093   MATCH_AcDbAssocParamBasedActionBody (ASSOCROTATEDDIMACTIONBODY)
1094   return found;
1095 }
1096 
1097 static int
match_ASSOCPATCHSURFACEACTIONBODY(const char * restrict filename,const Dwg_Object * restrict obj)1098 match_ASSOCPATCHSURFACEACTIONBODY (const char *restrict filename,
1099                                    const Dwg_Object *restrict obj)
1100 {
1101   char *text;
1102   int found = 0;
1103   const Dwg_Object_ASSOCPATCHSURFACEACTIONBODY *_obj
1104       = obj->tio.object->tio.ASSOCPATCHSURFACEACTIONBODY;
1105   MATCH_AcDbAssocParamBasedActionBody (ASSOCPATCHSURFACEACTIONBODY)
1106   return found;
1107 }
1108 static int
match_ASSOCPLANESURFACEACTIONBODY(const char * restrict filename,const Dwg_Object * restrict obj)1109 match_ASSOCPLANESURFACEACTIONBODY (const char *restrict filename,
1110                                    const Dwg_Object *restrict obj)
1111 {
1112   char *text;
1113   int found = 0;
1114   const Dwg_Object_ASSOCPLANESURFACEACTIONBODY *_obj
1115       = obj->tio.object->tio.ASSOCPLANESURFACEACTIONBODY;
1116   MATCH_AcDbAssocParamBasedActionBody (ASSOCPLANESURFACEACTIONBODY)
1117   return found;
1118 }
1119 static int
match_ASSOCEXTENDSURFACEACTIONBODY(const char * restrict filename,const Dwg_Object * restrict obj)1120 match_ASSOCEXTENDSURFACEACTIONBODY (const char *restrict filename,
1121                                       const Dwg_Object *restrict obj)
1122 {
1123   char *text;
1124   int found = 0;
1125   const Dwg_Object_ASSOCEXTENDSURFACEACTIONBODY *_obj
1126       = obj->tio.object->tio.ASSOCEXTENDSURFACEACTIONBODY;
1127   MATCH_AcDbAssocParamBasedActionBody (ASSOCEXTENDSURFACEACTIONBODY)
1128   return found;
1129 }
1130 static int
match_ASSOCEXTRUDEDSURFACEACTIONBODY(const char * restrict filename,const Dwg_Object * restrict obj)1131 match_ASSOCEXTRUDEDSURFACEACTIONBODY (const char *restrict filename,
1132                                       const Dwg_Object *restrict obj)
1133 {
1134   char *text;
1135   int found = 0;
1136   const Dwg_Object_ASSOCEXTRUDEDSURFACEACTIONBODY *_obj
1137       = obj->tio.object->tio.ASSOCEXTRUDEDSURFACEACTIONBODY;
1138   MATCH_AcDbAssocParamBasedActionBody (ASSOCEXTRUDEDSURFACEACTIONBODY)
1139   return found;
1140 }
1141 static int
match_ASSOCFILLETSURFACEACTIONBODY(const char * restrict filename,const Dwg_Object * restrict obj)1142 match_ASSOCFILLETSURFACEACTIONBODY (const char *restrict filename,
1143                                    const Dwg_Object *restrict obj)
1144 {
1145   char *text;
1146   int found = 0;
1147   const Dwg_Object_ASSOCFILLETSURFACEACTIONBODY *_obj
1148       = obj->tio.object->tio.ASSOCFILLETSURFACEACTIONBODY;
1149   MATCH_AcDbAssocParamBasedActionBody (ASSOCFILLETSURFACEACTIONBODY)
1150   return found;
1151 }
1152 static int
match_ASSOCLOFTEDSURFACEACTIONBODY(const char * restrict filename,const Dwg_Object * restrict obj)1153 match_ASSOCLOFTEDSURFACEACTIONBODY (const char *restrict filename,
1154                                     const Dwg_Object *restrict obj)
1155 {
1156   char *text;
1157   int found = 0;
1158   const Dwg_Object_ASSOCLOFTEDSURFACEACTIONBODY *_obj
1159       = obj->tio.object->tio.ASSOCLOFTEDSURFACEACTIONBODY;
1160   MATCH_AcDbAssocParamBasedActionBody (ASSOCLOFTEDSURFACEACTIONBODY)
1161   return found;
1162 }
1163 static int
match_ASSOCNETWORKSURFACEACTIONBODY(const char * restrict filename,const Dwg_Object * restrict obj)1164 match_ASSOCNETWORKSURFACEACTIONBODY (const char *restrict filename,
1165                                     const Dwg_Object *restrict obj)
1166 {
1167   char *text;
1168   int found = 0;
1169   const Dwg_Object_ASSOCNETWORKSURFACEACTIONBODY *_obj
1170       = obj->tio.object->tio.ASSOCNETWORKSURFACEACTIONBODY;
1171   MATCH_AcDbAssocParamBasedActionBody (ASSOCNETWORKSURFACEACTIONBODY)
1172   return found;
1173 }
1174 static int
match_ASSOCOFFSETSURFACEACTIONBODY(const char * restrict filename,const Dwg_Object * restrict obj)1175 match_ASSOCOFFSETSURFACEACTIONBODY (const char *restrict filename,
1176                                     const Dwg_Object *restrict obj)
1177 {
1178   char *text;
1179   int found = 0;
1180   const Dwg_Object_ASSOCOFFSETSURFACEACTIONBODY *_obj
1181       = obj->tio.object->tio.ASSOCOFFSETSURFACEACTIONBODY;
1182   MATCH_AcDbAssocParamBasedActionBody (ASSOCOFFSETSURFACEACTIONBODY)
1183   return found;
1184 }
1185 static int
match_ASSOCREVOLVEDSURFACEACTIONBODY(const char * restrict filename,const Dwg_Object * restrict obj)1186 match_ASSOCREVOLVEDSURFACEACTIONBODY (const char *restrict filename,
1187                                       const Dwg_Object *restrict obj)
1188 {
1189   char *text;
1190   int found = 0;
1191   const Dwg_Object_ASSOCREVOLVEDSURFACEACTIONBODY *_obj
1192       = obj->tio.object->tio.ASSOCREVOLVEDSURFACEACTIONBODY;
1193   MATCH_AcDbAssocParamBasedActionBody (ASSOCREVOLVEDSURFACEACTIONBODY)
1194   return found;
1195 }
1196 static int
match_ASSOCSWEPTSURFACEACTIONBODY(const char * restrict filename,const Dwg_Object * restrict obj)1197 match_ASSOCSWEPTSURFACEACTIONBODY (const char *restrict filename,
1198                                    const Dwg_Object *restrict obj)
1199 {
1200   char *text;
1201   int found = 0;
1202   const Dwg_Object_ASSOCSWEPTSURFACEACTIONBODY *_obj
1203       = obj->tio.object->tio.ASSOCSWEPTSURFACEACTIONBODY;
1204   MATCH_AcDbAssocParamBasedActionBody (ASSOCSWEPTSURFACEACTIONBODY)
1205   return found;
1206 }
1207 static int
match_ASSOCTRIMSURFACEACTIONBODY(const char * restrict filename,const Dwg_Object * restrict obj)1208 match_ASSOCTRIMSURFACEACTIONBODY (const char *restrict filename,
1209                                    const Dwg_Object *restrict obj)
1210 {
1211   char *text;
1212   int found = 0;
1213   const Dwg_Object_ASSOCTRIMSURFACEACTIONBODY *_obj
1214       = obj->tio.object->tio.ASSOCTRIMSURFACEACTIONBODY;
1215   MATCH_AcDbAssocParamBasedActionBody (ASSOCTRIMSURFACEACTIONBODY)
1216   return found;
1217 }
1218 
1219 static int
match_BLOCKPARAMDEPENDENCYBODY(const char * restrict filename,const Dwg_Object * restrict obj)1220 match_BLOCKPARAMDEPENDENCYBODY (const char *restrict filename,
1221                           const Dwg_Object *restrict obj)
1222 {
1223   char *text;
1224   int found = 0;
1225   MATCH_OBJECT (BLOCKPARAMDEPENDENCYBODY, name, 1);
1226   return found;
1227 }
1228 static int
match_BLOCKMOVEACTION(const char * restrict filename,const Dwg_Object * restrict obj)1229 match_BLOCKMOVEACTION (const char *restrict filename,
1230                           const Dwg_Object *restrict obj)
1231 {
1232   char *text;
1233   int found = 0;
1234   MATCH_OBJECT (BLOCKMOVEACTION, conn_pts[0].name, 301);
1235   MATCH_OBJECT (BLOCKMOVEACTION, conn_pts[1].name, 302);
1236   return found;
1237 }
1238 static int
match_BLOCKSTRETCHACTION(const char * restrict filename,const Dwg_Object * restrict obj)1239 match_BLOCKSTRETCHACTION (const char *restrict filename,
1240                           const Dwg_Object *restrict obj)
1241 {
1242   char *text;
1243   int found = 0;
1244   MATCH_OBJECT (BLOCKSTRETCHACTION, conn_pts[0].name, 301);
1245   MATCH_OBJECT (BLOCKSTRETCHACTION, conn_pts[1].name, 302);
1246   return found;
1247 }
1248 static int
match_BLOCKROTATEACTION(const char * restrict filename,const Dwg_Object * restrict obj)1249 match_BLOCKROTATEACTION (const char *restrict filename,
1250                           const Dwg_Object *restrict obj)
1251 {
1252   char *text;
1253   int found = 0;
1254   MATCH_OBJECT (BLOCKROTATEACTION, conn_pts[0].name, 301);
1255   MATCH_OBJECT (BLOCKROTATEACTION, conn_pts[1].name, 302);
1256   MATCH_OBJECT (BLOCKROTATEACTION, conn_pts[2].name, 303);
1257   return found;
1258 }
1259 static int
match_BLOCKVISIBILITYGRIP(const char * restrict filename,const Dwg_Object * restrict obj)1260 match_BLOCKVISIBILITYGRIP (const char *restrict filename,
1261                                const Dwg_Object *restrict obj)
1262 {
1263   char *text;
1264   int found = 0;
1265   Dwg_Object_BLOCKVISIBILITYGRIP *_obj = obj->tio.object->tio.BLOCKVISIBILITYGRIP;
1266 
1267   if (_obj->evalexpr.value_code == 1)
1268     {
1269       MATCH_OBJECT (BLOCKVISIBILITYGRIP, evalexpr.value.text1, 1);
1270     }
1271   MATCH_OBJECT (BLOCKVISIBILITYGRIP, name, 1);
1272   return found;
1273 }
1274 static int
match_BLOCKGRIPLOCATIONCOMPONENT(const char * restrict filename,const Dwg_Object * restrict obj)1275 match_BLOCKGRIPLOCATIONCOMPONENT (const char *restrict filename,
1276                                const Dwg_Object *restrict obj)
1277 {
1278   char *text;
1279   int found = 0;
1280   Dwg_Object_BLOCKGRIPLOCATIONCOMPONENT *_obj = obj->tio.object->tio.BLOCKGRIPLOCATIONCOMPONENT;
1281 
1282   if (_obj->evalexpr.value_code == 1)
1283     {
1284       MATCH_OBJECT (BLOCKGRIPLOCATIONCOMPONENT, evalexpr.value.text1, 1);
1285     }
1286   MATCH_OBJECT (BLOCKGRIPLOCATIONCOMPONENT, grip_expr, 91);
1287   return found;
1288 }
1289 static int
match_BLOCKBASEPOINTPARAMETER(const char * restrict filename,const Dwg_Object * restrict obj)1290 match_BLOCKBASEPOINTPARAMETER (const char *restrict filename,
1291                                const Dwg_Object *restrict obj)
1292 {
1293   char *text;
1294   int found = 0;
1295   Dwg_Object_BLOCKBASEPOINTPARAMETER *_obj = obj->tio.object->tio.BLOCKBASEPOINTPARAMETER;
1296 
1297   if (_obj->evalexpr.value_code == 1)
1298     {
1299       MATCH_OBJECT (BLOCKBASEPOINTPARAMETER, evalexpr.value.text1, 1);
1300     }
1301   MATCH_OBJECT (BLOCKBASEPOINTPARAMETER, name, 1);
1302   for (unsigned i = 0; i < _obj->prop1.num_connections; i++)
1303     {
1304       MATCH_OBJECT (BLOCKROTATIONPARAMETER, prop1.connections[i].name, 301);
1305     }
1306   for (unsigned i = 0; i < _obj->prop2.num_connections; i++)
1307     {
1308       MATCH_OBJECT (BLOCKROTATIONPARAMETER, prop2.connections[i].name, 302);
1309     }
1310   return found;
1311 }
1312 static int
match_BLOCKLINEARPARAMETER(const char * restrict filename,const Dwg_Object * restrict obj)1313 match_BLOCKLINEARPARAMETER (const char *restrict filename,
1314                           const Dwg_Object *restrict obj)
1315 {
1316   char *text;
1317   int found = 0;
1318   Dwg_Object_BLOCKLINEARPARAMETER *_obj = obj->tio.object->tio.BLOCKLINEARPARAMETER;
1319 
1320   if (_obj->evalexpr.value_code == 1)
1321     {
1322       MATCH_OBJECT (BLOCKLINEARPARAMETER, evalexpr.value.text1, 1);
1323     }
1324   MATCH_OBJECT (BLOCKLINEARPARAMETER, name, 1);
1325   for (unsigned i = 0; i < _obj->prop1.num_connections; i++)
1326     {
1327       MATCH_OBJECT (BLOCKLINEARPARAMETER, prop1.connections[i].name, 301);
1328     }
1329   for (unsigned i = 0; i < _obj->prop2.num_connections; i++)
1330     {
1331       MATCH_OBJECT (BLOCKLINEARPARAMETER, prop2.connections[i].name, 302);
1332     }
1333   for (unsigned i = 0; i < _obj->prop3.num_connections; i++)
1334     {
1335       MATCH_OBJECT (BLOCKLINEARPARAMETER, prop3.connections[i].name, 303);
1336     }
1337   for (unsigned i = 0; i < _obj->prop4.num_connections; i++)
1338     {
1339       MATCH_OBJECT (BLOCKLINEARPARAMETER, prop4.connections[i].name, 304);
1340     }
1341   MATCH_OBJECT (BLOCKLINEARPARAMETER, distance_name, 305);
1342   MATCH_OBJECT (BLOCKLINEARPARAMETER, distance_desc, 306);
1343   MATCH_OBJECT (BLOCKLINEARPARAMETER, value_set.desc, 307);
1344   return found;
1345 }
1346 static int
match_BLOCKFLIPPARAMETER(const char * restrict filename,const Dwg_Object * restrict obj)1347 match_BLOCKFLIPPARAMETER (const char *restrict filename,
1348                           const Dwg_Object *restrict obj)
1349 {
1350   char *text;
1351   int found = 0;
1352   Dwg_Object_BLOCKFLIPPARAMETER *_obj = obj->tio.object->tio.BLOCKFLIPPARAMETER;
1353 
1354   if (_obj->evalexpr.value_code == 1)
1355     {
1356       MATCH_OBJECT (BLOCKFLIPPARAMETER, evalexpr.value.text1, 1);
1357     }
1358   MATCH_OBJECT (BLOCKFLIPPARAMETER, name, 1);
1359   for (unsigned i = 0; i < _obj->prop1.num_connections; i++)
1360     {
1361       MATCH_OBJECT (BLOCKFLIPPARAMETER, prop1.connections[i].name, 301);
1362     }
1363   for (unsigned i = 0; i < _obj->prop2.num_connections; i++)
1364     {
1365       MATCH_OBJECT (BLOCKFLIPPARAMETER, prop2.connections[i].name, 302);
1366     }
1367   for (unsigned i = 0; i < _obj->prop3.num_connections; i++)
1368     {
1369       MATCH_OBJECT (BLOCKFLIPPARAMETER, prop3.connections[i].name, 303);
1370     }
1371   for (unsigned i = 0; i < _obj->prop4.num_connections; i++)
1372     {
1373       MATCH_OBJECT (BLOCKFLIPPARAMETER, prop4.connections[i].name, 304);
1374     }
1375   MATCH_OBJECT (BLOCKFLIPPARAMETER, flip_label, 305);
1376   MATCH_OBJECT (BLOCKFLIPPARAMETER, flip_label_desc, 306);
1377   MATCH_OBJECT (BLOCKFLIPPARAMETER, base_state_label, 307);
1378   MATCH_OBJECT (BLOCKFLIPPARAMETER, flipped_state_label, 308);
1379   MATCH_OBJECT (BLOCKFLIPPARAMETER, tooltip, 309);
1380   return found;
1381 }
1382 static int
match_BLOCKROTATIONPARAMETER(const char * restrict filename,const Dwg_Object * restrict obj)1383 match_BLOCKROTATIONPARAMETER (const char *restrict filename,
1384                           const Dwg_Object *restrict obj)
1385 {
1386   char *text;
1387   int found = 0;
1388   Dwg_Object_BLOCKROTATIONPARAMETER *_obj = obj->tio.object->tio.BLOCKROTATIONPARAMETER;
1389 
1390   if (_obj->evalexpr.value_code == 1)
1391     {
1392       MATCH_OBJECT (BLOCKROTATIONPARAMETER, evalexpr.value.text1, 1);
1393     }
1394   MATCH_OBJECT (BLOCKROTATIONPARAMETER, name, 1);
1395   for (unsigned i = 0; i < _obj->prop1.num_connections; i++)
1396     {
1397       MATCH_OBJECT (BLOCKROTATIONPARAMETER, prop1.connections[i].name, 301);
1398     }
1399   for (unsigned i = 0; i < _obj->prop2.num_connections; i++)
1400     {
1401       MATCH_OBJECT (BLOCKROTATIONPARAMETER, prop2.connections[i].name, 302);
1402     }
1403   for (unsigned i = 0; i < _obj->prop3.num_connections; i++)
1404     {
1405       MATCH_OBJECT (BLOCKROTATIONPARAMETER, prop3.connections[i].name, 303);
1406     }
1407   for (unsigned i = 0; i < _obj->prop4.num_connections; i++)
1408     {
1409       MATCH_OBJECT (BLOCKROTATIONPARAMETER, prop4.connections[i].name, 304);
1410     }
1411   MATCH_OBJECT (BLOCKROTATIONPARAMETER, angle_name, 305);
1412   MATCH_OBJECT (BLOCKROTATIONPARAMETER, angle_desc, 306);
1413   MATCH_OBJECT (BLOCKROTATIONPARAMETER, angle_value_set.desc, 307);
1414   return found;
1415 }
1416 static int
match_BLOCKXYPARAMETER(const char * restrict filename,const Dwg_Object * restrict obj)1417 match_BLOCKXYPARAMETER (const char *restrict filename,
1418                           const Dwg_Object *restrict obj)
1419 {
1420   char *text;
1421   int found = 0;
1422   Dwg_Object_BLOCKXYPARAMETER *_obj = obj->tio.object->tio.BLOCKXYPARAMETER;
1423 
1424   if (_obj->evalexpr.value_code == 1)
1425     {
1426       MATCH_OBJECT (BLOCKXYPARAMETER, evalexpr.value.text1, 1);
1427     }
1428   MATCH_OBJECT (BLOCKXYPARAMETER, name, 1);
1429   for (unsigned i = 0; i < _obj->prop1.num_connections; i++)
1430     {
1431       MATCH_OBJECT (BLOCKXYPARAMETER, prop1.connections[i].name, 301);
1432     }
1433   for (unsigned i = 0; i < _obj->prop2.num_connections; i++)
1434     {
1435       MATCH_OBJECT (BLOCKXYPARAMETER, prop2.connections[i].name, 302);
1436     }
1437   for (unsigned i = 0; i < _obj->prop3.num_connections; i++)
1438     {
1439       MATCH_OBJECT (BLOCKXYPARAMETER, prop3.connections[i].name, 303);
1440     }
1441   for (unsigned i = 0; i < _obj->prop4.num_connections; i++)
1442     {
1443       MATCH_OBJECT (BLOCKXYPARAMETER, prop4.connections[i].name, 304);
1444     }
1445   MATCH_OBJECT (BLOCKXYPARAMETER, x_label, 305);
1446   MATCH_OBJECT (BLOCKXYPARAMETER, x_label_desc, 306);
1447   MATCH_OBJECT (BLOCKXYPARAMETER, y_label, 307);
1448   MATCH_OBJECT (BLOCKXYPARAMETER, y_label_desc, 308);
1449   MATCH_OBJECT (BLOCKXYPARAMETER, x_value_set.desc, 410);
1450   MATCH_OBJECT (BLOCKXYPARAMETER, y_value_set.desc, 309);
1451   return found;
1452 }
1453 static int
match_BLOCKVISIBILITYPARAMETER(const char * restrict filename,const Dwg_Object * restrict obj)1454 match_BLOCKVISIBILITYPARAMETER (const char *restrict filename,
1455                           const Dwg_Object *restrict obj)
1456 {
1457   char *text;
1458   int found = 0;
1459   Dwg_Object_BLOCKVISIBILITYPARAMETER *_obj = obj->tio.object->tio.BLOCKVISIBILITYPARAMETER;
1460 
1461   if (_obj->evalexpr.value_code == 1)
1462     {
1463       MATCH_OBJECT (BLOCKVISIBILITYPARAMETER, evalexpr.value.text1, 1);
1464     }
1465   MATCH_OBJECT (BLOCKVISIBILITYPARAMETER, name, 1);
1466   for (unsigned i = 0; i < _obj->prop1.num_connections; i++)
1467     {
1468       MATCH_OBJECT (BLOCKVISIBILITYPARAMETER, prop1.connections[i].name, 301);
1469     }
1470   for (unsigned i = 0; i < _obj->prop2.num_connections; i++)
1471     {
1472       MATCH_OBJECT (BLOCKVISIBILITYPARAMETER, prop2.connections[i].name, 302);
1473     }
1474   MATCH_OBJECT (BLOCKVISIBILITYPARAMETER, blockvisi_name, 301);
1475   MATCH_OBJECT (BLOCKVISIBILITYPARAMETER, blockvisi_desc, 302);
1476   for (unsigned i = 0; i < _obj->num_states; i++)
1477     {
1478       MATCH_OBJECT (BLOCKVISIBILITYPARAMETER, states[i].name, 303);
1479     }
1480   return found;
1481 }
1482 static int
match_NAVISWORKSMODELDEF(const char * restrict filename,const Dwg_Object * restrict obj)1483 match_NAVISWORKSMODELDEF (const char *restrict filename,
1484                           const Dwg_Object *restrict obj)
1485 {
1486   char *text;
1487   int found = 0;
1488   MATCH_OBJECT (NAVISWORKSMODELDEF, path, 1);
1489   return found;
1490 }
1491 
1492 static int
match_OBJECTS(const char * restrict filename,Dwg_Data * restrict dwg)1493 match_OBJECTS (const char *restrict filename, Dwg_Data *restrict dwg)
1494 {
1495   int found = 0;
1496   char *text;
1497 
1498   if (!dwg)
1499     return 0;
1500   for (BITCODE_BL i = 0; i < dwg->num_objects; i++)
1501     {
1502       const Dwg_Object *obj = &dwg->object[i];
1503       if (obj->supertype != DWG_SUPERTYPE_OBJECT)
1504         continue;
1505       if (obj->type == DWG_TYPE_BLOCK_HEADER) // processed later, --tables finds BLOCK
1506         continue;
1507       if (numtype) // search for allowed --type and skip if not
1508         {
1509           int typeok = 0;
1510           for (int j = 0; j < numtype; j++)
1511             {
1512               if (obj->dxfname && !strcmp (type[j], obj->dxfname))
1513                 {
1514                   typeok = 1;
1515                   break;
1516                 }
1517             }
1518           if (!typeok) // next obj
1519             continue;
1520         }
1521 
1522 #define ELSEMATCH(OBJECT)                                               \
1523   else if (obj->fixedtype == DWG_TYPE_##OBJECT)                         \
1524     found += match_##OBJECT (filename, obj);
1525 
1526       if (obj->type == DWG_TYPE_LAYER)
1527         found += match_LAYER (filename, obj);
1528       ELSEMATCH (LTYPE)
1529       ELSEMATCH (STYLE)
1530       ELSEMATCH (VIEW)
1531       ELSEMATCH (VPORT)
1532       ELSEMATCH (DIMSTYLE)
1533       ELSEMATCH (UCS)
1534       ELSEMATCH (VX_TABLE_RECORD)
1535       if (opt_tables)
1536         continue;
1537 
1538       if (obj->fixedtype == DWG_TYPE_DICTIONARY
1539           || obj->fixedtype == DWG_TYPE_DICTIONARYWDFLT)
1540         found += match_DICTIONARY (filename, obj);
1541       ELSEMATCH (GROUP)
1542       ELSEMATCH (MLINESTYLE)
1543       ELSEMATCH (DICTIONARYVAR)
1544       ELSEMATCH (IMAGEDEF)
1545       ELSEMATCH (LAYER_INDEX)
1546       ELSEMATCH (LAYOUT)
1547       ELSEMATCH (PLOTSETTINGS)
1548       ELSEMATCH (SCALE)
1549       ELSEMATCH (FIELD)
1550       ELSEMATCH (TABLECONTENT)
1551       ELSEMATCH (GEODATA)
1552       else if (obj->fixedtype == DWG_TYPE_PDFDEFINITION)
1553         found += match_UNDERLAYDEFINITION (filename, obj);
1554       else if (obj->fixedtype == DWG_TYPE_DGNDEFINITION)
1555         found += match_UNDERLAYDEFINITION (filename, obj);
1556       else if (obj->fixedtype == DWG_TYPE_DWFDEFINITION)
1557         found += match_UNDERLAYDEFINITION (filename, obj);
1558       ELSEMATCH (VISUALSTYLE)
1559       ELSEMATCH (TABLESTYLE)
1560       ELSEMATCH (SUNSTUDY)
1561       ELSEMATCH (LIGHTLIST)
1562       ELSEMATCH (DBCOLOR)
1563       ELSEMATCH (MATERIAL)
1564       ELSEMATCH (DIMASSOC)
1565       ELSEMATCH (ASSOCOSNAPPOINTREFACTIONPARAM)
1566       ELSEMATCH (ASSOCACTIONPARAM)
1567       ELSEMATCH (ASSOCEDGEACTIONPARAM)
1568       ELSEMATCH (ASSOCFACEACTIONPARAM)
1569       ELSEMATCH (ASSOCOBJECTACTIONPARAM)
1570       ELSEMATCH (ASSOCPATHACTIONPARAM)
1571       ELSEMATCH (ASSOCVERTEXACTIONPARAM)
1572       ELSEMATCH (ASSOCPATCHSURFACEACTIONBODY)
1573       ELSEMATCH (ASSOCPLANESURFACEACTIONBODY)
1574       ELSEMATCH (ASSOCEXTENDSURFACEACTIONBODY)
1575       ELSEMATCH (ASSOCEXTRUDEDSURFACEACTIONBODY)
1576       ELSEMATCH (ASSOCFILLETSURFACEACTIONBODY)
1577       ELSEMATCH (ASSOCLOFTEDSURFACEACTIONBODY)
1578       ELSEMATCH (ASSOCNETWORKSURFACEACTIONBODY)
1579       ELSEMATCH (ASSOCOFFSETSURFACEACTIONBODY)
1580       ELSEMATCH (ASSOCREVOLVEDSURFACEACTIONBODY)
1581       ELSEMATCH (ASSOCSWEPTSURFACEACTIONBODY)
1582       ELSEMATCH (ASSOCTRIMSURFACEACTIONBODY)
1583       ELSEMATCH (ASSOCMLEADERACTIONBODY)
1584       ELSEMATCH (ASSOC3POINTANGULARDIMACTIONBODY)
1585       ELSEMATCH (ASSOCALIGNEDDIMACTIONBODY)
1586       ELSEMATCH (ASSOCORDINATEDIMACTIONBODY)
1587       ELSEMATCH (ASSOCROTATEDDIMACTIONBODY)
1588       ELSEMATCH (BLOCKPARAMDEPENDENCYBODY)
1589       ELSEMATCH (BLOCKBASEPOINTPARAMETER)
1590       ELSEMATCH (BLOCKFLIPPARAMETER)
1591       ELSEMATCH (BLOCKLINEARPARAMETER)
1592       ELSEMATCH (BLOCKROTATIONPARAMETER)
1593       ELSEMATCH (BLOCKXYPARAMETER)
1594       ELSEMATCH (BLOCKVISIBILITYPARAMETER)
1595       ELSEMATCH (BLOCKMOVEACTION)
1596       ELSEMATCH (BLOCKSTRETCHACTION)
1597       ELSEMATCH (BLOCKROTATEACTION)
1598       ELSEMATCH (BLOCKVISIBILITYGRIP)
1599       ELSEMATCH (BLOCKGRIPLOCATIONCOMPONENT)
1600       ELSEMATCH (NAVISWORKSMODELDEF)
1601     }
1602   return found;
1603 }
1604 
1605 static int
match_BLOCK_HEADER(const char * restrict filename,Dwg_Object_Ref * restrict ref)1606 match_BLOCK_HEADER (const char *restrict filename,
1607                     Dwg_Object_Ref *restrict ref)
1608 {
1609   int found = 0;
1610   const Dwg_Object *hdr;
1611   const Dwg_Object *obj;
1612   char *text;
1613 
1614   if (!ref)
1615     return 0;
1616   obj = hdr = ref->obj;
1617   if (!hdr || hdr->supertype != DWG_SUPERTYPE_OBJECT
1618       || hdr->type != DWG_TYPE_BLOCK_HEADER)
1619     return 0;
1620 
1621   MATCH_OBJECT (BLOCK_HEADER, name, 2);
1622   if (opt_tables)
1623     return found;
1624   MATCH_OBJECT (BLOCK_HEADER, xref_pname, 1);
1625   MATCH_OBJECT (BLOCK_HEADER, description, 4);
1626 
1627   if (verbose)
1628     fprintf(stderr, "HDR: %d, HANDLE: %lX\n", hdr->index, hdr->handle.value);
1629   for (obj = get_first_owned_entity (hdr); obj;
1630        obj = get_next_owned_entity (hdr, obj)) // without subentities
1631     {
1632       if (!obj)
1633         break;
1634       if (verbose)
1635         fprintf(stderr, "%s [%d], HANDLE: %lX\n", obj->name, obj->index, obj->handle.value);
1636       if (numtype) // search for allowed --type and skip if not
1637         {
1638           int typeok = 0;
1639           for (int i = 0; i < numtype; i++)
1640             {
1641               if (obj->dxfname && !strcmp (type[i], obj->dxfname))
1642                 {
1643                   typeok = 1;
1644                   break;
1645                 }
1646             }
1647           if (!typeok) // next obj
1648             continue;
1649         }
1650 
1651       if (obj->type == DWG_TYPE_TEXT)
1652         found += match_TEXT (filename, obj);
1653 #ifdef WITH_SUBENTS
1654       ELSEMATCH (ATTRIB)
1655 #endif
1656       ELSEMATCH (ATTDEF)
1657       ELSEMATCH (MTEXT)
1658       ELSEMATCH (ARCALIGNEDTEXT)
1659       else if (obj->type == DWG_TYPE_INSERT)
1660         {
1661 #ifndef WITH_SUBENTS
1662           const Dwg_Data *dwg = obj->parent;
1663           Dwg_Entity_INSERT *_obj = obj->tio.entity->tio.INSERT;
1664           if (_obj->has_attribs)
1665             {
1666               if (dwg->header.version >= R_13 && dwg->header.version <= R_2000)
1667                 {
1668                   Dwg_Object *last_attrib = _obj->last_attrib->obj;
1669                   Dwg_Object *o
1670                       = _obj->first_attrib ? _obj->first_attrib->obj : NULL;
1671                   while (o && o->type == DWG_TYPE_ATTRIB)
1672                     {
1673                       found += match_ATTRIB (filename, o);
1674                       o = dwg_next_entity (o);
1675                       if (o == last_attrib)
1676                         break;
1677                     }
1678                 }
1679               else if (dwg->header.version >= R_2004)
1680                 {
1681                   Dwg_Object *o;
1682                   for (BITCODE_BL j = 0; j < _obj->num_owned; j++)
1683                     {
1684                       o = _obj->attribs[j]
1685                               ? _obj->attribs[j]->obj
1686                               : NULL;
1687                       if (o && o->type == DWG_TYPE_ATTRIB)
1688                         found += match_ATTRIB (filename, o);
1689                     }
1690                 }
1691             }
1692 #endif
1693         }
1694       else if (obj->type == DWG_TYPE_MINSERT)
1695         {
1696 #ifndef WITH_SUBENTS
1697           const Dwg_Data *dwg = obj->parent;
1698           Dwg_Entity_MINSERT *_obj = obj->tio.entity->tio.MINSERT;
1699           if (_obj->has_attribs)
1700             {
1701               if (dwg->header.version >= R_13 && dwg->header.version <= R_2000)
1702                 {
1703                   Dwg_Object *last_attrib = _obj->last_attrib->obj;
1704                   Dwg_Object *o
1705                       = _obj->first_attrib ? _obj->first_attrib->obj : NULL;
1706                   while (o && o->type == DWG_TYPE_ATTRIB)
1707                     {
1708                       found += match_ATTRIB (filename, o);
1709                       o = dwg_next_entity (o);
1710                       if (o == last_attrib)
1711                         break;
1712                     }
1713                 }
1714               else if (dwg->header.version >= R_2004)
1715                 {
1716                   Dwg_Object *o;
1717                   for (BITCODE_BL j = 0; j < _obj->num_owned; j++)
1718                     {
1719                       o = _obj->attribs[j]
1720                               ? _obj->attribs[j]->obj
1721                               : NULL;
1722                       if (o && o->type == DWG_TYPE_ATTRIB)
1723                         found += match_ATTRIB (filename, o);
1724                     }
1725                 }
1726             }
1727 #endif
1728         }
1729       if (!opt_text)
1730         {
1731           if (obj->type == DWG_TYPE_DIMENSION_ORDINATE
1732               || obj->type == DWG_TYPE_DIMENSION_LINEAR
1733               || obj->type == DWG_TYPE_DIMENSION_ALIGNED
1734               || obj->type == DWG_TYPE_DIMENSION_ANG3PT
1735               || obj->type == DWG_TYPE_DIMENSION_ANG2LN
1736               || obj->type == DWG_TYPE_DIMENSION_RADIUS
1737               || obj->type == DWG_TYPE_DIMENSION_DIAMETER)
1738             found += match_DIMENSION (filename, obj);
1739           ELSEMATCH (VIEWPORT)
1740           else if (obj->type == DWG_TYPE__3DSOLID || obj->type == DWG_TYPE_BODY
1741                    || obj->type == DWG_TYPE_REGION)
1742             found += match_3DSOLID (filename, obj);
1743 
1744           ELSEMATCH (BLOCK)
1745           ELSEMATCH (HATCH)
1746           ELSEMATCH (TOLERANCE)
1747           ELSEMATCH (TABLE)
1748           ELSEMATCH (GEOPOSITIONMARKER)
1749           ELSEMATCH (LEADER)
1750           ELSEMATCH (MULTILEADER)
1751           ELSEMATCH (LIGHT)
1752         }
1753 
1754       if (!opt_text)
1755         {
1756           // common entity names
1757           MATCH_TABLE (ENTITY, layer, LAYER, 8);
1758           MATCH_TABLE (ENTITY, ltype, LTYPE, 8);
1759           if (obj->parent->header.version >= R_2000)
1760             {
1761               MATCH_TABLE (ENTITY, plotstyle, PLOTSTYLE, 8);
1762             }
1763           if (obj->parent->header.version >= R_2007)
1764             {
1765               MATCH_TABLE (ENTITY, material, MATERIAL, 8);
1766               MATCH_TABLE (ENTITY, shadow, DICTIONARY, 8);
1767             }
1768           if (obj->parent->header.version >= R_2010)
1769             {
1770               MATCH_TABLE (ENTITY, full_visualstyle, VISUALSTYLE, 8);
1771               MATCH_TABLE (ENTITY, face_visualstyle, VISUALSTYLE, 8);
1772               MATCH_TABLE (ENTITY, edge_visualstyle, VISUALSTYLE, 8);
1773             }
1774         }
1775     }
1776   return found;
1777 }
1778 
1779 int
main(int argc,char * argv[])1780 main (int argc, char *argv[])
1781 {
1782   int error = 0;
1783   int i = 1, j;
1784   char *filename;
1785   Dwg_Data dwg;
1786   int plen;
1787   int errcode;
1788 #ifdef HAVE_PCRE2_H
1789   PCRE2_SIZE erroffset;
1790   int have_jit;
1791 #  ifdef HAVE_PCRE2_16
1792   BITCODE_TU pattern16;
1793 #  endif
1794 #endif
1795   int opt_recurse = 0;
1796   int count = 0;
1797   int c;
1798 #ifdef HAVE_GETOPT_LONG
1799   int option_index = 0;
1800   static struct option long_options[]
1801       = { { "case", 0, 0, 'i' },      { "extended", 0, 0, 'x' },
1802           { "count", 0, 0, 'c' },     { "no-filename", 0, 0, 'h' },
1803           { "recursive", 0, 0, 'r' }, { "recursive", 0, 0, 'R' },
1804           { "type", 1, 0, 'y' },      { "dxf", 1, 0, 'd' },
1805           { "text", 0, 0, 't' },      { "blocks", 0, 0, 'b' },
1806           { "tables", 0, 0, 0 },
1807           { "help", 0, 0, 0 },        { "version", 0, 0, 0 },
1808           { NULL, 0, NULL, 0 } };
1809 #endif
1810 
1811   // check args
1812   if (argc < 2)
1813     return usage ();
1814   memset (dxf, 0, 10 * sizeof (short));
1815 
1816   while
1817 #ifdef HAVE_GETOPT_LONG
1818       ((c = getopt_long (argc, argv, "ixchrRy:d:tb", long_options,
1819                          &option_index))
1820        != -1)
1821 #else
1822       ((c = getopt (argc, argv, "ixchrRy:d:tbvu")) != -1)
1823 #endif
1824     {
1825       if (c == -1)
1826         break;
1827       switch (c)
1828         {
1829 #ifdef HAVE_GETOPT_LONG
1830         case 0:
1831           if (!strcmp (long_options[option_index].name, "help"))
1832             return help ();
1833           if (!strcmp (long_options[option_index].name, "version"))
1834             return opt_version ();
1835           if (!strcmp (long_options[option_index].name, "tables"))
1836             opt_tables = 1;
1837           break;
1838 #else
1839         case 'v':
1840           return opt_version ();
1841 #endif
1842 #ifdef HAVE_PCRE2_H
1843         case 'x':
1844           options |= PCRE2_EXTENDED;
1845           break;
1846 #endif
1847         case 'i':
1848           options |= PCRE2_CASELESS;
1849           break;
1850         case 'c':
1851           opt_count = 1;
1852           break;
1853         case 'h':
1854           opt_filename = 0;
1855           break;
1856         case 'r':
1857         case 'R':
1858           opt_recurse = 1;
1859           break;
1860         case 't':
1861           opt_text = 1;
1862           break;
1863         case 'b':
1864           opt_blocks = 1;
1865           break;
1866         case 'y':
1867           if (numtype >= 10)
1868             return usage ();        // too many
1869           type[numtype++] = optarg; // a string
1870           break;
1871         case 'd':
1872           if (numdxf >= 10)
1873             return usage (); // too many
1874           // a integer group
1875           dxf[numdxf++] = (short)strtol (optarg, NULL, 10);
1876           break;
1877 
1878         case 'u':
1879           return help ();
1880         case '?':
1881           fprintf (stderr, "%s: invalid option '-%c' ignored\n", argv[0],
1882                    optopt);
1883           break;
1884         default:
1885           return usage ();
1886         }
1887     }
1888   i = optind;
1889   if (i > argc - 2) // need 2 more args. TODO: unless -R given
1890     return usage ();
1891 
1892   pattern = argv[i];
1893   plen = strlen (pattern);
1894 #ifdef HAVE_PCRE2_H
1895   pcre2_config_8 (PCRE2_CONFIG_JIT, &have_jit);
1896   ri8 = pcre2_compile_8 ((PCRE2_SPTR8)pattern, plen, /* pattern */
1897                          options,                    /* options */
1898                          &errcode,                   /* errors */
1899                          &erroffset,                 /* error offset */
1900 #  ifdef USE_MATCH_CONTEXT
1901                          compile_context
1902 #  else
1903                          NULL
1904 #  endif
1905   );
1906   if (errcode != 0 && errcode != 100)
1907     {
1908       pcre2_get_error_message_8 (errcode, (PCRE2_UCHAR8 *)buf, 4096);
1909       LOG_ERROR ("pcre2_compile_8 error %d: %s with %s", errcode, buf,
1910                  pattern);
1911       return 1;
1912     }
1913   match_data8 = pcre2_match_data_create_from_pattern_8 (ri8, NULL);
1914   if (have_jit)
1915     pcre2_jit_compile_8 (ri8, PCRE2_JIT_COMPILE_OPTIONS);
1916 
1917 #  ifdef HAVE_PCRE2_16
1918   pcre2_config_16 (PCRE2_CONFIG_JIT, &have_jit);
1919   pattern16 = bit_utf8_to_TU (pattern, 0);
1920   ri16 = pcre2_compile_16 ((PCRE2_SPTR16)pattern16, plen, /* pattern */
1921                            options,                       /* options */
1922                            &errcode,                      /* errors */
1923                            &erroffset,                    /* error offset */
1924 #    ifdef USE_MATCH_CONTEXT
1925                            compile_context
1926 #    else
1927                            NULL
1928 #    endif
1929   );
1930   free (pattern16);
1931   if (errcode != 0 && errcode != 100)
1932     {
1933       pcre2_get_error_message_8 (errcode, (PCRE2_UCHAR8 *)buf, 4096);
1934       LOG_ERROR ("pcre2_compile_16 error %d: %s with %s", errcode, buf,
1935                  pattern);
1936       return 1;
1937     }
1938   match_data16 = pcre2_match_data_create_from_pattern_16 (ri16, NULL);
1939   if (have_jit)
1940     pcre2_jit_compile_16 (ri16, PCRE2_JIT_COMPILE_OPTIONS);
1941 #  endif
1942 #endif
1943 
1944   // for all filenames...
1945   for (j = i + 1; j < argc; j++)
1946     {
1947       filename = argv[j];
1948       memset (&dwg, 0, sizeof (Dwg_Data));
1949       dwg.opts = 0;
1950       error = dwg_read_file (filename, &dwg);
1951       if (error > DWG_ERR_CRITICAL)
1952         {
1953           fprintf (stderr, "Error: Could not read DWG file %s, error: 0x%x\n",
1954                    filename, error);
1955           continue;
1956         }
1957 
1958       if (!opt_text)
1959         count += match_OBJECTS (filename, &dwg);
1960       if (!opt_tables)
1961         count += match_BLOCK_HEADER (filename, dwg_model_space_ref (&dwg));
1962       if (opt_blocks)
1963         {
1964           for (long k = 0; k < dwg.block_control.num_entries; k++)
1965             {
1966               count += match_BLOCK_HEADER (filename, dwg.block_control.entries[k]);
1967             }
1968         }
1969       if (!opt_tables)
1970         count += match_BLOCK_HEADER (filename, dwg_paper_space_ref (&dwg));
1971 
1972       fflush (stdout);
1973       if (j < argc)
1974         dwg_free (&dwg); // skip the last free
1975     }
1976   if (opt_count)
1977     printf ("%d\n", count);
1978 
1979   return count ? 0 : 1;
1980 }
1981