1601 lines
56 KiB
C
1601 lines
56 KiB
C
/*****************************************************************************/
|
|
/* LibreDWG - free implementation of the DWG file format */
|
|
/* */
|
|
/* Copyright (C) 2018-2019 Free Software Foundation, Inc. */
|
|
/* */
|
|
/* This library is free software, licensed under the terms of the GNU */
|
|
/* General Public License as published by the Free Software Foundation, */
|
|
/* either version 3 of the License, or (at your option) any later version. */
|
|
/* You should have received a copy of the GNU General Public License */
|
|
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
/*****************************************************************************/
|
|
|
|
/*
|
|
* unknown.c: decode unknown bitstreams
|
|
* written by Reini Urban
|
|
*
|
|
* A sample program to find the most likely
|
|
* fields for all unknown dwg entities and objects.
|
|
* Gather all binary raw data from all unknown dwg entities and objects
|
|
* into examples/alldwg.inc and examples/alldxf_*.inc
|
|
* With the available likely fields try permutations of most likely types.
|
|
* When no identifiable field value was found, (filled is empty) 0.0% is
|
|
* printed and the entity is printed to stderr for alldwg.skip to be ignored
|
|
* later.
|
|
* See also HACKING "reverse-engineering with examples/unknown"
|
|
* or https://savannah.gnu.org/forum/forum.php?forum_id=9197 and
|
|
* https://savannah.gnu.org/forum/forum.php?forum_id=9203.
|
|
*/
|
|
|
|
#include "../src/config.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <libgen.h> //dirname,basename
|
|
|
|
#include "dwg.h"
|
|
#include "../src/bits.h"
|
|
#include "../src/logging.h"
|
|
#include "../src/common.h"
|
|
#include "../src/myalloca.h"
|
|
|
|
// not needed anymore
|
|
// void *memmem (const void *big, size_t big_len, const void *little,
|
|
// size_t little_len);
|
|
|
|
#define CHAIN_SIZE 128
|
|
int cur_hdl; // to avoid dupl. search
|
|
|
|
#include "unknown.h"
|
|
|
|
static struct _unknown_dxf unknown_dxf[] = {
|
|
// see log_unknown_dxf.pl
|
|
#include "alldxf_0.inc"
|
|
{ NULL, NULL, 0, "", 0, 0, 0, 0, 0, 0, 0, NULL }
|
|
};
|
|
|
|
#include "alldxf_1.inc"
|
|
|
|
/* not needed for the solver, only to check against afterwards */
|
|
#if 0
|
|
static struct _unknown {
|
|
const char *name;
|
|
const char *log;
|
|
const char *bits;
|
|
const char *dxf;
|
|
const unsigned int handle;
|
|
const int is_entity;
|
|
const int num_bits;
|
|
const int commonsize;
|
|
const int hdloff;
|
|
const int strsize;
|
|
const int hdlsize;
|
|
const int bitsize;
|
|
} unknowns[] =
|
|
{
|
|
{ "ACAD_EVALUATION_GRAPH", "example_2000.log", 0x2E3, "40501406481013fffffffcffffffff3fffffffcffffffff980c0c80b8bee", "test/test-data/example_2000.dxf", 0, 234, 60, -60, 0, 268 },
|
|
/* the following types:
|
|
5 ACDBASSOCGEOMDEPENDENCY
|
|
3 ACDBASSOCNETWORK
|
|
53 ACDBDETAILVIEWSTYLE
|
|
53 ACDBSECTIONVIEWSTYLE
|
|
5 ACDB_LEADEROBJECTCONTEXTDATA_CLASS
|
|
63 CELLSTYLEMAP
|
|
245 MATERIAL
|
|
1 MULTILEADER
|
|
1 SUN
|
|
97 TABLESTYLE
|
|
*/
|
|
// see log_unknown.pl
|
|
# include "alldwg.inc"
|
|
|
|
{ 0, NULL, "", "", NULL, 0L, 0, 0, 0, 0, 0, 0 }
|
|
};
|
|
#endif
|
|
|
|
static struct _bd
|
|
{
|
|
const char *value;
|
|
const char *bin;
|
|
} bd[] = {
|
|
// see bd-unknown.pl
|
|
#include "bd-unknown.inc"
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
static void
|
|
bits_TV (Bit_Chain *restrict dat, struct _unknown_field *restrict g)
|
|
{
|
|
bit_write_TV (dat, (char *)g->value);
|
|
g->type = BITS_TV;
|
|
}
|
|
|
|
static void
|
|
bits_TU (Bit_Chain *restrict dat, struct _unknown_field *restrict g)
|
|
{
|
|
// the source is always utf8
|
|
BITCODE_TU wstr = bit_utf8_to_TU ((char *)g->value, 0);
|
|
bit_write_TU (dat, wstr);
|
|
g->type = BITS_TU;
|
|
free (wstr);
|
|
}
|
|
|
|
static void
|
|
bits_TF (Bit_Chain *restrict dat, struct _unknown_field *restrict g, int len)
|
|
{
|
|
bit_write_TF (dat, (BITCODE_TF)g->value, len);
|
|
g->type = BITS_TF;
|
|
}
|
|
|
|
static void
|
|
bits_string (Bit_Chain *restrict dat, struct _unknown_field *restrict g)
|
|
{
|
|
if (dat->version >= R_2007)
|
|
bits_TU (dat, g);
|
|
else
|
|
bits_TV (dat, g);
|
|
}
|
|
|
|
static void
|
|
bits_hexstring (Bit_Chain *restrict dat, struct _unknown_field *restrict g)
|
|
{
|
|
// convert hex to string
|
|
int len = strlen (g->value) / 2;
|
|
unsigned char buf[1024];
|
|
for (int i = 0; i < len; i++)
|
|
{
|
|
unsigned char *s = (unsigned char *)&g->value[i * 2];
|
|
buf[i] = ((*s < 'A') ? *s - '0' : *s + 10 - 'A') << 4;
|
|
s++;
|
|
buf[i] += (*s < 'A') ? *s - '0' : *s + 10 - 'A';
|
|
}
|
|
bit_write_TF (dat, buf, len);
|
|
g->type = BITS_TF;
|
|
}
|
|
|
|
static void
|
|
bits_B (Bit_Chain *restrict dat, struct _unknown_field *restrict g)
|
|
{
|
|
if (*g->value == '0')
|
|
{
|
|
bit_write_B (dat, 0);
|
|
g->type = BITS_B;
|
|
}
|
|
else if (*g->value == '1')
|
|
{
|
|
bit_write_B (dat, 0);
|
|
g->type = BITS_B;
|
|
}
|
|
else
|
|
{
|
|
LOG_ERROR ("Invalid B %s", g->value);
|
|
}
|
|
}
|
|
|
|
static void
|
|
bits_RD (Bit_Chain *restrict dat, struct _unknown_field *restrict g)
|
|
{
|
|
double d = strtod (g->value, NULL);
|
|
bit_write_RD (dat, d);
|
|
g->type = BITS_RD;
|
|
}
|
|
|
|
static void
|
|
bits_BD (Bit_Chain *restrict dat, struct _unknown_field *restrict g)
|
|
{
|
|
double d = strtod (g->value, NULL);
|
|
// properly found are: 0.0, 1.0, 5929.403601723592, 607.2183823688756,
|
|
// 4.0, 2.0, 0.36, 5.0, 4.131293495034893, 4701.847034571434,
|
|
// 0.5024999976158142
|
|
// hard-code some special values not properly converted and found.
|
|
if (strEQc (g->value, "0.5"))
|
|
d = 0.5;
|
|
else if (strEQc (g->value, "10.0"))
|
|
d = 10.0;
|
|
else if (strEQc (g->value, "11.0"))
|
|
d = 11.0;
|
|
else if (strEQc (g->value, "63.5"))
|
|
d = 63.5;
|
|
g->type = BITS_BD;
|
|
// some more not found BD values
|
|
for (struct _bd *b = &bd[0]; b->value; b++)
|
|
{
|
|
if (strEQ (g->value, b->value))
|
|
{
|
|
bit_write_bits (dat, b->bin);
|
|
return;
|
|
}
|
|
}
|
|
// sscanf(g->value, "%lf", &d);
|
|
bit_write_BD (dat, d);
|
|
}
|
|
|
|
static void
|
|
bits_angle_BD (Bit_Chain *restrict dat, struct _unknown_field *restrict g)
|
|
{
|
|
double d = strtod (g->value, NULL);
|
|
// sscanf(g->value, "%lf", &d);
|
|
d = deg2rad (d);
|
|
bit_write_BD (dat, d);
|
|
g->type = BITS_BD;
|
|
}
|
|
|
|
static void
|
|
bits_RC (Bit_Chain *restrict dat, struct _unknown_field *restrict g)
|
|
{
|
|
BITCODE_RC l = (BITCODE_RC)strtol (g->value, NULL, 10);
|
|
bit_write_RC (dat, l);
|
|
g->type = BITS_RC;
|
|
}
|
|
|
|
static void
|
|
bits_BS (Bit_Chain *restrict dat, struct _unknown_field *restrict g)
|
|
{
|
|
BITCODE_BS l = (BITCODE_BS)strtol (g->value, NULL, 10);
|
|
bit_write_BS (dat, l);
|
|
g->type = BITS_BS;
|
|
}
|
|
|
|
static void
|
|
bits_BL (Bit_Chain *restrict dat, struct _unknown_field *restrict g)
|
|
{
|
|
uint32_t l = (uint32_t)strtol (g->value, NULL, 10);
|
|
bit_write_BL (dat, l);
|
|
g->type = BITS_BL;
|
|
}
|
|
|
|
static void
|
|
bits_BLd (Bit_Chain *restrict dat, struct _unknown_field *restrict g)
|
|
{
|
|
int32_t l = (int32_t)strtol (g->value, NULL, 10);
|
|
bit_write_BLd (dat, l);
|
|
g->type = BITS_BLd;
|
|
}
|
|
|
|
static void
|
|
bits_RS (Bit_Chain *restrict dat, struct _unknown_field *restrict g)
|
|
{
|
|
BITCODE_RS l = (BITCODE_RS)strtol (g->value, NULL, 10);
|
|
bit_write_RS (dat, l);
|
|
g->type = BITS_RS;
|
|
}
|
|
|
|
static void
|
|
bits_RL (Bit_Chain *restrict dat, struct _unknown_field *restrict g)
|
|
{
|
|
uint32_t l = (uint32_t)strtol (g->value, NULL, 10);
|
|
bit_write_RL (dat, l);
|
|
g->type = BITS_RL;
|
|
}
|
|
|
|
static void
|
|
bits_CMC (Bit_Chain *restrict dat, struct _unknown_field *restrict g)
|
|
{
|
|
// dat should know if >= R_2004, but we just search for the index (62)
|
|
// we try ENC on entities, CMC on objects
|
|
Dwg_Color color;
|
|
memset (&color, 0, sizeof (color));
|
|
color.index = strtol (g->value, NULL, 10);
|
|
if (dat->version >= R_2004)
|
|
{
|
|
// check next g field
|
|
struct _unknown_field *ng = g + 1;
|
|
struct _unknown_field *ng2 = g + 2;
|
|
// TODO: need to detect book_name (flag 2)
|
|
if (ng->code >= 420 && ng->code < 430)
|
|
{
|
|
color.rgb = strtol (ng->value, NULL, 10);
|
|
if (ng2->code >= 430 && ng2->code < 440)
|
|
{
|
|
color.flag |= 0x1;
|
|
color.name = (char *)ng2->value;
|
|
ng2++;
|
|
}
|
|
}
|
|
}
|
|
bit_write_CMC (dat, dat, &color);
|
|
g->type = BITS_CMC;
|
|
}
|
|
|
|
// needs to know color.index (62) and color.rgb (421) at least, opt. also alpha
|
|
// (441)
|
|
static void
|
|
bits_ENC (Bit_Chain *restrict dat, struct _unknown_field *restrict g)
|
|
{
|
|
// dat should know if >= R_2004, but we just search for the index
|
|
Dwg_Color color;
|
|
memset (&color, 0, sizeof (color));
|
|
color.index = strtol (g->value, NULL, 10);
|
|
if (dat->version >= R_2004)
|
|
{
|
|
// check next g field
|
|
struct _unknown_field *ng = g + 1;
|
|
struct _unknown_field *ng2 = g + 2;
|
|
if (ng->code >= 420 && ng->code < 430)
|
|
{
|
|
color.flag = 0x80;
|
|
color.rgb = strtol (ng->value, NULL, 10);
|
|
if (ng2->code >= 430 && ng2->code < 440)
|
|
{
|
|
color.flag |= 0x1;
|
|
color.name = (char *)ng2->value;
|
|
ng2++;
|
|
if (ng2->code >= 440 && ng2->code < 450)
|
|
{
|
|
color.flag |= 0x20;
|
|
color.alpha = strtol (ng2->value, NULL, 10);
|
|
}
|
|
}
|
|
else if (ng2->code >= 440 && ng2->code < 450)
|
|
{
|
|
color.flag |= 0x20;
|
|
color.alpha = strtol (ng2->value, NULL, 10);
|
|
}
|
|
}
|
|
else if (ng->code >= 440 && ng->code < 450)
|
|
{
|
|
color.flag = 0x20;
|
|
color.alpha = strtol (ng->value, NULL, 10);
|
|
}
|
|
}
|
|
bit_write_ENC (dat, dat, dat, &color);
|
|
g->type = BITS_ENC;
|
|
}
|
|
|
|
static void
|
|
handle_string (char *restrict dest, const int code, const char *restrict hdl,
|
|
const long relhandle)
|
|
{
|
|
Dwg_Handle handle;
|
|
// parse hex -> owner handle;
|
|
sscanf (hdl, "%lX", &handle.value);
|
|
handle.code = code;
|
|
if (code > 5)
|
|
{ // relative offset to objhandle
|
|
switch (code)
|
|
{
|
|
case 6:
|
|
handle.value = 0;
|
|
break;
|
|
case 8:
|
|
handle.value = 0;
|
|
break;
|
|
case 0xA:
|
|
handle.value -= relhandle;
|
|
break;
|
|
case 0xC:
|
|
handle.value = relhandle - handle.value;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if (handle.value == 0)
|
|
handle.size = 0;
|
|
else if (handle.value < 0xff)
|
|
handle.size = 1;
|
|
else if (handle.value < 0xffff)
|
|
handle.size = 2;
|
|
else if (handle.value < 0xffffff)
|
|
handle.size = 3;
|
|
else
|
|
handle.size = 4;
|
|
sprintf (dest, FORMAT_H, ARGS_H (handle));
|
|
}
|
|
|
|
static void
|
|
bits_handle (Bit_Chain *restrict dat, struct _unknown_field *restrict g,
|
|
int code, unsigned int objhandle)
|
|
{
|
|
Dwg_Handle handle;
|
|
// parse hex -> owner handle;
|
|
sscanf (g->value, "%lX", &handle.value);
|
|
handle.code = code;
|
|
cur_hdl = code;
|
|
if (code > 5)
|
|
{ // relative offset to objhandle
|
|
switch (code)
|
|
{
|
|
case 6:
|
|
handle.value = 0;
|
|
break;
|
|
case 8:
|
|
handle.value = 0;
|
|
break;
|
|
case 0xA:
|
|
handle.value -= objhandle;
|
|
break;
|
|
case 0xC:
|
|
handle.value = objhandle - handle.value;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if (handle.value == 0)
|
|
handle.size = 0;
|
|
else if (handle.value < 0xff)
|
|
handle.size = 1;
|
|
else if (handle.value < 0xffff)
|
|
handle.size = 2;
|
|
else if (handle.value < 0xffffff)
|
|
handle.size = 3;
|
|
else
|
|
handle.size = 4;
|
|
printf (" handle " FORMAT_H " (%X)\n", ARGS_H (handle), objhandle);
|
|
bit_write_H (dat, &handle);
|
|
g->type = BITS_HANDLE;
|
|
}
|
|
|
|
static int
|
|
is_handle (int code)
|
|
{
|
|
return code == 5 || code == 105 || (code >= 320 && code <= 369)
|
|
|| (code >= 390 && code <= 399) || (code >= 480 && code <= 481);
|
|
}
|
|
|
|
static void
|
|
bits_try_handle (struct _unknown_field *g, int code, unsigned int objhandle)
|
|
{
|
|
Bit_Chain dat = EMPTY_CHAIN (CHAIN_SIZE);
|
|
dat.chain = calloc (1, CHAIN_SIZE);
|
|
|
|
bits_handle (&dat, g, code, objhandle);
|
|
|
|
g->bytes = dat.chain;
|
|
g->num_bits = (dat.byte * 8) + dat.bit;
|
|
}
|
|
|
|
static int
|
|
dxf_is16 (struct _unknown_dxf *dxf)
|
|
{
|
|
return strstr (dxf->dxf, "/2007/") || strstr (dxf->dxf, "_2007.dxf")
|
|
|| strstr (dxf->dxf, "/201") || strstr (dxf->dxf, "_201")
|
|
? 1
|
|
: 0;
|
|
}
|
|
|
|
static void
|
|
bits_format (struct _unknown_field *g, const int version,
|
|
struct _unknown_dxf *dxf)
|
|
{
|
|
int code = g->code;
|
|
Bit_Chain dat = EMPTY_CHAIN (CHAIN_SIZE);
|
|
const int is16 = version >= 2007 ? 1 : 0;
|
|
|
|
dat.chain = calloc (1, CHAIN_SIZE);
|
|
if (version)
|
|
{
|
|
char s[16];
|
|
sprintf (s, "r%d", version);
|
|
dat.version = dwg_version_as (s);
|
|
}
|
|
|
|
if (0 <= code && code < 5)
|
|
bits_string (&dat, g);
|
|
else if (code == 5 || code == -5)
|
|
bits_handle (&dat, g, 0, 0);
|
|
else if (5 < code && code < 10)
|
|
// 6 ltype handle or BS index, 7 style handle, 8 layer handle
|
|
bits_string (&dat, g);
|
|
else if (code < 50)
|
|
bits_BD (&dat, g);
|
|
else if (code < 60)
|
|
bits_angle_BD (&dat, g); // deg2rad for angles
|
|
else if (code < 70)
|
|
{
|
|
if (dat.version >= R_2004 && dxf->is_entity)
|
|
bits_ENC (&dat, g);
|
|
else
|
|
bits_CMC (&dat, g);
|
|
}
|
|
else if (code < 80)
|
|
if (code == 75 && strEQc (g->name, "ref.has_lastpt_ref"))
|
|
bits_B (&dat, g);
|
|
else
|
|
bits_BS (&dat, g);
|
|
else if (80 <= code && code <= 99) // BL int32
|
|
bits_BL (&dat, g);
|
|
else if (code == 100)
|
|
return;
|
|
else if (code == 102) // this is never stored in a DWG
|
|
bits_string (&dat, g);
|
|
else if (code == 105)
|
|
bits_handle (&dat, g, 3, 0);
|
|
else if (110 <= code && code <= 149)
|
|
bits_BD (&dat, g);
|
|
else if (160 <= code && code <= 169)
|
|
bits_BL (&dat, g);
|
|
else if (code <= 179)
|
|
bits_BS (&dat, g);
|
|
else if (210 <= code && code <= 239)
|
|
bits_BD (&dat, g);
|
|
else if (270 <= code && code <= 289)
|
|
bits_BS (&dat, g);
|
|
else if (code <= 299)
|
|
bits_B (&dat, g);
|
|
else if (code <= 309)
|
|
bits_string (&dat, g);
|
|
else if (code <= 319)
|
|
bits_hexstring (&dat, g);
|
|
else if (code >= 320 && code < 360)
|
|
bits_handle (&dat, g, 4, 0); // 2 or 4 or 3.0
|
|
else if (code >= 340 && code < 360)
|
|
bits_handle (&dat, g, 5, 0);
|
|
else if (code >= 360 && code <= 369)
|
|
bits_handle (&dat, g, 3, 0);
|
|
else if (code <= 389)
|
|
bits_BS (&dat, g);
|
|
else if (code <= 399)
|
|
bits_handle (&dat, g, 5, 0);
|
|
else if (code <= 409)
|
|
bits_BS (&dat, g);
|
|
else if (code <= 419)
|
|
bits_string (&dat, g);
|
|
else if (code <= 429)
|
|
bits_BLd (&dat, g); // int32_t. ignore if after color
|
|
else if (code <= 439)
|
|
bits_string (&dat, g); // ignore if after color
|
|
else if (code <= 449)
|
|
bits_BLd (&dat, g); // int32_t. ignore if after color
|
|
else if (code <= 459)
|
|
bits_BL (&dat, g); // long
|
|
else if (code <= 469)
|
|
bits_BD (&dat, g);
|
|
else if (code <= 479)
|
|
bits_string (&dat, g);
|
|
else if (code <= 481)
|
|
bits_handle (&dat, g, 5, 0);
|
|
else if (code == 999)
|
|
;
|
|
else if (1000 <= code && code <= 1009)
|
|
bits_string (&dat, g);
|
|
else if (1010 <= code && code <= 1049)
|
|
bits_BD (&dat, g);
|
|
else if (1050 <= code && code <= 1059)
|
|
bits_angle_BD (&dat, g);
|
|
else if (1060 <= code && code <= 1070)
|
|
bits_BS (&dat, g);
|
|
else if (code == 1071)
|
|
bits_BL (&dat, g); // int32_t
|
|
else
|
|
fprintf (stderr, "Unknown DXF code %d\n", code);
|
|
|
|
if (g->type)
|
|
{
|
|
g->bytes = dat.chain;
|
|
g->num_bits = (dat.byte * 8) + dat.bit;
|
|
}
|
|
else
|
|
{
|
|
free (dat.chain);
|
|
dat.chain = NULL;
|
|
}
|
|
}
|
|
|
|
// check how many of the given fields (code=value pairs) exist in the DXF
|
|
#if 0
|
|
static int
|
|
num_dxf (const struct _unknown_field *g, const struct _unknown_dxf *dxf) {
|
|
int num_dxf = 0;
|
|
struct _unknown_field *f = (struct _unknown_field *)dxf->fields;
|
|
while (f->value) {
|
|
if (f->code == g->code && strEQ (f->value, g->value))
|
|
num_dxf++;
|
|
f++;
|
|
}
|
|
return num_dxf;
|
|
}
|
|
#endif
|
|
|
|
static int
|
|
is_common_entity_data (int dxf)
|
|
{
|
|
return dxf == 8 || dxf == 440 || dxf == 420 || dxf == 430 || dxf == 48
|
|
|| dxf == 284 || dxf == 370;
|
|
}
|
|
|
|
static int
|
|
set_found (struct _dxf *dxf, const struct _unknown_field *g)
|
|
{
|
|
// check for overlap, if already found by some other field
|
|
int overlap = 0;
|
|
if (g->num_bits + g->pos[0] > dxf->num_bits)
|
|
{
|
|
fprintf (stderr, "overflow with found group %d %s: %d+%d >= %d\n",
|
|
g->code, g->name, g->num_bits, g->pos[0], dxf->num_bits);
|
|
return 1;
|
|
}
|
|
for (int k = g->pos[0]; k < g->num_bits + g->pos[0]; k++)
|
|
{
|
|
if (dxf->found[k] && !overlap && k < g->num_bits)
|
|
{
|
|
overlap = 1;
|
|
printf ("position %d already found\n", k);
|
|
}
|
|
dxf->found[k]++;
|
|
}
|
|
return overlap;
|
|
}
|
|
|
|
static int
|
|
set_found_i (struct _dxf *dxf, const struct _unknown_field *g, int i)
|
|
{
|
|
// check for overlap, if already found by some other field
|
|
int overlap = 0;
|
|
if (g->num_bits + g->pos[i] > dxf->num_bits)
|
|
{
|
|
fprintf (stderr, "overflow with found group %d %s: %d+%d >= %d\n",
|
|
g->code, g->name, g->num_bits, g->pos[i], dxf->num_bits);
|
|
return 1;
|
|
}
|
|
for (int k = g->pos[i]; k < g->num_bits + g->pos[i]; k++)
|
|
{
|
|
if (dxf->found[k] && !overlap)
|
|
{
|
|
overlap = 1;
|
|
printf ("field %d %s already found at %d\n", g->code, g->name, k);
|
|
}
|
|
dxf->found[k]++;
|
|
}
|
|
return overlap;
|
|
}
|
|
|
|
static void
|
|
set_possible_pos (struct _dxf *dxf, const struct _unknown_field *g,
|
|
const int pos)
|
|
{
|
|
// add coverage counter for each bit
|
|
if (g->num_bits + pos > dxf->num_bits)
|
|
{
|
|
fprintf (stderr, "overflow with possible group %d %s: %d+%d >= %d\n",
|
|
g->code, g->name, g->num_bits, pos, dxf->num_bits);
|
|
return;
|
|
}
|
|
for (int k = pos; k < g->num_bits + pos; k++)
|
|
{
|
|
dxf->possible[k]++;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
static void
|
|
set_possible(struct _dxf *dxf, const struct _unknown_field *g, const int i)
|
|
{
|
|
// add coverage counter for each bit
|
|
for (int j=0; j<i; j++) {
|
|
for (int k=g->pos[j]; k < g->num_bits + g->pos[j]; k++) {
|
|
dxf->possible[k]++;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// The i-th bit of a string. See bit_read_B()
|
|
// 0x1: 10000000,0 >> 8 = 1
|
|
#define BIT(b, i) (((b)[(i) / 8] & (0x80 >> (i) % 8)) >> (7 - (i) % 8))
|
|
//#define BIT(b,i) (((b)[(i)/8] >> (8-((i)%8))) & 1)
|
|
|
|
// like memmem but for bits, not bytes.
|
|
// search for the bits of small in big. returns the bit offset in big or -1.
|
|
// handle bits before and after.
|
|
static int
|
|
membits (const unsigned char *restrict big, const int bigsize,
|
|
const unsigned char *restrict small, const int smallsize, int offset)
|
|
{
|
|
int pos = offset;
|
|
if (smallsize > bigsize)
|
|
return -1;
|
|
while (pos + smallsize < bigsize)
|
|
{
|
|
int i = 0;
|
|
while (i < smallsize)
|
|
{
|
|
if (BIT (big, pos + i) != BIT (small, i))
|
|
break;
|
|
i++; // found, check next bit
|
|
}
|
|
if (i == smallsize) // found all smallsize bits
|
|
return pos;
|
|
pos++;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static int
|
|
search_bits (int j, struct _unknown_field *g, struct _unknown_dxf *udxf,
|
|
struct _dxf *dxf, int offset)
|
|
{
|
|
int size;
|
|
unsigned char *s;
|
|
unsigned char *found;
|
|
int num_found = 0;
|
|
int dxf_num_bits = udxf->num_bits;
|
|
int dxf_size = dxf_num_bits / 8;
|
|
|
|
if (!g->type || !g->num_bits || !dxf_size)
|
|
return 0;
|
|
size = (g->num_bits / 8) + (g->num_bits % 8 ? 1 : 0);
|
|
dxf_size += (dxf_size % 8 ? 1 : 0);
|
|
if (size > dxf_size)
|
|
return 0;
|
|
s = alloca (size);
|
|
printf (" search %d bits of type %s [%d] in %d:%d ", g->num_bits,
|
|
dwg_bits_name[g->type], j, dxf_num_bits - offset, offset);
|
|
bit_print_bits (g->bytes, g->num_bits);
|
|
while ((offset = membits ((unsigned char *)udxf->bytes, udxf->num_bits,
|
|
g->bytes, g->num_bits, offset))
|
|
!= -1)
|
|
{
|
|
if (num_found < 5) // record only the first 5 offsets for the solver
|
|
g->pos[num_found] = offset;
|
|
num_found++;
|
|
set_possible_pos (
|
|
dxf, g, offset); // but record all other offsets here as counts 0-255
|
|
// if (num_found > 5)
|
|
// break;
|
|
offset++;
|
|
}
|
|
freea (s);
|
|
return num_found;
|
|
}
|
|
|
|
/* Not the same as json_cquote. This is only for C */
|
|
static char *
|
|
cquote (char *restrict dest, const char *restrict src)
|
|
{
|
|
char c;
|
|
char *d = dest;
|
|
char *s = (char *)src;
|
|
while ((c = *s++))
|
|
{
|
|
if (c == '"')
|
|
{
|
|
*dest++ = '\\';
|
|
*dest++ = c;
|
|
}
|
|
else if (c == '\\')
|
|
{
|
|
*dest++ = '\\';
|
|
*dest++ = c;
|
|
}
|
|
else
|
|
*dest++ = c;
|
|
}
|
|
*dest = 0; // add final delim, skipped above
|
|
return d;
|
|
}
|
|
|
|
static void
|
|
pi_filename (char *restrict pi_fn, uint16_t i)
|
|
{
|
|
if (i)
|
|
{
|
|
char tmp[36];
|
|
snprintf (tmp, 35, ".%hu", i);
|
|
tmp[35] = '\0';
|
|
strcat (pi_fn, tmp);
|
|
}
|
|
strcat (pi_fn, ".pi");
|
|
}
|
|
|
|
static int
|
|
open_pi (FILE *pi, char *restrict class, char *pi_fn)
|
|
{
|
|
if (!pi)
|
|
{
|
|
fprintf (stderr, "Failed to write %s\n", pi_fn);
|
|
return 1;
|
|
}
|
|
fprintf (pi,
|
|
"import unknown.\n\n"
|
|
"/* %s field packing problem.\n"
|
|
" examples/unknown generated example, needs picat-lang.org.\n"
|
|
" Usage: picat [-g go2] %s\n"
|
|
"*/\n",
|
|
class, pi_fn);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
close_pi (FILE *pi, long class_filled, long class_size, int k)
|
|
{
|
|
int i;
|
|
// class_summary
|
|
fprintf (pi, "\n%% summary: %ld/%ld=%.1f%%\n\n", class_filled, class_size,
|
|
100.0 * class_filled / class_size);
|
|
|
|
for (i = 0; i < k; i++)
|
|
{
|
|
fprintf (pi, "go%d ?=> def(%d,Data).\n", i, i);
|
|
}
|
|
fprintf (pi, "\nmain => go0%s\n", k == 1 ? "." : ",");
|
|
for (i = 1; i < k; i++)
|
|
{
|
|
fprintf (pi, " go%d%s\n", i, i == k - 1 ? "." : ",");
|
|
}
|
|
fclose (pi);
|
|
}
|
|
|
|
int
|
|
main (int argc, char *argv[])
|
|
{
|
|
unsigned i = 1, ic, j, num_classes = 0;
|
|
unsigned long sum_filled = 0, sum_size = 0;
|
|
char *class = NULL;
|
|
char *file = NULL;
|
|
#define MAX_CLASSES 200
|
|
char *classes[MAX_CLASSES]; // create files per classes
|
|
struct _dxf *dxf = calloc (sizeof (unknown_dxf) / sizeof (unknown_dxf[0]),
|
|
sizeof (struct _dxf));
|
|
// clang-format off
|
|
#include "alldxf_2.inc"
|
|
// clang-format on
|
|
|
|
if (argc > 2 && strEQc (argv[i], "--class"))
|
|
{
|
|
class = argv[i + 1];
|
|
i = 3;
|
|
}
|
|
if (argc - i >= 2 && strEQc (argv[i], "--file"))
|
|
file = argv[i + 1];
|
|
// process per class, not per logged instances.
|
|
if (!class)
|
|
{
|
|
num_classes = 0;
|
|
for (i = 0; unknown_dxf[i].name; i++)
|
|
{ // TODO: alldwg/alldxf needs to be sorted per class, not file.
|
|
if (!class || !strEQ (class, unknown_dxf[i].name))
|
|
{
|
|
classes[num_classes++] = (char *)unknown_dxf[i].name;
|
|
class = (char *)unknown_dxf[i].name;
|
|
if (num_classes >= MAX_CLASSES)
|
|
{
|
|
fprintf (stderr, "Too many classes: %d (unsorted?)\n",
|
|
MAX_CLASSES);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
num_classes = 1;
|
|
classes[0] = class;
|
|
}
|
|
for (ic = 0; ic < num_classes; ic++)
|
|
{
|
|
FILE *pi;
|
|
char pi_fn[256];
|
|
char base_pi_fn[256];
|
|
int k = 0;
|
|
long class_filled = 0, class_size = 0;
|
|
char *dn;
|
|
uint16_t i_pi = 0;
|
|
|
|
class = classes[ic];
|
|
// dirname should be examples, but can also be examples/.libs
|
|
dn = dirname (argv[0]);
|
|
printf ("dirname(%s): %s\n", argv[0], dn);
|
|
if (dn && strstr (dn, "/examples/.libs"))
|
|
{
|
|
size_t l = strlen (dn);
|
|
strcpy (pi_fn, dn);
|
|
pi_fn[l - 5] = '\0';
|
|
}
|
|
else if (dn && strEQc (basename (dn), "examples"))
|
|
{
|
|
strcpy (pi_fn, dn);
|
|
strcat (pi_fn, "/");
|
|
}
|
|
else if (strEQc (argv[0], "examples"))
|
|
{
|
|
strcpy (pi_fn, "examples/");
|
|
}
|
|
else
|
|
strcpy (pi_fn, "");
|
|
strcat (pi_fn, class);
|
|
strcpy (base_pi_fn, pi_fn);
|
|
pi_filename (pi_fn, i_pi);
|
|
pi = fopen (pi_fn, "w");
|
|
if (open_pi (pi, class, pi_fn))
|
|
continue;
|
|
for (i = 0; unknown_dxf[i].name; i++)
|
|
{
|
|
unsigned num_fields;
|
|
unsigned num_found = -1;
|
|
unsigned size = unknown_dxf[i].num_bits;
|
|
struct _unknown_field *g
|
|
= (struct _unknown_field *)unknown_dxf[i].fields;
|
|
const int is16 = dxf_is16 (&unknown_dxf[i]);
|
|
int have_struct = 0;
|
|
int is_dict = 0;
|
|
int is_react = 0;
|
|
int version = 0;
|
|
char *s;
|
|
|
|
if (class && !strEQ (class, unknown_dxf[i].name))
|
|
continue;
|
|
if (file && !strEQ (file, unknown_dxf[i].dxf))
|
|
continue;
|
|
/*if (strEQc (unknown_dxf[i].name, "TABLEGEOMETRY")) {
|
|
printf("skip TABLEGEOMETRY\n");
|
|
continue;
|
|
}*/
|
|
s = strstr (unknown_dxf[i].dxf, "20");
|
|
if (s)
|
|
sscanf (s, "%d", &version);
|
|
else
|
|
{
|
|
s = strstr (unknown_dxf[i].dxf, "_r");
|
|
if (s)
|
|
sscanf (s + 2, "%d", &version);
|
|
}
|
|
dxf[i].found = calloc (1, unknown_dxf[i].num_bits + 1);
|
|
dxf[i].possible = calloc (1, unknown_dxf[i].num_bits + 1);
|
|
dxf[i].num_bits = unknown_dxf[i].num_bits + 1;
|
|
// TODO offline: find the shortest objects.
|
|
printf ("\n%s: 0x%X (%d) %s\n", unknown_dxf[i].name,
|
|
unknown_dxf[i].handle, size, unknown_dxf[i].dxf);
|
|
printf (" =bits:\n");
|
|
bit_print_bits ((unsigned char *)unknown_dxf[i].bytes, size);
|
|
fprintf (pi,
|
|
"def(%d, Data) =>\n"
|
|
" println(\"%s: 0x%X (%d) %s:\"),\n"
|
|
" Class=\"%s\",\n"
|
|
" Dxf=\"%s\",\n"
|
|
" Version=%d,\n"
|
|
" Offsets=[%d, %d, %d, %d, %d], %% hdloff, strsize, "
|
|
"commonsize, bitsize, hdlsize\n",
|
|
k, class, unknown_dxf[i].handle, size, unknown_dxf[i].dxf,
|
|
class, unknown_dxf[i].dxf, version, unknown_dxf[i].hdloff,
|
|
unknown_dxf[i].strsize, unknown_dxf[i].commonsize,
|
|
unknown_dxf[i].bitsize, unknown_dxf[i].hdlsize);
|
|
fprintf (pi, " S=\"");
|
|
bit_fprint_bits (pi, (unsigned char *)unknown_dxf[i].bytes, size);
|
|
fprintf (pi, "\",\n"
|
|
" %% name: [1] bits, [2] value, [3] poslist, [4] "
|
|
"fieldname, [5] dxfcode\n"
|
|
" Fields = [\n");
|
|
for (j = 0; g[j].code; j++)
|
|
{
|
|
char *piname;
|
|
int offset = 0;
|
|
printf ("%d: %s\n", g[j].code, g[j].value);
|
|
if (g[j].code == 102)
|
|
{
|
|
if (strEQc (g[j].value, "{ACAD_XDICTIONARY"))
|
|
is_dict = 1;
|
|
else if (strEQc (g[j].value, "{ACAD_REACTORS"))
|
|
is_react = 1;
|
|
else if (strEQc (g[j].value, "}"))
|
|
{
|
|
is_react = 0;
|
|
is_dict = 0;
|
|
}
|
|
continue;
|
|
}
|
|
if (g[j].code == 100 || g[j].code >= 1000)
|
|
{
|
|
continue;
|
|
}
|
|
// if we came here from continue, i.e. not_found
|
|
// store the binary repr
|
|
bits_format (&g[j], version, &unknown_dxf[i]);
|
|
SEARCH:
|
|
// searching for it in the stream and store found position if
|
|
// found only once
|
|
num_found
|
|
= search_bits (j, &g[j], &unknown_dxf[i], &dxf[i], offset);
|
|
if (!num_found)
|
|
{
|
|
|
|
// try alternate formats than the standard one from
|
|
// bits_format:
|
|
int code = g[j].code;
|
|
if (is_handle (code) && code != 5)
|
|
{
|
|
int handles[] = { 2, 3, 4, 5, 6, 8, 0xa, 0xc };
|
|
unsigned int hdl;
|
|
int cur_code = cur_hdl;
|
|
sscanf (g[j].value, "%X", &hdl);
|
|
// for 330 start with 6 (relative reactors)
|
|
for (int c = code == 330 ? 4 : 0; c < 8; c++)
|
|
{
|
|
if (handles[c] == cur_code)
|
|
continue;
|
|
if (handles[c] == 6
|
|
&& hdl != unknown_dxf[i].handle + 1) //+1
|
|
continue;
|
|
if (handles[c] == 8
|
|
&& hdl != unknown_dxf[i].handle - 1) //-1
|
|
continue;
|
|
if (handles[c] == 0xa
|
|
&& hdl < unknown_dxf[i].handle) //>
|
|
continue;
|
|
if (handles[c] == 0xc
|
|
&& hdl > unknown_dxf[i].handle) //<
|
|
continue;
|
|
bits_try_handle (&g[j], handles[c],
|
|
unknown_dxf[i].handle);
|
|
num_found = search_bits (j, &g[j], &unknown_dxf[i],
|
|
&dxf[i], offset);
|
|
if (num_found)
|
|
{ // cur_hdl is set
|
|
// sprintf(&g[j].value, "%x..%X", handles[c],
|
|
// hdl);
|
|
goto FOUND;
|
|
}
|
|
}
|
|
}
|
|
if (g[j].type == BITS_ENC)
|
|
{
|
|
Bit_Chain dat = EMPTY_CHAIN (CHAIN_SIZE);
|
|
dat.chain = calloc (1, CHAIN_SIZE);
|
|
|
|
bits_CMC (&dat, &g[j]);
|
|
g[j].bytes = dat.chain;
|
|
g[j].num_bits = (dat.byte * 8) + dat.bit;
|
|
num_found = search_bits (j, &g[j], &unknown_dxf[i],
|
|
&dxf[i], offset);
|
|
if (num_found)
|
|
goto FOUND;
|
|
}
|
|
if (g[j].type == BITS_BS && strlen (g[j].value) < 3)
|
|
{
|
|
Bit_Chain dat = EMPTY_CHAIN (CHAIN_SIZE);
|
|
dat.chain = calloc (1, CHAIN_SIZE);
|
|
|
|
bits_RC (&dat, &g[j]);
|
|
g[j].bytes = dat.chain;
|
|
g[j].num_bits = (dat.byte * 8) + dat.bit;
|
|
num_found = search_bits (j, &g[j], &unknown_dxf[i],
|
|
&dxf[i], offset);
|
|
if (num_found)
|
|
goto FOUND;
|
|
}
|
|
if (g[j].type == BITS_BS)
|
|
{
|
|
Bit_Chain dat = EMPTY_CHAIN (CHAIN_SIZE);
|
|
dat.chain = calloc (1, CHAIN_SIZE);
|
|
|
|
bits_BL (&dat, &g[j]);
|
|
g[j].bytes = dat.chain;
|
|
g[j].num_bits = (dat.byte * 8) + dat.bit;
|
|
num_found = search_bits (j, &g[j], &unknown_dxf[i],
|
|
&dxf[i], offset);
|
|
if (num_found)
|
|
goto FOUND;
|
|
|
|
bit_set_position (&dat, 0);
|
|
bits_RS (&dat, &g[j]);
|
|
g[j].bytes = dat.chain;
|
|
g[j].num_bits = (dat.byte * 8) + dat.bit;
|
|
num_found = search_bits (j, &g[j], &unknown_dxf[i],
|
|
&dxf[i], offset);
|
|
if (num_found)
|
|
goto FOUND;
|
|
}
|
|
if ((g[j].type == BITS_BL || g[j].type == BITS_BLd)
|
|
&& strlen (g[j].value) <= 5)
|
|
{
|
|
Bit_Chain dat = EMPTY_CHAIN (CHAIN_SIZE);
|
|
dat.chain = calloc (1, CHAIN_SIZE);
|
|
|
|
bits_BS (&dat, &g[j]);
|
|
g[j].bytes = dat.chain;
|
|
g[j].num_bits = (dat.byte * 8) + dat.bit;
|
|
num_found = search_bits (j, &g[j], &unknown_dxf[i],
|
|
&dxf[i], offset);
|
|
if (num_found)
|
|
goto FOUND;
|
|
|
|
bit_set_position (&dat, 0);
|
|
bits_RL (&dat, &g[j]);
|
|
g[j].bytes = dat.chain;
|
|
g[j].num_bits = (dat.byte * 8) + dat.bit;
|
|
num_found = search_bits (j, &g[j], &unknown_dxf[i],
|
|
&dxf[i], offset);
|
|
if (num_found)
|
|
goto FOUND;
|
|
}
|
|
if (g[j].type == BITS_RC)
|
|
{
|
|
Bit_Chain dat = EMPTY_CHAIN (CHAIN_SIZE);
|
|
dat.chain = calloc (1, CHAIN_SIZE);
|
|
|
|
bits_BS (&dat, &g[j]);
|
|
g[j].bytes = dat.chain;
|
|
g[j].num_bits = (dat.byte * 8) + dat.bit;
|
|
num_found = search_bits (j, &g[j], &unknown_dxf[i],
|
|
&dxf[i], offset);
|
|
if (num_found)
|
|
goto FOUND;
|
|
}
|
|
if (g[j].type == BITS_BD)
|
|
{
|
|
Bit_Chain dat = EMPTY_CHAIN (CHAIN_SIZE);
|
|
dat.chain = calloc (1, CHAIN_SIZE);
|
|
|
|
bits_RD (&dat, &g[j]);
|
|
g[j].bytes = dat.chain;
|
|
g[j].num_bits = (dat.byte * 8) + dat.bit;
|
|
num_found = search_bits (j, &g[j], &unknown_dxf[i],
|
|
&dxf[i], offset);
|
|
if (num_found)
|
|
goto FOUND;
|
|
}
|
|
// relaxed BD search, less mantissa precision.
|
|
// e.g. 49:"0.0008202099737533" (66 bits of type BD)
|
|
// 52 -> 44 bit
|
|
if (g[j].type == BITS_RD && strlen (g[j].value) >= 3)
|
|
{
|
|
double d;
|
|
Bit_Chain dat = EMPTY_CHAIN (CHAIN_SIZE);
|
|
dat.chain = calloc (1, CHAIN_SIZE);
|
|
|
|
bits_BD (&dat, &g[j]); // g.value -> dat
|
|
g[j].bytes = dat.chain;
|
|
|
|
if (dat.byte == 8)
|
|
g[j].num_bits = 58; // from 66
|
|
else
|
|
goto FOUND;
|
|
// print rounded found value and show bit diff
|
|
printf (
|
|
" imprecise BD search, 42bit mantissa precision\n");
|
|
num_found = search_bits (j, &g[j], &unknown_dxf[i],
|
|
&dxf[i], offset);
|
|
if (num_found)
|
|
{
|
|
free (dat.chain);
|
|
dat.chain = (unsigned char *)unknown_dxf[i].bytes;
|
|
g[j].bytes = dat.chain;
|
|
dat.size = unknown_dxf[i].num_bits / 8;
|
|
bit_set_position (&dat, g[j].pos[0]);
|
|
d = bit_read_BD (&dat);
|
|
if (fabs (d - strtod (g[j].value, NULL)) < 0.001)
|
|
{
|
|
printf (" found imprecise %f value (42bit)\n",
|
|
d);
|
|
goto FOUND;
|
|
}
|
|
else
|
|
{
|
|
printf (" result too imprecise %f (42bit)\n",
|
|
d);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
g[j].num_bits = 54; // from 66
|
|
// printf(" more imprecise BD search, 38bit mantissa
|
|
// precision\n");
|
|
num_found = search_bits (j, &g[j], &unknown_dxf[i],
|
|
&dxf[i], offset);
|
|
if (num_found)
|
|
{
|
|
free (dat.chain);
|
|
dat.chain
|
|
= (unsigned char *)unknown_dxf[i].bytes;
|
|
g[j].bytes = dat.chain;
|
|
dat.size = unknown_dxf[i].num_bits / 8;
|
|
bit_set_position (&dat, g[j].pos[0]);
|
|
d = bit_read_BD (&dat);
|
|
if (fabs (d - strtod (g[j].value, NULL)) < 0.001)
|
|
{
|
|
printf (" found imprecise BD %f value "
|
|
"(38bit)\n",
|
|
d);
|
|
goto FOUND;
|
|
}
|
|
else
|
|
{
|
|
printf (
|
|
" result too imprecise BD (38bit)\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// ditto relaxed RD search, without the BB prefix
|
|
if (g[j].type == BITS_RD && strlen (g[j].value) >= 3)
|
|
{
|
|
double d;
|
|
Bit_Chain dat = EMPTY_CHAIN (CHAIN_SIZE);
|
|
dat.chain = calloc (1, CHAIN_SIZE);
|
|
|
|
bits_RD (&dat, &g[j]); // g.value -> dat
|
|
g[j].bytes = dat.chain;
|
|
|
|
if (dat.byte == 8)
|
|
g[j].num_bits = 56; // from 64
|
|
else
|
|
goto FOUND;
|
|
// print rounded found value and show bit diff
|
|
printf (
|
|
" imprecise RD search, 42bit mantissa precision\n");
|
|
num_found = search_bits (j, &g[j], &unknown_dxf[i],
|
|
&dxf[i], offset);
|
|
if (num_found)
|
|
{
|
|
free (dat.chain);
|
|
dat.chain = (unsigned char *)unknown_dxf[i].bytes;
|
|
dat.size = unknown_dxf[i].num_bits / 8;
|
|
bit_set_position (&dat, g[j].pos[0]);
|
|
d = bit_read_BD (&dat);
|
|
if (fabs (d - strtod (g[j].value, NULL)) < 0.001)
|
|
{
|
|
printf (
|
|
" found imprecise RD %f value (42bit)\n",
|
|
d);
|
|
goto FOUND;
|
|
}
|
|
else
|
|
{
|
|
printf (" result too imprecise RD %f (42bit)\n",
|
|
d);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
g[j].num_bits = 52; // from 64
|
|
// printf(" more imprecise RD search, 38bit mantissa
|
|
// precision\n");
|
|
num_found = search_bits (j, &g[j], &unknown_dxf[i],
|
|
&dxf[i], offset);
|
|
if (num_found)
|
|
{
|
|
free (dat.chain);
|
|
dat.chain
|
|
= (unsigned char *)unknown_dxf[i].bytes;
|
|
dat.size = unknown_dxf[i].num_bits / 8;
|
|
bit_set_position (&dat, g[j].pos[0]);
|
|
d = bit_read_BD (&dat);
|
|
if (fabs (d - strtod (g[j].value, NULL)) < 0.001)
|
|
{
|
|
printf (" found imprecise RD %f value "
|
|
"(38bit)\n",
|
|
d);
|
|
goto FOUND;
|
|
}
|
|
else
|
|
{
|
|
printf (
|
|
" result too imprecise RD %f (38bit)\n",
|
|
d);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// TU not found, try TV (unsuccessful) or TF (wrong len?)
|
|
// the length usually includes the final \0
|
|
if (g[j].type == BITS_TV || g[j].type == BITS_TU)
|
|
{
|
|
Bit_Chain dat = EMPTY_CHAIN (CHAIN_SIZE);
|
|
int len = strlen (g[j].value);
|
|
dat.chain = calloc (1, CHAIN_SIZE);
|
|
|
|
#if 0
|
|
/* TU/TF cannot be mixed */
|
|
if (is16)
|
|
{
|
|
bits_TV (&dat, &g[j]);
|
|
|
|
g[j].bytes = dat.chain;
|
|
g[j].num_bits = (dat.byte * 8) + dat.bit;
|
|
num_found = search_bits (j, &g[j], &unknown_dxf[i],
|
|
&dxf[i], offset);
|
|
if (num_found)
|
|
goto FOUND;
|
|
}
|
|
#endif
|
|
if (len)
|
|
{
|
|
bit_set_position (&dat, 0);
|
|
// search without the final \0
|
|
bits_TF (&dat, &g[j], len);
|
|
|
|
g[j].bytes = dat.chain;
|
|
g[j].num_bits = (dat.byte * 8) + dat.bit;
|
|
num_found = search_bits (j, &g[j], &unknown_dxf[i],
|
|
&dxf[i], offset);
|
|
if (num_found)
|
|
goto FOUND;
|
|
}
|
|
}
|
|
|
|
if (!num_found || is_common_entity_data (g[j].code))
|
|
{
|
|
piname = (char *)dwg_bits_name[g[j].type];
|
|
if (strEQc (piname, "HANDLE"))
|
|
piname = (char *)"H";
|
|
// unfound DXF field for the picat file.
|
|
// later could be used as hints for the picat solver
|
|
fprintf (pi, " %%new_struct('_%s%d', [\"", piname,
|
|
g[j].code);
|
|
bit_fprint_bits (pi, g[j].bytes, g[j].num_bits);
|
|
if (g[j].type == BITS_HANDLE)
|
|
{
|
|
char buf[32];
|
|
handle_string (buf, cur_hdl, g[j].value,
|
|
unknown_dxf[i].handle);
|
|
fprintf (pi, "\", '%s', [], \"%s\", %d])\n", buf,
|
|
g[j].name, g[j].code);
|
|
}
|
|
else if ((g[j].type == BITS_TV || g[j].type == BITS_TU
|
|
|| g[j].type == BITS_TF)
|
|
&& strchr (g[j].value, '\\'))
|
|
{
|
|
char *buf = alloca (2 * strlen (g[j].value));
|
|
fprintf (pi, "\", \"%s\", [], \"%s\", %d])\n",
|
|
cquote (buf, g[j].value), g[j].name,
|
|
g[j].code);
|
|
freea (buf);
|
|
}
|
|
else
|
|
{
|
|
fprintf (pi, "\", '%s', [], \"%s\", %d])\n",
|
|
g[j].value, g[j].name, g[j].code);
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
|
|
FOUND:
|
|
piname = (char *)dwg_bits_name[g[j].type];
|
|
if (g[j].type == BITS_HANDLE)
|
|
piname = (char *)"H";
|
|
fprintf (pi, " %snew_struct('%s%d', [\"",
|
|
have_struct ? "," : " ", piname, g[j].code);
|
|
have_struct = 1;
|
|
bit_fprint_bits (pi, g[j].bytes, g[j].num_bits);
|
|
if (g[j].type == BITS_HANDLE)
|
|
{
|
|
char buf[32];
|
|
// reactors or xdict?
|
|
handle_string (buf, cur_hdl, g[j].value,
|
|
unknown_dxf[i].handle);
|
|
fprintf (pi, "\", '%s', [], \"%s\", %d])\n", buf, g[j].name,
|
|
g[j].code);
|
|
}
|
|
/* i.e. if string value contains \ */
|
|
else if ((g[j].type == BITS_TV || g[j].type == BITS_TU
|
|
|| g[j].type == BITS_TF)
|
|
&& strchr (g[j].value, '\\'))
|
|
{
|
|
char *buf = alloca (2 * strlen (g[j].value));
|
|
fprintf (pi, "\", \"%s\", [], \"%s\", %d])\n",
|
|
cquote (buf, g[j].value), g[j].name, g[j].code);
|
|
freea (buf);
|
|
}
|
|
else
|
|
{
|
|
fprintf (pi, "\", '%s', [], \"%s\", %d])\n", g[j].value,
|
|
g[j].name, g[j].code);
|
|
}
|
|
if (num_found == 1)
|
|
{
|
|
// we still need to skip already reserved offsets
|
|
if (set_found (&dxf[i], &g[j]))
|
|
{
|
|
offset = g[j].pos[0] + 1;
|
|
goto SEARCH;
|
|
}
|
|
printf ("+ %d: %s [%s] found 1 at offset %d-%d /%d\n",
|
|
g[j].code, g[j].value, dwg_bits_name[g[j].type],
|
|
g[j].pos[0], g[j].pos[0] + g[j].num_bits - 1, size);
|
|
if (g[j].num > 1)
|
|
printf (" but we have %d same DXF fields\n",
|
|
g[j].num);
|
|
else
|
|
dxf[i].num_filled += g[j].num_bits;
|
|
}
|
|
else if (num_found == 2)
|
|
{
|
|
printf (
|
|
"%s %d: %s [%s] found 2 at offsets %d-%d, %d-%d /%d\n",
|
|
2 == g[j].num ? "+" : "?", g[j].code, g[j].value,
|
|
dwg_bits_name[g[j].type], g[j].pos[0],
|
|
g[j].pos[0] + g[j].num_bits - 1, g[j].pos[1],
|
|
g[j].pos[1] + g[j].num_bits - 1, size);
|
|
// check if we have two of those fields, then it's unique
|
|
// also
|
|
if (2 == g[j].num)
|
|
{
|
|
printf (" and we have %d same DXF fields\n", 2);
|
|
set_found (&dxf[i], &g[j]);
|
|
set_found_i (&dxf[i], &g[j], 1);
|
|
dxf[i].num_filled += g[j].num_bits;
|
|
}
|
|
else if (g[j].num > 1)
|
|
{
|
|
printf (" but we have %d same DXF fields\n",
|
|
g[j].num);
|
|
}
|
|
}
|
|
else if (num_found == 3)
|
|
{
|
|
printf (
|
|
"%s %d: %s [%s] found 3 at offsets %d-%d, %d, %d /%d\n",
|
|
3 == g[j].num ? "+" : "?", g[j].code, g[j].value,
|
|
dwg_bits_name[g[j].type], g[j].pos[0],
|
|
g[j].pos[0] + g[j].num_bits - 1, g[j].pos[1],
|
|
g[j].pos[2], size);
|
|
if (3 == g[j].num)
|
|
{
|
|
printf (" and we have %d same DXF fields\n", 3);
|
|
set_found (&dxf[i], &g[j]);
|
|
set_found_i (&dxf[i], &g[j], 1);
|
|
set_found_i (&dxf[i], &g[j], 2);
|
|
dxf[i].num_filled += g[j].num_bits;
|
|
}
|
|
else if (g[j].num > 1)
|
|
{
|
|
printf (" but we have %d same DXF fields\n",
|
|
g[j].num);
|
|
}
|
|
}
|
|
else if (num_found == 4)
|
|
{
|
|
printf ("%s %d: %s [%s] found 4 at offsets %d-%d, %d, %d, "
|
|
"%d /%d\n",
|
|
4 == g[j].num ? "+" : "?", g[j].code, g[j].value,
|
|
dwg_bits_name[g[j].type], g[j].pos[0],
|
|
g[j].pos[0] + g[j].num_bits - 1, g[j].pos[1],
|
|
g[j].pos[2], g[j].pos[3], size);
|
|
if (4 == g[j].num)
|
|
{
|
|
printf (" and we have %d same DXF fields\n", 4);
|
|
set_found (&dxf[i], &g[j]);
|
|
set_found_i (&dxf[i], &g[j], 1);
|
|
set_found_i (&dxf[i], &g[j], 2);
|
|
set_found_i (&dxf[i], &g[j], 3);
|
|
dxf[i].num_filled += g[j].num_bits;
|
|
}
|
|
else if (g[j].num > 1)
|
|
{
|
|
printf (" but we have %d same DXF fields\n",
|
|
g[j].num);
|
|
}
|
|
}
|
|
else if (num_found == 5)
|
|
{
|
|
printf ("%s %d: %s [%s] found 5 at offsets %d-%d, %d, %d, "
|
|
"%d, %d /%d\n",
|
|
5 == g[j].num ? "+" : "?", g[j].code, g[j].value,
|
|
dwg_bits_name[g[j].type], g[j].pos[0],
|
|
g[j].pos[0] + g[j].num_bits - 1, g[j].pos[1],
|
|
g[j].pos[2], g[j].pos[3], g[j].pos[4], size);
|
|
if (5 == g[j].num)
|
|
{
|
|
printf (" and we have %d same DXF fields\n", 5);
|
|
set_found (&dxf[i], &g[j]);
|
|
set_found_i (&dxf[i], &g[j], 1);
|
|
set_found_i (&dxf[i], &g[j], 2);
|
|
set_found_i (&dxf[i], &g[j], 3);
|
|
set_found_i (&dxf[i], &g[j], 4);
|
|
dxf[i].num_filled += g[j].num_bits;
|
|
}
|
|
else if (g[j].num > 1)
|
|
{
|
|
printf (" but we have %d same DXF fields\n",
|
|
g[j].num);
|
|
}
|
|
}
|
|
else if (num_found > 5 && num_found == g[j].num)
|
|
{
|
|
printf ("? %d: %s [%s] found %d at offsets %d-%d, %d, %d, "
|
|
"%d, %d, ... /%d\n",
|
|
g[j].code, g[j].value, dwg_bits_name[g[j].type],
|
|
num_found, g[j].pos[0],
|
|
g[j].pos[0] + g[j].num_bits - 1, g[j].pos[1],
|
|
g[j].pos[2], g[j].pos[3], g[j].pos[4], size);
|
|
printf (" and we have %d same DXF fields\n",
|
|
num_found);
|
|
set_found (&dxf[i], &g[j]);
|
|
set_found_i (&dxf[i], &g[j], 1);
|
|
set_found_i (&dxf[i], &g[j], 2);
|
|
set_found_i (&dxf[i], &g[j], 3);
|
|
set_found_i (&dxf[i], &g[j], 4);
|
|
dxf[i].num_filled += g[j].num_bits;
|
|
}
|
|
else if (num_found > 5)
|
|
{
|
|
printf ("? %d: %s [%s] found %d >5 at offsets %d-%d, %d, "
|
|
"%d, %d, %d, ... /%d\n",
|
|
g[j].code, g[j].value, dwg_bits_name[g[j].type],
|
|
num_found, g[j].pos[0],
|
|
g[j].pos[0] + g[j].num_bits - 1, g[j].pos[1],
|
|
g[j].pos[2], g[j].pos[3], g[j].pos[4], size);
|
|
if (g[j].num > 1)
|
|
printf (" but we have %d same DXF fields\n",
|
|
g[j].num);
|
|
}
|
|
// same pos, search for next. but only if it's a bigger hit, not
|
|
// just 1-2 bits
|
|
/*if (num_found >= 1 && g->num_bits > 2 && set_found(&dxf[i],
|
|
&g[j])) { offset = g[j].pos[0]+1; goto SEARCH;
|
|
}
|
|
*/
|
|
if (0)
|
|
{
|
|
free (g[j].bytes);
|
|
g[j].bytes = NULL;
|
|
}
|
|
}
|
|
fprintf (pi, " ],\n"
|
|
" Data = [S,Fields,Class,Dxf,Version,Offsets],\n"
|
|
" go(Data).\n\n");
|
|
num_fields = j;
|
|
// check for holes and percentage of found ranges
|
|
/*printf("coverage: [");
|
|
for (j=0; j<size; j++) {
|
|
if (dxf[i].found[j]) {
|
|
dxf[i].num_filled++;
|
|
printf("1");
|
|
} else {
|
|
printf(" ");
|
|
}
|
|
}*/
|
|
printf ("%d/%d=%.1f%%\n", dxf[i].num_filled, size,
|
|
100.0 * dxf[i].num_filled / size);
|
|
if (!dxf[i].num_filled)
|
|
{
|
|
fprintf (stderr, "empty %s \"%s\" 0x%X %d\n",
|
|
unknown_dxf[i].name, unknown_dxf[i].dxf,
|
|
unknown_dxf[i].handle, unknown_dxf[i].num_bits);
|
|
}
|
|
class_filled += dxf[i].num_filled;
|
|
class_size += size;
|
|
sum_filled += dxf[i].num_filled;
|
|
sum_size += size;
|
|
printf ("possible: [");
|
|
for (j = 0; j < size; j++)
|
|
{
|
|
if (dxf[i].found[j])
|
|
{ // maybe print the type if the size > 1 (BLxxxxxx)
|
|
printf ("x");
|
|
}
|
|
else if (dxf[i].possible[j])
|
|
{
|
|
dxf[i].num_possible++;
|
|
printf ("%c", dxf[i].possible[j] >= 10
|
|
? '.'
|
|
: dxf[i].possible[j] + '0');
|
|
}
|
|
else
|
|
{
|
|
printf (" ");
|
|
}
|
|
}
|
|
printf ("]\n");
|
|
|
|
// TODO: try likely field combinations and print the top 3.
|
|
// See unknown.pi
|
|
// there are various heuristics, like the handle and string stream at
|
|
// the end. points BD's being neighbors, ...
|
|
|
|
free (dxf[i].found);
|
|
free (dxf[i].possible);
|
|
k++;
|
|
if (k >= 50)
|
|
{
|
|
strcpy (pi_fn, base_pi_fn);
|
|
pi_filename (pi_fn, ++i_pi);
|
|
close_pi (pi, class_filled, class_size, k);
|
|
k = 0;
|
|
pi = fopen (pi_fn, "w");
|
|
if (open_pi (pi, class, pi_fn))
|
|
continue;
|
|
}
|
|
}
|
|
close_pi (pi, class_filled, class_size, k);
|
|
}
|
|
|
|
printf ("summary: %ld/%ld=%.2f%%\n", sum_filled, sum_size,
|
|
100.0 * sum_filled / sum_size);
|
|
return 0;
|
|
}
|