Initial commit

Made-with: Cursor
This commit is contained in:
lyf
2026-03-12 17:51:30 +08:00
commit 79102a18fb
1507 changed files with 480854 additions and 0 deletions

View File

@@ -0,0 +1,152 @@
/*****************************************************************************/
/* 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/>. */
/*****************************************************************************/
/*
* bd.c: print double of bits
* written by Reini Urban
*
*/
#include "../src/config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dwg.h"
#include "../src/bits.h"
int
main (int argc, char *argv[])
{
char *input;
int hex = 0;
int size, bits;
unsigned long pos;
Bit_Chain dat = EMPTY_CHAIN (0);
if (argc < 2)
{
printf ("usage: examples/bd "
"001100000000000000000000000000011000000000000000100000001010010"
"00\n");
printf ("or examples/bd -x '8055 40f9 3284 d222 3e40 7436 e0d9 23fd'\n");
return 1;
}
if (argc > 2 && !strcmp (argv[1], "-x"))
{
hex = 1;
input = argv[2];
size = strlen (input);
}
else
{
input = argv[1];
bits = strlen (input);
size = (bits / 8);
}
dat.chain = malloc (size + 1);
dat.size = size;
dat.version = R_2004;
if (hex)
{
dat.size = bit_write_hexbits (&dat, input);
bits = dat.size / 8;
}
else
bit_write_bits (&dat, input);
pos = bit_position (&dat);
bit_set_position (&dat, 0);
// accept more types, like CMC, BS, BL, HANDLE and print all possible
// variants
if (pos == 64)
{
double d = bit_read_RD (&dat);
printf ("%.15f RD @%lu\n", d, bit_position (&dat));
}
else if (pos == 2 || pos > 64)
{
double d = bit_read_BD (&dat);
printf ("%.15f BD @%lu (%ld)\n", d, bit_position (&dat), pos);
if (pos == 2)
{
int i;
bit_set_position (&dat, 0);
i = bit_read_BB (&dat);
printf ("%d BB @%lu\n", i, bit_position (&dat));
if (i == 2)
printf ("%d BS/BL @%lu\n", 0, bit_position (&dat));
else if (i == 3)
printf ("%d BS @%lu\n", 256, bit_position (&dat));
}
}
else if (pos == 34)
{
long l = bit_read_BL (&dat);
printf ("%ld BL @%lu\n", l, bit_position (&dat));
}
else if (pos == 32)
{
long l = bit_read_RL (&dat);
printf ("%ld RL @%lu\n", l, bit_position (&dat));
}
else if (pos == 16)
{
int l = (int)bit_read_RS (&dat);
printf ("%d RS @%lu\n", l, bit_position (&dat));
}
else if (pos == 10)
{
long l = bit_read_BS (&dat);
Dwg_Handle h;
printf ("%ld BS @%lu\n", l, bit_position (&dat));
bit_set_position (&dat, 0);
if (!bit_read_H (&dat, &h) && h.size == 1)
printf (FORMAT_H " H @%lu (%ld)\n", ARGS_H (h), bit_position (&dat),
pos);
}
else if (pos == 8)
{
int l = (int)bit_read_RC (&dat);
Dwg_Handle h;
printf ("%d RC @%lu\n", l, bit_position (&dat));
bit_set_position (&dat, 0);
if (!bit_read_H (&dat, &h) && h.size == 1)
printf (FORMAT_H " H @%lu (%ld)\n", ARGS_H (h), bit_position (&dat),
pos);
}
else
{
Dwg_Handle h;
Dwg_Color c;
double d = bit_read_BD (&dat);
if (pos >= bit_position (&dat))
{
printf ("%.15f BD? @%lu (%ld)\n", d, bit_position (&dat), pos);
}
else
{ // divide into chunks of 34,32,18,16,10,8,2
printf ("? (%ld)\n", pos);
}
bit_set_position (&dat, 0);
if (!bit_read_H (&dat, &h))
printf (FORMAT_H " H? @%lu (%ld)\n", ARGS_H (h), bit_position (&dat),
pos);
bit_set_position (&dat, 0);
bit_read_CMC (&dat, &dat, &c);
if (c.index < 257)
printf ("%d 0x%06X 0x%x CMC? @%lu (%ld)\n", c.index, c.rgb, c.flag,
bit_position (&dat), pos);
}
free (dat.chain);
return 0;
}

View File

@@ -0,0 +1,232 @@
/*****************************************************************************/
/* 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/>. */
/*****************************************************************************/
/*
* bits.c: print all possible type/values of given bits
* written by Reini Urban
*/
#include "../src/config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "dwg.h"
#include "../src/bits.h"
static int maxoff = 0;
static int
decode (Bit_Chain *dat, int off, const int size)
{
int pos = 0;
BITCODE_BS bs = 0;
printf ("decode offset:%d, size:%d\n", off, size);
if (off >= size)
return 0;
bit_set_position (dat, off);
if (size - off >= 66)
{
double d = bit_read_BD (dat);
int p = (int)bit_position (dat);
if (d != bit_nan ())
{
printf ("%.15f BD @%d (%d)\n", d, p, size);
pos = p;
}
bit_set_position (dat, off);
}
if (size - off >= 64)
{
double d = bit_read_RD (dat);
int p = (int)bit_position (dat);
if (d != bit_nan ())
{
printf ("%.15f RD @%d (%d)\n", d, p, size);
pos = p;
}
bit_set_position (dat, off);
}
if (size - off >= 34)
{
BITCODE_BL l = (long)bit_read_BL (dat);
int p = (int)bit_position (dat);
if (p <= size - off)
{
printf ("%u BL @%d (%d)\n", l, p, size);
pos = p;
}
bit_set_position (dat, off);
}
if (size - off >= 32)
{
BITCODE_BL l = (long)bit_read_RL (dat);
pos = (int)bit_position (dat);
printf ("%u RL @%d (%d)\n", l, pos, size);
bit_set_position (dat, off);
}
if (size - off >= 16)
{
BITCODE_RS l = (int)bit_read_RS (dat);
pos = (int)bit_position (dat);
printf ("%d RS @%d (%d)\n", l, pos, size);
bit_set_position (dat, off);
}
if (size - off >= 10)
{
int p;
bs = bit_read_BS (dat);
p = (int)bit_position (dat);
if (p <= size - off)
{
printf ("%d BS @%d (%d)\n", bs, p, size);
pos = p;
}
bit_set_position (dat, off);
}
if (size - off >= 8)
{
int l = bit_read_RC (dat);
pos = (int)bit_position (dat);
printf ("%d RC @%d (%d)\n", l, pos, size);
bit_set_position (dat, off);
}
if (size - off >= 8)
{
Dwg_Handle h;
int err, p;
err = bit_read_H (dat, &h);
p = (int)bit_position (dat);
if (!err && h.size == 1 && p <= size - off)
{
printf ("%x.%d.%lX H @%d (%d)\n", h.code, h.size, h.value, p, size);
pos = p;
}
bit_set_position (dat, off);
}
if (size - off >= 4)
{
Dwg_Color c;
int p;
bit_read_CMC (dat, dat, &c);
p = (int)bit_position (dat);
if (c.index < 257 && p <= size - off)
{
printf ("%d 0x%06X 0x%x CMC @%d (%d)\n", c.index, c.rgb, c.flag, p,
size);
pos = p;
}
free (c.name);
free (c.book_name);
bit_set_position (dat, off);
}
if (size - off >= 2)
{
int i = bit_read_BB (dat);
pos = (int)bit_position (dat);
printf ("%d BB @%d (%d)\n", i, pos, size);
if (i == 2)
printf ("%d BS/BL @%d (%d)\n", 0, pos, size);
else if (i == 3)
printf ("%d BS @%d (%d)\n", 256, pos, size);
bit_set_position (dat, off);
}
// if BS is a valid length try TV also
if (bs > 0 && bs < size - off - pos)
{
int i;
char *s = bit_read_TV (dat);
int p = (int)bit_position (dat);
if (s)
{
for (i = 0; i < bs; i++)
if (!isprint (s[i]))
break;
if (i == bs)
{
printf ("%s TV @%d (%d)\n", s, pos, size);
pos = p;
}
free (s);
}
}
while (pos < size)
{
if (pos <= off)
pos++;
if (maxoff < pos)
maxoff = pos;
// printf ("offset %d\n", pos);
return decode (dat, off + 1, size);
}
return 0;
}
int
main (int argc, char *argv[])
{
int hex = 0;
int i;
int pos;
Bit_Chain dat = EMPTY_CHAIN (0);
if (argc < 2)
{
printf ("usage: examples/bits "
"001100000000000000000000000000011000000000000000100000001010010"
"00\n");
printf (
"or examples/bits -x '8055 40f9 3284 d222 3e40 7436 e0d9 23fd'\n");
return 1;
}
if (argc > 2 && !strcmp (argv[1], "-x"))
{
hex = 1;
i = 2;
}
else
{
i = 1;
}
// dat.chain = malloc (size + 1);
// dat.size = size;
dat.version = R_2004;
do
{
char *input = argv[i];
int bits = strlen (input);
if (hex)
dat.size += bits;
else
dat.size += bits / 8;
dat.chain = realloc (dat.chain, dat.size + 1);
if (hex)
{
int size = bit_write_hexbits (&dat, input);
dat.size -= dat.size - size;
}
else
bit_write_bits (&dat, input);
i++;
}
while (i < argc);
pos = (int)bit_position (&dat);
// accept all types, like CMC, BS, BL, HANDLE and print all possible variants
pos = decode (&dat, 0, (int)pos);
free (dat.chain);
return 0;
}

View File

@@ -0,0 +1,531 @@
/*****************************************************************************/
/* LibreDWG - free implementation of the DWG file format */
/* */
/* Copyright (C) 2013-2020,2023 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/>. */
/*****************************************************************************/
/*
* dwg2svg2.c: convert a DWG to SVG via the API.
if there are paperspace entities, only output them. else all modelspace
entities.
* written by Gaganjyot Singh
* modified by Reini Urban
*/
#include "../src/config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <getopt.h>
#ifdef ENABLE_MIMALLOC
# include <mimalloc-override.h>
#endif
#include <dwg.h>
#include <dwg_api.h>
#include "geom.h"
static int opts = 0;
static dwg_data g_dwg;
static double model_xmin, model_ymin;
static double page_width, page_height, scale;
static int
usage (void)
{
printf ("\nUsage: dwg2svg2 [-v[0-9]] DWGFILE\n");
return 1;
}
static int
opt_version (void)
{
printf ("dwg2svg2 %s\n", PACKAGE_VERSION);
return 0;
}
static int
help (void)
{
printf ("\nUsage: dwg2svg2 [OPTION]... DWGFILE >file.svg\n");
printf ("Example to use the DWG api\n"
"\n");
#ifdef HAVE_GETOPT_LONG
printf (" -v[0-9], --verbose [0-9] verbosity\n");
printf (" --help display this help and exit\n");
printf (" --version output version information and exit\n"
"\n");
#else
printf (" -v[0-9] verbosity\n");
printf (" -h display this help and exit\n");
printf (" -i output version information and exit\n"
"\n");
#endif
printf ("GNU LibreDWG online manual: "
"<https://www.gnu.org/software/libredwg/>\n");
return 0;
}
#define log_if_error(msg) \
if (error) \
{ \
fprintf (stderr, "ERROR: %s", msg); \
exit (1); \
}
#define log_error(msg) \
{ \
fprintf (stderr, "ERROR: %s", msg); \
exit (1); \
}
#define dynget(obj, name, field, var) \
if (!dwg_dynapi_entity_value (obj, "" name, "" field, var, NULL)) \
{ \
fprintf (stderr, "ERROR: %s.%s", name, field); \
exit (1); \
}
#define dynget_utf8(obj, name, field, var) \
if (!dwg_dynapi_entity_utf8text (obj, "" name, "" field, var, &isnew, \
NULL)) \
{ \
fprintf (stderr, "ERROR: %s.%s", name, field); \
exit (1); \
}
static double
transform_X (double x)
{
return x - model_xmin;
}
static double
transform_Y (double y)
{
return page_height - (y - model_ymin);
}
static void output_SVG (dwg_data *dwg);
static int
test_SVG (char *filename)
{
int error;
memset (&g_dwg, 0, sizeof (dwg_data));
g_dwg.opts = opts;
error = dwg_read_file (filename, &g_dwg);
if (error < DWG_ERR_CRITICAL)
output_SVG (&g_dwg);
dwg_free (&g_dwg);
/* This value is the return value for `main',
so clamp it to either 0 or 1. */
return error < DWG_ERR_CRITICAL ? 0 : 1;
}
static void
output_TEXT (dwg_object *obj)
{
int error, index;
dwg_point_2d ins_pt;
Dwg_Entity_TEXT *text;
char *text_value;
double fontsize;
const Dwg_Version_Type dwg_version = obj->parent->header.version;
int isnew = 0;
index = dwg_object_get_index (obj, &error);
log_if_error ("object_get_index");
text = dwg_object_to_TEXT (obj);
if (!text)
log_error ("dwg_object_to_TEXT");
dynget_utf8 (text, "TEXT", "text_value", &text_value);
dynget (text, "TEXT", "ins_pt", &ins_pt);
dynget (text, "TEXT", "height", &fontsize);
printf ("\t<text id=\"dwg-object-%d\" x=\"%f\" y=\"%f\" "
"font-family=\"Verdana\" font-size=\"%f\" fill=\"blue\">%s</text>\n",
index, transform_X (ins_pt.x), transform_Y (ins_pt.y), fontsize,
text_value);
if (text_value && isnew)
free (text_value);
}
static void
output_LINE (dwg_object *obj)
{
int error, index;
Dwg_Entity_LINE *line;
dwg_point_3d start, end;
index = dwg_object_get_index (obj, &error);
log_if_error ("object_get_index");
line = dwg_object_to_LINE (obj);
if (!line)
log_error ("dwg_object_to_LINE");
if (!dwg_get_LINE (line, "start", &start))
log_error ("LINE.start");
if (!dwg_get_LINE (line, "end", &end))
log_error ("LINE.end");
printf ("\t<path id=\"dwg-object-%d\" d=\"M %f,%f %f,%f\" "
"style=\"fill:none;stroke:blue;stroke-width:0.1px\" />\n",
index, transform_X (start.x), transform_Y (start.y),
transform_X (end.x), transform_Y (end.y));
}
static void
output_CIRCLE (dwg_object *obj)
{
Dwg_Entity_CIRCLE *circle;
int error, index;
double radius;
dwg_point_3d center;
index = dwg_object_get_index (obj, &error);
log_if_error ("object_get_index");
circle = dwg_object_to_CIRCLE (obj);
if (!circle)
log_error ("dwg_object_to_CIRCLE");
if (!dwg_get_CIRCLE (circle, "center", &center))
log_error ("CIRCLE.center");
if (!dwg_get_CIRCLE (circle, "radius", &radius))
log_error ("CIRCLE.radius");
printf ("\t<circle id=\"dwg-object-%d\" cx=\"%f\" cy=\"%f\" r=\"%f\" "
"fill=\"none\" stroke=\"blue\" stroke-width=\"0.1px\" />\n",
index, transform_X (center.x), transform_Y (center.y), radius);
}
static void
output_ARC (dwg_object *obj)
{
Dwg_Entity_ARC *arc;
int error, index;
double radius, start_angle, end_angle;
dwg_point_3d center;
double x_start, y_start, x_end, y_end;
int large_arc;
index = dwg_object_get_index (obj, &error);
log_if_error ("object_get_index");
arc = dwg_object_to_ARC (obj);
if (!arc)
log_error ("dwg_object_to_ARC");
dynget (arc, "ARC", "radius", &radius);
dynget (arc, "ARC", "center", &center);
dynget (arc, "ARC", "start_angle", &start_angle);
dynget (arc, "ARC", "end_angle", &end_angle);
x_start = center.x + radius * cos (start_angle);
y_start = center.y + radius * sin (start_angle);
x_end = center.x + radius * cos (end_angle);
y_end = center.y + radius * sin (end_angle);
// Assuming clockwise arcs.
large_arc = (end_angle - start_angle < M_PI) ? 0 : 1;
printf ("\t<path id=\"dwg-object-%d\" d=\"M %f,%f A %f,%f 0 %d 0 %f,%f\" "
"fill=\"none\" stroke=\"blue\" stroke-width=\"%f\" />\n",
index, transform_X (x_start), transform_Y (y_start), radius, radius,
large_arc, transform_X (x_end), transform_Y (y_end), 0.1);
}
static void
output_INSERT (dwg_object *obj)
{
int index, error;
BITCODE_RL abs_ref;
double rotation;
dwg_ent_insert *insert;
dwg_point_3d ins_pt, _scale;
dwg_handle *obj_handle, *ins_handle;
Dwg_Data *dwg;
insert = dwg_object_to_INSERT (obj);
if (!insert)
log_error ("dwg_object_to_INSERT");
dwg = obj->parent;
index = dwg_object_get_index (obj, &error);
log_if_error ("object_get_index");
dynget (insert, "INSERT", "rotation", &rotation);
dynget (insert, "INSERT", "ins_pt", &ins_pt);
dynget (insert, "INSERT", "scale", &_scale);
obj_handle = dwg_object_get_handle (obj, &error);
log_if_error ("get_handle");
if (!insert->block_header)
log_error ("insert->block_header");
abs_ref = insert->block_header->absolute_ref;
if (insert->block_header->handleref.code == 5 || dwg->header.version < R_13)
{
printf ("\t<use id=\"dwg-object-%d\" transform=\"translate(%f %f) "
"rotate(%f) scale(%f %f)\" xlink:href=\"#symbol-%X\" /><!-- "
"block_header->handleref: " FORMAT_H " -->\n",
index, transform_X (ins_pt.x), transform_Y (ins_pt.y),
(180.0 / M_PI) * rotation, _scale.x, _scale.y, abs_ref,
ARGS_H (*obj_handle));
}
else
{
printf ("\n\n<!-- WRONG INSERT(" FORMAT_H ") -->\n",
ARGS_H (*obj_handle));
}
}
static int
output_object (dwg_object *obj)
{
int i = 0;
if (!obj)
{
fprintf (stderr, "object is NULL\n");
return 0;
}
if (dwg_object_get_fixedtype (obj) == DWG_TYPE_INSERT)
{
i++;
output_INSERT (obj);
}
else if (dwg_object_get_fixedtype (obj) == DWG_TYPE_LINE)
{
i++;
output_LINE (obj);
}
else if (dwg_object_get_fixedtype (obj) == DWG_TYPE_CIRCLE)
{
i++;
output_CIRCLE (obj);
}
else if (dwg_object_get_fixedtype (obj) == DWG_TYPE_TEXT)
{
i++;
output_TEXT (obj);
}
else if (dwg_object_get_fixedtype (obj) == DWG_TYPE_ARC)
{
i++;
output_ARC (obj);
}
return i;
}
static int
output_BLOCK_HEADER (dwg_object_ref *ref)
{
dwg_object *hdr, *obj;
dwg_obj_block_header *_hdr;
int error;
BITCODE_RL abs_ref;
char *name;
int i = 0;
if (!ref)
{
fprintf (stderr,
"Empty BLOCK."
" Could not output an SVG symbol for this BLOCK_HEADER\n");
return 0;
}
hdr = dwg_ref_get_object (ref, &error);
if (!hdr || error)
{
abs_ref = dwg_ref_get_absref (ref, &error);
fprintf (stderr, "Failed to resolve BLOCK handle %X.\n",
(unsigned)abs_ref);
return 0;
}
abs_ref = dwg_ref_get_absref (ref, &error);
_hdr = dwg_object_to_BLOCK_HEADER (hdr);
if (_hdr)
{
i++;
dynget (_hdr, "BLOCK_HEADER", "name", &name);
// name = dwg_obj_block_header_get_name (_hdr, &error);
printf ("\t<g id=\"symbol-%X\" >\n\t\t<!-- %s -->\n",
abs_ref ? abs_ref : 0, name ? name : "");
if (name != NULL && name != _hdr->name
&& hdr->parent->header.version >= R_2007)
free (name);
}
else
printf ("\t<g id=\"symbol-%X\" >\n\t\t<!-- ? -->\n",
abs_ref ? abs_ref : 0);
obj = get_first_owned_entity (hdr);
while (obj)
{
i += output_object (obj);
obj = get_next_owned_entity (hdr, obj);
}
printf ("\t</g>\n");
return i;
}
static void
output_SVG (dwg_data *dwg)
{
unsigned int i, num_hdr_objs;
int error;
dwg_obj_block_control *_ctrl;
dwg_object_ref *hdr;
dwg_object_ref **hdr_refs;
dwg_object_ref *ms = dwg_model_space_ref (dwg);
dwg_object_ref *ps = dwg_paper_space_ref (dwg);
double dx = dwg_model_x_max (dwg) - dwg_model_x_min (dwg);
double dy = dwg_model_y_max (dwg) - dwg_model_y_min (dwg);
double pdx = dwg->header_vars.PLIMMAX.x - dwg->header_vars.PLIMMIN.x;
double pdy = dwg->header_vars.PLIMMAX.y - dwg->header_vars.PLIMMIN.y;
double scale_x = dx / (pdx == 0.0 ? 1.0 : pdx);
double scale_y = dy / (pdy == 0.0 ? 1.0 : pdy);
scale = 25.4 / 72.0; // pt:mm TODO
model_xmin = dwg_model_x_min (dwg);
model_ymin = dwg_model_y_min (dwg);
page_width = dx;
page_height = dy;
scale *= (scale_x > scale_y ? scale_x : scale_y);
_ctrl = dwg_block_control (dwg);
hdr_refs = dwg_obj_block_control_get_block_headers (_ctrl, &error);
log_if_error ("block_control_get_block_headers");
num_hdr_objs = dwg_obj_block_control_get_num_entries (_ctrl, &error);
log_if_error ("block_control_get_num_entries");
printf ("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
"<svg\n"
" xmlns:svg=\"http://www.w3.org/2000/svg\"\n"
" xmlns=\"http://www.w3.org/2000/svg\"\n"
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
" version=\"1.1\"\n"
" width=\"%f\"\n"
" height=\"%f\"\n"
">\n",
page_width, page_height);
printf ("\t<defs>\n");
for (i = 0; i < num_hdr_objs; i++)
{
hdr = hdr_refs[i];
if (hdr == ms || hdr == ps)
continue;
output_BLOCK_HEADER (hdr_refs[i]);
}
printf ("\t</defs>\n");
if (ps)
i = output_BLOCK_HEADER (ps);
if (!ps || !i)
output_BLOCK_HEADER (ms);
free (hdr_refs);
printf ("</svg>\n");
}
int
main (int argc, char *argv[])
{
int i = 1;
int c;
#ifdef HAVE_GETOPT_LONG
int option_index = 0;
static struct option long_options[]
= { { "verbose", 1, &opts, 1 }, // optional
{ "help", 0, 0, 0 },
{ "version", 0, 0, 0 },
{ NULL, 0, NULL, 0 } };
#endif
if (argc < 2)
return usage ();
while
#ifdef HAVE_GETOPT_LONG
((c = getopt_long (argc, argv, ":v::h", long_options, &option_index))
!= -1)
#else
((c = getopt (argc, argv, ":v::hi")) != -1)
#endif
{
if (c == -1)
break;
switch (c)
{
case ':': // missing arg
if (optarg && !strcmp (optarg, "v"))
{
opts = 1;
break;
}
fprintf (stderr, "%s: option '-%c' requires an argument\n", argv[0],
optopt);
break;
#ifdef HAVE_GETOPT_LONG
case 0:
/* This option sets a flag */
if (!strcmp (long_options[option_index].name, "verbose"))
{
if (opts < 0 || opts > 9)
return usage ();
# if defined(USE_TRACING) && defined(HAVE_SETENV)
{
char v[2];
*v = opts + '0';
*(v + 1) = 0;
setenv ("LIBREDWG_TRACE", v, 1);
}
# endif
break;
}
if (!strcmp (long_options[option_index].name, "version"))
return opt_version ();
if (!strcmp (long_options[option_index].name, "help"))
return help ();
break;
#else
case 'i':
return opt_version ();
#endif
case 'v': // support -v3 and -v
i = (optind > 0 && optind < argc) ? optind - 1 : 1;
if (!memcmp (argv[i], "-v", 2))
{
opts = argv[i][2] ? argv[i][2] - '0' : 1;
}
if (opts < 0 || opts > 9)
return usage ();
#if defined(USE_TRACING) && defined(HAVE_SETENV)
{
char v[2];
*v = opts + '0';
*(v + 1) = 0;
setenv ("LIBREDWG_TRACE", v, 1);
}
#endif
break;
case 'h':
return help ();
case '?':
fprintf (stderr, "%s: invalid option '-%c' ignored\n", argv[0],
optopt);
break;
default:
return usage ();
}
}
i = optind;
if (i >= argc)
return usage ();
return test_SVG (argv[i]);
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,821 @@
/*****************************************************************************/
/* LibreDWG - free implementation of the DWG file format */
/* */
/* Copyright (C) 2020 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/>. */
/*****************************************************************************/
/*
* dwgfuzz.c: afl++/honggfuzz fuzzing for all in- and exporters. Just not the
separate ones.
*
* Also usable like:
../configure --disable-shared --disable-bindings CC=hfuzz-clang CFLAGS='-O2
-g -fsanitize=address,undefined -fno-omit-frame-pointer -I/usr/local/include'
&& make -C src && make -C examples dwgfuzz honggfuzz -i ../.fuzz-in-dxf --
examples/dwgfuzz -indxf ___FILE___
* Also useful for debugging the fuzzers.
AFL_DONT_OPTIMIZE=1 AFL_LLVM_INSTRIM=1 AFL_USE_ASAN=1 make -C examples
dwgfuzz V=1 AFL_DEBUG=15 AFL_DEBUG_CHILD_OUTPUT=1 gdb --args afl-fuzz -m none
-i ../.fuzz-in-dxf/ -o .fuzz-out/ examples/dwgfuzz (gdb) set follow-fork-mode
child
* written by Reini Urban
*/
#include "../src/config.h"
#ifdef HAVE_SSCANF_S
# define __STDC_WANT_LIB_EXT1__ 1
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <getopt.h>
#include <dwg.h>
#include <dwg_api.h>
#include "common.h"
#include "decode.h"
#include "encode.h"
#include "bits.h"
#ifndef DISABLE_DXF
# include "out_dxf.h"
# ifndef DISABLE_JSON
# include "in_json.h"
# include "out_json.h"
# endif
# include "in_dxf.h"
#endif
#define FUZZ_INMEM 0
#define FUZZ_STDIN 1
#define FUZZ_FILE 2
// defined by ./make-afl-clang-fast.sh for INMEM. defaults to FILE for
// debugging
#ifndef FUZZ_MODE
# define FUZZ_MODE FUZZ_INMEM
//#define FUZZ_MODE FUZZ_STDIN
//#define FUZZ_MODE FUZZ_FILE
#endif
int dwg_fuzz_dat (Dwg_Data **restrict dwgp, Bit_Chain *restrict dat);
static int
version (void)
{
printf ("dwgfuzz %s INMEM\n", PACKAGE_VERSION);
#ifndef __AFL_COMPILER
printf ("not instrumented\n");
#else
# ifdef __AFL_FUZZ_TESTCASE_BUF
printf ("shared-memory instrumented\n");
# else
printf ("instrumented\n");
# endif
#endif
return 0;
}
#ifndef __AFL_COMPILER
# define __AFL_FUZZ_INIT()
# if FUZZ_MODE == FUZZ_INMEM
unsigned char *__AFL_FUZZ_TESTCASE_BUF;
unsigned long __AFL_FUZZ_TESTCASE_LEN;
# define __AFL_INIT() \
fp = fopen (argv[2], "rb"); \
if (!fp) \
return 0; \
__AFL_FUZZ_TESTCASE_LEN = dat.size; \
dat_read_file (&dat, fp, argv[2]); \
__AFL_FUZZ_TESTCASE_BUF = dat.chain;
# else
# define __AFL_INIT()
# endif
# define __AFL_FUZZ_TESTCASE_LEN dat.size
# define __AFL_LOOP(i) 1
#endif
__AFL_FUZZ_INIT ();
static int
help (void)
{
#if FUZZ_MODE == FUZZ_FILE
printf ("\nUsage: dwgfuzz MODE @@\n");
#elif !defined __AFL_COMPILER
printf ("\nUsage: dwgfuzz MODE ../.fuzz-in/INFILE\n");
#else
printf ("\nUsage: dwgfuzz MODE\n");
#endif
printf ("afl++ clang-fast shared-memory backend, using many importers and "
"exporters.\n"
"\n");
printf ("MODE:\n");
#ifdef USE_WRITE
# ifndef DISABLE_DXF
printf (" -indxf: import from DXF, export as r2000 DWG\n");
# endif
# ifndef DISABLE_JSON
printf (" -injson: import from JSON, export as r2000 DWG\n");
# endif
printf (" -rw: import from DWG, export as r2000 DWG, re-import from "
"this DWG (rewrite)\n");
printf (" -add: import from special add file, export as DWG and DXF, "
"re-import from this\n");
#endif
printf (" -dwg: import from DWG only\n");
#ifndef DISABLE_DXF
printf (" -dxf: import from DWG, export as DXF\n");
printf (" -dxfb: import from DWG, export as binary DXF\n");
#endif
#ifndef DISABLE_JSON
printf (" -json: import from DWG, export as JSON\n");
printf (" -geojson: import from DWG, export as GeoJSON\n");
#endif
printf ("\n"
" --version display the version and exit\n");
printf (" --help display this help and exit\n");
return 0;
}
// for LLVMFuzzerTestOneInput see llvmfuzz.c
int
main (int argc, char *argv[])
{
int i = 0;
Dwg_Data dwg;
Bit_Chain dat = { 0 };
Bit_Chain out_dat = { 0 };
FILE *fp;
struct stat attrib;
enum
{
INVALID,
DWG,
#if defined(USE_WRITE) && !defined(DISABLE_DXF)
INDXF,
#endif
#if defined(USE_WRITE) && !defined(DISABLE_JSON)
INJSON,
#endif
#if defined(USE_WRITE)
RW,
ADD,
#endif
#if !defined(DISABLE_DXF)
DXF,
DXFB,
#endif
#if !defined(DISABLE_JSON)
JSON,
GEOJSON,
#endif
} mode
= INVALID;
__AFL_INIT ();
if (argc <= 1 || !*argv[1])
return 1;
if (strEQc (argv[1], "-dwg"))
mode = DWG;
#ifdef USE_WRITE
# ifndef DISABLE_DXF
else if (strEQc (argv[1], "-indxf"))
mode = INDXF;
# endif
# ifndef DISABLE_JSON
else if (strEQc (argv[1], "-injson"))
mode = INJSON;
# endif
else if (strEQc (argv[1], "-rw"))
mode = RW;
else if (strEQc (argv[1], "-add"))
mode = ADD;
#endif /* USE_WRITE */
#ifndef DISABLE_DXF
else if (strEQc (argv[1], "-dxf"))
mode = DXF;
else if (strEQc (argv[1], "-dxfb"))
mode = DXFB;
#endif
#ifndef DISABLE_JSON
else if (strEQc (argv[1], "-json"))
mode = JSON;
else if (strEQc (argv[1], "-geojson"))
mode = GEOJSON;
#endif
else if (strEQc (argv[1], "--version"))
return version ();
else if (strEQc (argv[1], "--help"))
return help ();
else
return 1;
if (mode == INVALID)
return 1;
#if FUZZ_MODE == FUZZ_FILE
if (argc <= 2 || !*argv[2])
return 1;
#endif
#if FUZZ_MODE == FUZZ_INMEM && !defined(__AFL_COMPILER)
if (argc <= 2 || !*argv[2])
return 1;
#endif
memset (&dwg, 0, sizeof (dwg));
dat.chain = NULL;
// dat.opts = 3;;
#if FUZZ_MODE == FUZZ_INMEM
dat.chain = __AFL_FUZZ_TESTCASE_BUF;
#endif
while (__AFL_LOOP (10000))
{ // llvm_mode persistent, non-forking mode
i++;
#ifndef __AFL_COMPILER
# ifdef USE_WRITE
if (mode == ADD && i > 1)
break;
# endif
if (i > 3)
break;
#endif
#if FUZZ_MODE == FUZZ_INMEM
// fastest mode via shared mem
if (!dat.chain)
dat.chain = __AFL_FUZZ_TESTCASE_BUF;
dat.size = __AFL_FUZZ_TESTCASE_LEN;
printf ("Fuzzing from shared memory (%" PRIuSIZE ")\n", dat.size);
#elif FUZZ_MODE == FUZZ_STDIN
// still 10x faster than the old file-forking fuzzer.
dat.size = 0;
// dat.chain = NULL;
dat_read_stream (&dat, stdin);
printf ("Fuzzing from stdin (%" PRIuSIZE ")\n", dat.size);
#elif FUZZ_MODE == FUZZ_FILE
dat.size = 0;
fp = fopen (argv[2], "rb");
if (!fp)
return 0;
dat_read_file (&dat, fp, argv[2]);
fclose (fp);
printf ("Fuzzing from file (%" PRIuSIZE ")\n", dat.size);
#else
# error Missing FUZZ_MODE
#endif
if (dat.size == 0)
exit (1);
if (dat.size < 100)
continue; // useful minimum input length
memset (&out_dat, 0, sizeof (out_dat));
bit_chain_set_version (&out_dat, &dat);
#ifdef _WIN32
out_dat.fh = fopen ("NUL", "w");
#else
out_dat.fh = fopen ("/dev/null", "w");
#endif
switch (mode)
{
case DWG:
if (dwg_decode (&dat, &dwg) >= DWG_ERR_CRITICAL)
exit (0);
break;
#if defined(USE_WRITE) && !defined(DISABLE_DXF)
case INDXF:
if (dwg_read_dxf (&dat, &dwg) < DWG_ERR_CRITICAL)
{
out_dat.version = R_2000;
if (dwg_encode (&dwg, &out_dat) >= DWG_ERR_CRITICAL)
exit (0);
free (out_dat.chain);
}
break;
#endif
#if defined(USE_WRITE)
case RW:
if (dwg_decode (&dat, &dwg) < DWG_ERR_CRITICAL)
{
out_dat.version = R_2000;
if (dwg_encode (&dwg, &out_dat) >= DWG_ERR_CRITICAL)
exit (0);
if (dwg_decode (&out_dat, &dwg) >= DWG_ERR_CRITICAL)
exit (0);
free (out_dat.chain);
}
break;
case ADD:
{
Dwg_Data *dwgp = &dwg;
if (dwg_fuzz_dat (&dwgp, &dat) == 0)
{
int error;
out_dat.byte = 0;
out_dat.bit = 0;
out_dat.from_version = dwg.header.from_version;
out_dat.version = dwg.header.version;
out_dat.opts = dwg.opts;
error = dwg_encode (&dwg, &out_dat); // dwg -> out_dat
if (error >= DWG_ERR_CRITICAL)
exit (0);
out_dat.byte = 0;
out_dat.bit = 0;
memset (&dwg, 0, sizeof (Dwg_Data));
error = dwg_decode (&out_dat, &dwg); // out_dat -> dwg
if (error >= DWG_ERR_CRITICAL)
exit (0);
}
}
break;
#endif
#if defined(USE_WRITE) && !defined(DISABLE_JSON)
case INJSON:
if (dwg_read_json (&dat, &dwg) < DWG_ERR_CRITICAL)
{
out_dat.version = R_2000;
if (dwg_encode (&dwg, &out_dat) >= DWG_ERR_CRITICAL)
exit (0);
}
break;
#endif
#ifndef DISABLE_DXF
case DXF:
if (dwg_decode (&dat, &dwg) < DWG_ERR_CRITICAL)
{
if (dwg_write_dxf (&out_dat, &dwg) >= DWG_ERR_CRITICAL)
exit (0);
}
break;
case DXFB:
if (dwg_decode (&dat, &dwg) < DWG_ERR_CRITICAL)
{
if (dwg_write_dxfb (&out_dat, &dwg) >= DWG_ERR_CRITICAL)
exit (0);
}
break;
#endif
#ifndef DISABLE_JSON
case JSON:
if (dwg_decode (&dat, &dwg) < DWG_ERR_CRITICAL)
{
if (dwg_write_json (&out_dat, &dwg) >= DWG_ERR_CRITICAL)
exit (0);
}
break;
case GEOJSON:
if (dwg_decode (&dat, &dwg) < DWG_ERR_CRITICAL)
{
if (dwg_write_geojson (&out_dat, &dwg) >= DWG_ERR_CRITICAL)
exit (0);
}
break;
#endif
case INVALID:
default:
exit (1);
}
free (out_dat.chain);
fclose (out_dat.fh);
}
dwg_free (&dwg);
return 0;
}
#if defined(USE_WRITE)
static dwg_point_2d *
scan_pts2d (unsigned num_pts, char **pp)
{
char *p = *pp;
dwg_point_2d *pts;
p = strchr (p, '(');
if (!p)
return NULL;
p++;
if (num_pts > 5000)
exit (0);
pts = calloc (num_pts, 16);
if (!pts)
exit (0);
for (unsigned i = 0; i < num_pts; i++)
{
if (sscanf (p, "(%lf %lf)", &pts[i].x, &pts[i].y))
{
p = strchr (p, ')');
if (!p)
break;
p++;
}
else
{
*pp = p;
p = NULL;
break;
}
}
if (p)
{
*pp = p;
return pts;
}
else
{
free (pts);
return NULL;
}
}
static dwg_point_3d *
scan_pts3d (unsigned num_pts, char **pp)
{
char *p = *pp;
dwg_point_3d *pts;
p = strchr (p, '(');
if (!p)
return NULL;
p++;
if (num_pts > 5000)
exit (0);
pts = calloc (num_pts, 24);
if (!pts)
exit (0);
for (unsigned i = 0; i < num_pts; i++)
{
if (sscanf (p, "(%lf %lf %lf)", &pts[i].x, &pts[i].y, &pts[i].z))
{
p = strchr (p, ')');
if (!p)
break;
p++;
}
else
{
*pp = p;
p = NULL;
break;
}
}
if (p && num_pts)
{
*pp = p;
return pts;
}
else
{
free (pts);
return NULL;
}
}
static char *
next_line (char *restrict p, const char *restrict end)
{
while (p < end && *p != '\n')
p++;
if (p < end)
p++;
return p;
}
int
dwg_fuzz_dat (Dwg_Data **restrict dwgp, Bit_Chain *restrict dat)
{
Dwg_Data *dwg;
Dwg_Object *mspace;
Dwg_Object_Ref *mspace_ref;
Dwg_Object_BLOCK_HEADER *hdr;
const char *end;
char *p;
Dwg_Version_Type version = R_INVALID;
int i = 0;
int imperial = 0;
BITCODE_BL orig_num;
if (!dat->chain)
abort ();
end = (char *)&dat->chain[dat->size - 1];
if ((p = strstr ((char *)dat->chain, "\nimperial\n")))
{
imperial = 1;
p += strlen ("\nimperial\n");
}
if ((p = strstr ((char *)dat->chain, "version")))
{
int i_ver;
char s_ver[16];
i = sscanf (p, "version %d", &i_ver);
if (i)
{
snprintf (s_ver, 16, "r%d", i_ver);
s_ver[15] = '\0';
version = dwg_version_as (s_ver);
p += strlen ("version ");
}
else
p += strlen ("version ");
p = next_line (p, end);
}
if (!i || version >= R_AFTER)
version = R_2000;
dwg = dwg_new_Document (version, imperial, 0);
*dwgp = dwg;
mspace = dwg_model_space_object (dwg);
mspace_ref = dwg_model_space_ref (dwg);
hdr = mspace->tio.object->tio.BLOCK_HEADER;
orig_num = dwg->num_objects;
// read dat line by line and call the matching add API
while (p && p < end)
{
char text[120], s1[120];
dwg_point_2d p2, p3, p4;
dwg_point_3d pt1, pt2, pt3, pt4, scale;
double height, rot, len, f1, f2;
int i1, i2;
unsigned u;
Dwg_Entity_VIEWPORT *viewport = NULL;
Dwg_Entity_MTEXT *mtext = NULL;
Dwg_Object_DICTIONARY *dictionary = NULL;
Dwg_Object_XRECORD *xrecord = NULL;
Dwg_Object_MLINESTYLE *mlinestyle = NULL;
Dwg_Object_DIMSTYLE *dimstyle = NULL;
Dwg_Object_UCS *ucs = NULL;
Dwg_Object_LAYOUT *layout = NULL;
// accepts only ASCII strings, for fuzzing only
# ifdef HAVE_SSCANF_S
# define SSCANF_S sscanf_s
# define SZ , 119
# define FMT_NAME "%[a-zA-Z0-9_]"
# define FMT_TBL "\"%[a-zA-Z0-9._ -]\""
# define FMT_PATH "\"%[a-zA-Z0-9_. \\-]\""
# define FMT_ANY "\"%s\""
# else
# define SSCANF_S sscanf
# define SZ
# define FMT_NAME "%119[a-zA-Z0-9_]"
# define FMT_TBL "\"%119[a-zA-Z0-9._ -]\""
# define FMT_PATH "\"%119[a-zA-Z0-9_. \\-]\""
# define FMT_ANY "\"%119s\""
# endif
# define SET_ENT(var, name) \
if (!var) \
; \
else if (SSCANF_S (p, #var "." FMT_NAME " = %d", &s1[0] SZ, &i1)) \
dwg_dynapi_entity_set_value (var, #name, s1, &i1, 0); \
else if (SSCANF_S (p, #var "." FMT_NAME " = %lf", &s1[0] SZ, &f1)) \
dwg_dynapi_entity_set_value (var, #name, s1, &f1, 0); \
else if (SSCANF_S (p, #var "." FMT_NAME " = " FMT_ANY, &s1[0] SZ, \
&text[0] SZ)) \
dwg_dynapi_entity_set_value (var, #name, s1, text, 1)
if (SSCANF_S (p, "line (%lf %lf %lf) (%lf %lf %lf)", &pt1.x, &pt1.y,
&pt1.z, &pt2.x, &pt2.y, &pt2.z))
dwg_add_LINE (hdr, &pt1, &pt2);
else if (SSCANF_S (p, "ray (%lf %lf %lf) (%lf %lf %lf)", &pt1.x, &pt1.y,
&pt1.z, &pt2.x, &pt2.y, &pt2.z))
dwg_add_RAY (hdr, &pt1, &pt2);
else if (SSCANF_S (p, "xline (%lf %lf %lf) (%lf %lf %lf)", &pt1.x,
&pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z))
dwg_add_XLINE (hdr, &pt1, &pt2);
else if (SSCANF_S (p, "text " FMT_ANY " (%lf %lf %lf) %lf", &text[0] SZ,
&pt1.x, &pt1.y, &pt1.z, &height))
dwg_add_TEXT (hdr, text, &pt1, height);
else if (SSCANF_S (p, "mtext (%lf %lf %lf) %lf " FMT_ANY, &pt1.x, &pt1.y,
&pt1.z, &height, &text[0] SZ))
mtext = dwg_add_MTEXT (hdr, &pt1, height, text);
else
SET_ENT (mtext, MTEXT);
else if (SSCANF_S (p, "block " FMT_TBL, &text[0] SZ))
dwg_add_BLOCK (hdr, text);
else if (memBEGINc (p, "endblk\n")) dwg_add_ENDBLK (hdr);
else if (SSCANF_S (p, "insert (%lf %lf %lf) " FMT_TBL " %lf %lf %lf %lf",
&pt1.x, &pt1.y, &pt1.z, &text[0] SZ, &scale.x,
&scale.y, &scale.z, &rot))
dwg_add_INSERT (hdr, &pt1, text, scale.x, scale.y, scale.z,
deg2rad (rot));
else if (SSCANF_S (p,
"minsert (%lf %lf %lf) " FMT_TBL
" %lf %lf %lf %lf %d %d "
"%lf %lf",
&pt1.x, &pt1.y, &pt1.z, &text[0] SZ, &scale.x,
&scale.y, &scale.z, &rot, &i1, &i2, &f1, &f2))
dwg_add_MINSERT (hdr, &pt1, text, scale.x, scale.y, scale.z,
deg2rad (rot), i1, i2, f1, f2);
else if (SSCANF_S (p, "point (%lf %lf %lf)", &pt1.x, &pt1.y, &pt1.z))
dwg_add_POINT (hdr, &pt1);
else if (SSCANF_S (p, "circle (%lf %lf %lf) %lf", &pt1.x, &pt1.y, &pt1.z,
&f1)) dwg_add_CIRCLE (hdr, &pt1, f1);
else if (SSCANF_S (p, "arc (%lf %lf %lf) %lf %lf %lf", &pt1.x, &pt1.y,
&pt1.z, &f1, &f2, &height))
dwg_add_ARC (hdr, &pt1, f1, f2, height);
else if (SSCANF_S (p,
"dimension_aligned (%lf %lf %lf) (%lf %lf %lf) (%lf "
"%lf %lf)",
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z,
&pt3.x, &pt3.y, &pt3.z))
dwg_add_DIMENSION_ALIGNED (hdr, &pt1, &pt2, &pt3);
else if (SSCANF_S (
p,
"dimension_linear (%lf %lf %lf) (%lf %lf %lf) (%lf %lf "
"%lf) %lf",
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &pt3.x,
&pt3.y, &pt3.z, &rot))
dwg_add_DIMENSION_LINEAR (hdr, &pt1, &pt2, &pt3, deg2rad (rot));
else if (SSCANF_S (
p,
"dimension_ang2ln (%lf %lf %lf) (%lf %lf %lf) (%lf %lf "
"%lf) (%lf %lf %lf)",
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &pt3.x,
&pt3.y, &pt3.z, &pt4.x, &pt4.y, &pt4.z))
dwg_add_DIMENSION_ANG2LN (hdr, &pt1, &pt2, &pt3, &pt4);
else if (SSCANF_S (
p,
"dimension_ang3pt (%lf %lf %lf) (%lf %lf %lf) (%lf %lf "
"%lf) (%lf %lf %lf)",
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &pt3.x,
&pt3.y, &pt3.z, &pt4.x, &pt4.y, &pt4.z))
dwg_add_DIMENSION_ANG3PT (hdr, &pt1, &pt2, &pt3, &pt4);
else if (SSCANF_S (p,
"dimension_diameter (%lf %lf %lf) (%lf %lf %lf) %lf",
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &len))
dwg_add_DIMENSION_DIAMETER (hdr, &pt1, &pt2, len);
else if (SSCANF_S (p,
"dimension_ordinate (%lf %lf %lf) (%lf %lf %lf) %d",
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &i1))
dwg_add_DIMENSION_ORDINATE (hdr, &pt1, &pt2, i1 ? true : false);
else if (SSCANF_S (p, "dimension_radius (%lf %lf %lf) (%lf %lf %lf) %lf",
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &len))
dwg_add_DIMENSION_RADIUS (hdr, &pt1, &pt2, len);
else if (SSCANF_S (p,
"3dface (%lf %lf %lf) (%lf %lf %lf) (%lf %lf "
"%lf) (%lf %lf %lf)",
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z,
&pt3.x, &pt3.y, &pt3.z, &pt4.x, &pt4.y, &pt4.z))
dwg_add_3DFACE (hdr, &pt1, &pt2, &pt3, &pt4);
else if (SSCANF_S (p,
"3dface (%lf %lf %lf) (%lf %lf %lf) (%lf %lf "
"%lf)",
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z,
&pt3.x, &pt3.y, &pt3.z))
dwg_add_3DFACE (hdr, &pt1, &pt2, &pt3, NULL);
else if (SSCANF_S (
p, "solid (%lf %lf %lf) (%lf %lf) (%lf %lf) (%lf %lf)",
&pt1.x, &pt1.y, &pt1.z, &p2.x, &p2.y, &p3.x, &p3.y, &p4.x,
&p4.y)) dwg_add_SOLID (hdr, &pt1, &p2, &p3, &p4);
else if (SSCANF_S (
p, "trace (%lf %lf %lf) (%lf %lf) (%lf %lf) (%lf %lf)",
&pt1.x, &pt1.y, &pt1.z, &p2.x, &p2.y, &p3.x, &p3.y, &p4.x,
&p4.y)) dwg_add_TRACE (hdr, &pt1, &p2, &p3, &p4);
else if (SSCANF_S (p, "polyline_2d %d ((%lf %lf)", &i1, &pt1.x, &pt1.y))
{
dwg_point_2d *pts = scan_pts2d (i1, &p);
if (i1 && pts)
{
dwg_add_POLYLINE_2D (hdr, i1, pts);
free (pts);
}
}
else if (SSCANF_S (p, "polyline_3d %d ((%lf %lf %lf)", &i1, &pt1.x,
&pt1.y, &pt1.z))
{
dwg_point_3d *pts = scan_pts3d (i1, &p);
if (i1 && pts)
{
dwg_add_POLYLINE_3D (hdr, i1, pts);
free (pts);
}
}
else if (SSCANF_S (p, "polyline_mesh %d %d ((%lf %lf %lf)", &i1, &i2,
&pt1.x, &pt1.y, &pt1.z))
{
dwg_point_3d *pts = scan_pts3d (i1 * i2, &p);
if (i1 && i2 && pts)
{
dwg_add_POLYLINE_MESH (hdr, i1, i2, pts);
free (pts);
}
}
else if (SSCANF_S (p, "dictionary " FMT_TBL " " FMT_TBL " %u",
&text[0] SZ, &s1[0] SZ, &u)) dictionary
= dwg_add_DICTIONARY (dwg, text, s1, (unsigned long)u);
else if (dictionary
&& SSCANF_S (p, "xrecord dictionary " FMT_TBL, &text[0] SZ))
xrecord
= dwg_add_XRECORD (dictionary, text);
else if (SSCANF_S (p, "shape " FMT_PATH " (%lf %lf %lf) %lf %lf",
&text[0] SZ, &pt1.x, &pt1.y, &pt1.z, &scale.x, &rot))
dwg_add_SHAPE (hdr, text, &pt1, scale.x, deg2rad (rot));
else if (SSCANF_S (p, "viewport " FMT_TBL, &text[0] SZ)) viewport
= dwg_add_VIEWPORT (hdr, text);
else SET_ENT (viewport, VIEWPORT);
else if (SSCANF_S (p, "ellipse (%lf %lf %lf) %lf %lf", &pt1.x, &pt1.y,
&pt1.z, &f1, &f2))
dwg_add_ELLIPSE (hdr, &pt1, f1, f2);
else if (SSCANF_S (p, "spline %d ((%lf %lf %lf)", &i1, &pt1.x, &pt1.y,
&pt1.z))
{
dwg_point_3d *fitpts = scan_pts3d (i1, &p);
if (i1 && fitpts
&& sscanf (p, ") (%lf %lf %lf) (%lf %lf %lf)", &pt2.x, &pt2.y,
&pt2.z, &pt3.x, &pt3.y, &pt3.z))
{
dwg_add_SPLINE (hdr, i1, fitpts, &pt2, &pt3);
}
free (fitpts);
}
else if (mtext
&& sscanf (p, "leader %d ((%lf %lf %lf)", &i1, &pt1.x, &pt1.y,
&pt1.z))
{
dwg_point_3d *pts = scan_pts3d (i1, &p);
if (i1 && pts && sscanf (p, ") mtext %d", &i2))
{
dwg_add_LEADER (hdr, i1, pts, mtext, i2);
}
free (pts);
}
else if (SSCANF_S (p,
"tolerance " FMT_TBL " (%lf %lf %lf) (%lf %lf %lf)",
&text[0] SZ, &pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y,
&pt2.z)) dwg_add_TOLERANCE (hdr, text, &pt1, &pt2);
else if (SSCANF_S (p, "mlinestyle " FMT_TBL, &text[0] SZ)) mlinestyle
= dwg_add_MLINESTYLE (dwg, text);
else if (SSCANF_S (p, "dimstyle " FMT_TBL, &text[0] SZ)) dimstyle
= dwg_add_DIMSTYLE (dwg, text);
else SET_ENT (mlinestyle, MLINESTYLE);
else SET_ENT (dimstyle, DIMSTYLE);
else if (SSCANF_S (
p, "ucs (%lf %lf %lf) (%lf %lf %lf) (%lf %lf %lf) " FMT_TBL,
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &pt3.x,
&pt3.y, &pt3.z, &text[0] SZ)) ucs
= dwg_add_UCS (dwg, &pt1, &pt2, &pt3, text);
else SET_ENT (ucs, UCS);
else if (viewport
&& SSCANF_S (p, "layout viewport " FMT_TBL " " FMT_ANY,
&text[0] SZ, &s1[0] SZ))
{
int error;
Dwg_Object *obj = dwg_ent_generic_to_object (viewport, &error);
if (!error)
layout = dwg_add_LAYOUT (obj, text, s1);
}
else if (SSCANF_S (p, "torus (%lf %lf %lf) (%lf %lf %lf) %lf %lf",
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &f1,
&f2)) dwg_add_TORUS (hdr, &pt1, &pt2, f1, f2);
else if (SSCANF_S (p, "sphere (%lf %lf %lf) (%lf %lf %lf) %lf", &pt1.x,
&pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &f1))
dwg_add_SPHERE (hdr, &pt1, &pt2, f1);
else if (SSCANF_S (
p, "cylinder (%lf %lf %lf) (%lf %lf %lf) %lf %lf %lf %lf",
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &height,
&f1, &f2, &len))
dwg_add_CYLINDER (hdr, &pt1, &pt2, height, f1, f2, len);
else if (SSCANF_S (p, "cone (%lf %lf %lf) (%lf %lf %lf) %lf %lf %lf %lf",
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z,
&height, &f1, &f2, &len))
dwg_add_CONE (hdr, &pt1, &pt2, height, f1, f2, len);
else if (SSCANF_S (p, "wedge (%lf %lf %lf) (%lf %lf %lf) %lf %lf %lf",
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &len,
&f1, &height))
dwg_add_WEDGE (hdr, &pt1, &pt2, len, f1, height);
else if (SSCANF_S (p, "box (%lf %lf %lf) (%lf %lf %lf) %lf %lf %lf",
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &len,
&f1, &height))
dwg_add_BOX (hdr, &pt1, &pt2, len, f1, height);
else if (SSCANF_S (p,
"pyramid (%lf %lf %lf) (%lf %lf %lf) %lf %d %lf %lf",
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z,
&height, &i1, &f1, &f2))
dwg_add_PYRAMID (hdr, &pt1, &pt2, height, i1, f1, f2);
else if (SSCANF_S (p, "HEADER." FMT_NAME " = %d", &s1[0] SZ, &i1))
dwg_dynapi_header_set_value (dwg, s1, &i1, 0);
else if (SSCANF_S (p, "HEADER." FMT_NAME " = %lf", &s1[0] SZ, &f1))
dwg_dynapi_header_set_value (dwg, s1, &f1, 0);
else if (SSCANF_S (p, "HEADER." FMT_NAME " = " FMT_ANY, &s1[0] SZ,
&text[0] SZ))
dwg_dynapi_header_set_value (dwg, s1, text, 1);
p = next_line (p, end);
}
// dwg_resolve_objectrefs_silent (orig_dwg);
// start fuzzing if at least 2 entities were added.
return (dwg->num_objects - orig_num > 2 ? 0 : 1);
}
#endif // USE_WRITE

View File

@@ -0,0 +1,335 @@
/*****************************************************************************/
/* LibreDWG - free implementation of the DWG file format */
/* */
/* Copyright (C) 2021, 2023 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/>. */
/*****************************************************************************/
/*
* llvmfuzz.c: libfuzzer testing, esp. for oss-fuzz. with libfuzzer or
* standalone written by Reini Urban
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
//#include <unistd.h>
#include <sys/stat.h>
#include "common.h"
#include <dwg.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
#include "decode.h"
#include "encode.h"
#include "bits.h"
#ifndef DISABLE_DXF
# include "out_dxf.h"
# ifndef DISABLE_JSON
# include "in_json.h"
# include "out_json.h"
# endif
# include "in_dxf.h"
#endif
int out;
int ver;
extern int LLVMFuzzerTestOneInput (const unsigned char *data, size_t size);
// libfuzzer limitation:
// Enforce NULL-termination of the input buffer, to avoid bogus reports. copy
// it. Problematic is mostly strtol(3) which also works with \n termination.
static int
enforce_null_termination (Bit_Chain *dat, bool enforce)
{
unsigned char *copy;
unsigned char c;
if (!dat->size)
return 0;
c = dat->chain[dat->size - 1];
// Allow \n termination without \0 in DXF? No, still crashes
if (!enforce && ((c == '\n' && c + 1 == '\0') || c == '\0'))
return 0;
#ifdef STANDALONE
fprintf (stderr,
"llvmfuzz_standalone: enforce libfuzzer buffer NULL termination\n");
#endif
copy = malloc (dat->size + 1);
memcpy (copy, dat->chain, dat->size);
copy[dat->size] = '\0';
dat->chain = copy;
return 1;
}
int
LLVMFuzzerTestOneInput (const unsigned char *data, size_t size)
{
Dwg_Data dwg;
Bit_Chain dat = { NULL, 0, 0, 0, 0, 0, 0, NULL, 0 };
Bit_Chain out_dat = { NULL, 0, 0, 0, 0, 0, 0, NULL, 0 };
int copied = 0;
struct ly_ctx *ctx = NULL;
static char tmp_file[256];
dat.chain = (unsigned char *)data;
dat.size = size;
memset (&dwg, 0, sizeof (dwg));
// Detect the input format: DWG, DXF or JSON
if (dat.size > 2 && dat.chain[0] == 'A' && dat.chain[1] == 'C')
{
if (dwg_decode (&dat, &dwg) >= DWG_ERR_CRITICAL)
{
dwg_free (&dwg);
return 0;
}
}
#ifndef DISABLE_JSON
else if (dat.size > 1 && dat.chain[0] == '{')
{
copied = enforce_null_termination (&dat, true);
if (dwg_read_json (&dat, &dwg) >= DWG_ERR_CRITICAL)
{
if (copied)
bit_chain_free (&dat);
dwg_free (&dwg);
return 0;
}
dat.opts |= DWG_OPTS_INJSON;
dwg.opts |= DWG_OPTS_INJSON;
}
#endif
#ifndef DISABLE_DXF
else
{
copied = enforce_null_termination (&dat, false);
if (dwg_read_dxf (&dat, &dwg) >= DWG_ERR_CRITICAL)
{
if (copied)
bit_chain_free (&dat);
dwg_free (&dwg);
return 0;
}
}
#else
else
return 0;
#endif
memset (&out_dat, 0, sizeof (out_dat));
bit_chain_set_version (&out_dat, &dat);
if (copied)
bit_chain_free (&dat);
#if 0
snprintf (tmp_file, 255, "/tmp/llvmfuzzer%d.out", getpid());
tmp_file[255] = '\0';
#elif defined _WIN32
strcpy (tmp_file, "NUL");
#else
strcpy (tmp_file, "/dev/null");
#endif
out_dat.fh = fopen (tmp_file, "w");
switch (out)
{
case 0:
{
switch (ver)
{
// TODO support preR13, many downconverters still missing
case 0:
out_dat.version = dwg.header.version = R_1_4;
break;
case 1:
out_dat.version = dwg.header.version = R_2_0;
break;
case 2:
out_dat.version = dwg.header.version = R_2_10;
break;
case 3:
out_dat.version = dwg.header.version = R_2_21;
break;
case 4:
out_dat.version = dwg.header.version = R_2_4;
break;
case 5:
out_dat.version = dwg.header.version = R_2_6;
break;
case 6:
out_dat.version = dwg.header.version = R_9;
break;
case 7:
out_dat.version = dwg.header.version = R_10;
break;
case 8:
out_dat.version = dwg.header.version = R_11;
break;
case 9:
out_dat.version = dwg.header.version = R_12;
break;
case 10:
out_dat.version = dwg.header.version = R_13;
break;
case 11:
out_dat.version = dwg.header.version = R_13c3;
break;
case 12:
out_dat.version = dwg.header.version = R_14;
break;
case 13:
out_dat.version = dwg.header.version = R_2004;
break;
default: // favor this one
out_dat.version = dwg.header.version = R_2000;
break;
}
dwg_encode (&dwg, &out_dat);
break;
}
#ifndef DISABLE_DXF
case 1:
dwg_write_dxf (&out_dat, &dwg);
break;
case 2: // experimental
dwg_write_dxfb (&out_dat, &dwg);
break;
# ifndef DISABLE_JSON
case 3:
dwg_write_json (&out_dat, &dwg);
break;
case 4:
dwg_write_geojson (&out_dat, &dwg);
break;
# endif
#endif
default:
break;
}
dwg_free (&dwg);
free (out_dat.chain);
fclose (out_dat.fh);
// unlink (tmp_file);
return 0;
}
#ifdef STANDALONE
/*
# ifdef __GNUC__
__attribute__((weak))
# endif
extern int LLVMFuzzerInitialize(int *argc, char ***argv);
*/
static int
usage (void)
{
printf ("\nUsage: OUT=0 VER=3 llvmfuzz_standalone INPUT...");
return 1;
}
// llvmfuzz_standalone reproducer, see OUT and VER env vars
int
main (int argc, char *argv[])
{
unsigned seed;
const unsigned int possible_outputformats =
#ifdef DISABLE_DXF
# ifdef DISABLE_JSON
1;
# else
3;
# endif
#else
5;
#endif
if (argc <= 1 || !*argv[1])
return usage ();
if (getenv ("SEED"))
seed = (unsigned)strtol (getenv ("SEED"), NULL, 10) % 9999;
else
{
#ifdef HAVE_GETTIMEOFDAY
struct timeval tval;
gettimeofday (&tval, NULL);
seed = (unsigned)(tval.tv_sec * 1000 + tval.tv_usec) % 9999;
#else
seed = (unsigned)time (NULL) % 9999;
#endif
}
srand (seed);
/* works only on linux
if (LLVMFuzzerInitialize)
LLVMFuzzerInitialize (&argc, &argv);
*/
for (int i = 1; i < argc; i++)
{
unsigned char *buf;
FILE *f = fopen (argv[i], "rb");
struct stat attrib;
long len;
size_t n_read;
int fd;
if (!f)
{
fprintf (stderr, "Illegal file argument %s\n", argv[i]);
continue;
}
fd = fileno (f);
if (fd < 0 || fstat (fd, &attrib)
|| !(S_ISREG (attrib.st_mode)
# ifndef _WIN32
|| S_ISLNK (attrib.st_mode)
# endif
))
{
fprintf (stderr, "Illegal input file \"%s\"\n", argv[i]);
continue;
}
// libFuzzer design bug, not zero-terminating its text buffer
fseek (f, 0, SEEK_END);
len = ftell (f);
fseek (f, 0, SEEK_SET);
if (len <= 0)
continue;
buf = (unsigned char *)malloc (len);
n_read = fread (buf, 1, len, f);
fclose (f);
assert ((long)n_read == len);
out = rand () % possible_outputformats;
#ifdef STANDALONE
if (getenv ("OUT"))
out = strtol (getenv ("OUT"), NULL, 10);
// print SEED onlyu when needed (no env vars given)
if (!(out || getenv ("VER")))
fprintf (stderr, "SEED=%04u ", seed);
fprintf (stderr, "OUT=%d ", out);
#endif
if (out == 0)
{
ver = rand () % 20;
#ifdef STANDALONE
if (getenv ("VER"))
ver = strtol (getenv ("VER"), NULL, 10);
fprintf (stderr, "VER=%d ", ver);
#endif
}
fprintf (stderr, "examples/llvmfuzz_standalone %s [%" PRIuSIZE "]\n",
argv[i], len);
LLVMFuzzerTestOneInput (buf, len);
free (buf);
// Bit_Chain dat = { 0 };
// dat_read_file (&dat, fp, argv[i]);
// LLVMFuzzerTestOneInput (dat.chain, dat.size);
// bit_free_chain (&dat);
}
}
#endif

View File

@@ -0,0 +1,230 @@
/*****************************************************************************/
/* LibreDWG - free implementation of the DWG file format */
/* */
/* Copyright (C) 2009, 2023 Free Software Foundation, Inc. */
/* Copyright (C) 2010 Thien-Thi Nguyen */
/* */
/* 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/>. */
/*****************************************************************************/
/*
* load_dwg.c: load a DWG, get lines, text and circles
* written by Felipe Castro
* modified by Felipe Corrêa da Silva Sances
* modified by Thien-Thi Nguyen
* modified by Reini Urban
*/
#include "config.h"
#ifdef __STDC_ALLOC_LIB__ /* for strdup */
# define __STDC_WANT_LIB_EXT2__ 1 /* for strdup */
#else
# define _USE_BSD 1
#endif
#ifndef _XOPEN_SOURCE /* for strdup, snprintf */
# define _XOPEN_SOURCE 700
#endif
#include <stdio.h>
#include <time.h>
#ifndef DISABLE_WRITE
# include <sys/stat.h>
# include <unistd.h>
#endif
#include "dwg.h"
#include "dwg_api.h"
#include "../src/bits.h"
#include "../programs/suffix.inc"
static int help (void);
int verbosity (int argc, char **argv, int i, unsigned int *opts);
#include "../programs/common.inc"
static int
usage (void)
{
printf ("\nUsage: load_dwg [-v[0-9]] DWGFILE\n");
return 1;
}
static int
opt_version (void)
{
printf ("load_dwg %s\n", PACKAGE_VERSION);
return 0;
}
static int
help (void)
{
printf ("\nUsage: load_dwg [OPTION]... DWGFILE\n");
printf ("Example to add fingerprint elements to a DWG.\n"
"\n");
printf (" -v[0-9], --verbose [0-9] verbosity\n");
printf (" --help display this help and exit\n");
printf (" --version output version information and exit\n"
"\n");
printf ("GNU LibreDWG online manual: "
"<https://www.gnu.org/software/libredwg/>\n");
return 0;
}
static int
add_fingerprint (Dwg_Data *dwg, dwg_point_3d *pt)
{
int error = 0;
char text[128];
double height = dwg->header_vars.TEXTSIZE;
time_t t = time (NULL);
Dwg_Object_BLOCK_HEADER *hdr = dwg_get_block_header (dwg, &error);
Dwg_Entity_TEXT *ent;
if (error)
return 1;
#ifdef HAVE_WFORMAT_Y2K
GCC46_DIAG_IGNORE (-Wformat-y2k)
#endif
strftime (text, sizeof (text), "Last updated: %c", localtime (&t));
#ifdef HAVE_WFORMAT_Y2K
GCC46_DIAG_RESTORE
#endif
#ifdef USE_WRITE
if ((ent = dwg_add_TEXT (hdr, text, pt, height)))
{
ent->horiz_alignment = HORIZ_ALIGNMENT_RIGHT;
return 0;
}
else
#endif
return 1;
}
static int
change_fingerprint (Dwg_Data *dwg, Dwg_Entity_TEXT *_obj)
{
char text[128];
double height = dwg->header_vars.TEXTSIZE;
time_t t = time (NULL);
#ifdef HAVE_WFORMAT_Y2K
GCC46_DIAG_IGNORE (-Wformat-y2k)
#endif
strftime (text, sizeof (text), "Last updated: %c", localtime (&t));
#ifdef HAVE_WFORMAT_Y2K
GCC46_DIAG_RESTORE
#endif
if (dwg->header.version < R_2007)
{
if (strlen (text) < strlen (_obj->text_value))
strcpy (_obj->text_value, text);
else
{
free (_obj->text_value);
_obj->text_value = strdup (text);
}
}
else
{
free (_obj->text_value);
_obj->text_value = (BITCODE_TV)bit_utf8_to_TU (text, 0);
}
return 0;
}
static int
load_dwg (char *filename, unsigned int opts)
{
BITCODE_BL i;
int success, found = 0;
Dwg_Data dwg;
dwg_point_3d pt;
#ifdef USE_WRITE
char *new_filename = (char *)malloc (strlen (filename) + 4);
char *fn = strdup (filename);
char *base = basename (fn);
char *p;
struct stat st;
if ((p = strrchr (base, '.')))
*p = '\0';
sprintf (new_filename, "%s_new.dwg", base);
free (fn);
#endif
memset (&dwg, 0, sizeof (Dwg_Data));
dwg.opts = opts;
success = dwg_read_file (filename, &dwg);
// get the insertion point for our fingerprint
pt.x = dwg.header_vars.LIMMAX.x;
pt.y = dwg.header_vars.LIMMAX.y;
pt.z = 0.0;
// check if a fingerprint already exists there.
// if so update it. if not add it
for (i = 0; i < dwg.num_objects; i++)
{
if (dwg.object[i].fixedtype == DWG_TYPE_TEXT)
{
Dwg_Entity_TEXT *_obj = dwg.object[i].tio.entity->tio.TEXT;
if (pt.x == _obj->ins_pt.x && pt.y == _obj->ins_pt.y
&& _obj->horiz_alignment == HORIZ_ALIGNMENT_RIGHT)
{
found++;
change_fingerprint (&dwg, _obj);
fprintf (stderr, "fingerprint updated at (%f, %f)\n", pt.x,
pt.y);
}
}
}
if (!found)
{
add_fingerprint (&dwg, &pt);
fprintf (stderr, "fingerprint added at (%f, %f)\n", pt.x, pt.y);
}
#ifdef USE_WRITE
if (0 == stat (new_filename, &st))
unlink (new_filename);
if (dwg.header.version > R_2000)
dwg.header.version = R_2000;
success = dwg_write_file (new_filename, &dwg);
free (new_filename);
#endif
dwg_free (&dwg);
return success;
}
int
main (int argc, char *argv[])
{
int i = 1;
unsigned int opts = 0;
if (argc < 2)
return usage ();
#if defined(USE_TRACING) && defined(HAVE_SETENV)
setenv ("LIBREDWG_TRACE", "1", 0);
#endif
if (argc > 2
&& (!strcmp (argv[i], "--verbose") || !strncmp (argv[i], "-v", 2)))
{
int num_args = verbosity (argc, argv, i, &opts);
argc -= num_args;
i += num_args;
}
if (argc > 1 && !strcmp (argv[i], "--help"))
return help ();
if (argc > 1 && !strcmp (argv[i], "--version"))
return opt_version ();
REQUIRE_INPUT_FILE_ARG (argc);
load_dwg (argv[i], opts);
return 0;
}

View File

@@ -0,0 +1,76 @@
/*****************************************************************************/
/* LibreDWG - free implementation of the DWG file format */
/* */
/* Copyright (C) 2023 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/>. */
/*****************************************************************************/
/*
* odaversion.c: prints the ODA compatible DWG version
* modified by Reini Urban
oda understands those versions:
"ACAD9","ACAD10","ACAD12",
"ACAD13","ACAD14",
"ACAD2000","ACAD2004",
"ACAD2007","ACAD2010",
"ACAD2013","ACAD2018"
*/
#include <stdio.h>
int
main (int argc, char *argv[])
{
FILE *f;
char buf[7];
size_t size;
if (argc != 2)
return 1;
f = fopen (argv[1], "rb");
if (!f)
return 1;
size = fread (buf, 1, 6, f);
if (size != 6)
return 1;
buf[6] = '\0';
if (buf[0] == 'A' && buf[1] == 'C')
{
int v;
if (1 != sscanf (buf, "AC%4d", &v))
return 1;
if (v < 1004) // <r9
printf ("\n");
else if (v <= 1005)
printf ("9\n");
else if (v <= 1006)
printf ("10\n");
else if (v <= 1009)
printf ("11\n");
else if (v <= 1012)
printf ("13\n");
else if (v <= 1014)
printf ("14\n");
else if (v <= 1016)
printf ("2000\n");
else if (v <= 1018)
printf ("2004\n");
else if (v <= 1021)
printf ("2007\n");
else if (v <= 1024)
printf ("2010\n");
else if (v < 1028)
printf ("2013\n");
else if (v < 1033)
printf ("2018\n");
else
printf ("\n");
}
fclose (f);
return 0;
}

View File

@@ -0,0 +1,15 @@
#include <stdio.h>
#include <stdlib.h>
unsigned char block[255];
main ()
{
int len, err;
while (!feof (stdin))
{
len = fread (block, 1, 255, stdin);
err = rs_decode_block (block, 1);
fwrite (block, 1, 239, stdout);
}
}

View File

@@ -0,0 +1,28 @@
#include <stdio.h>
#include <stdlib.h>
unsigned char data[239];
unsigned char parity[16];
main ()
{
int len, i;
while (!feof (stdin))
{
len = fread (data, 1, 239, stdin);
rs_encode_block (parity, data, len);
for (i = 0; i < 16; i++)
{
if (i != 0)
fputc ('-', stderr);
}
fwrite (data, 1, len, stdout);
while (len++ < 239)
fputc (0, stdout); /* Pad data with 0s */
fwrite (parity, 16, 1, stdout);
}
}

File diff suppressed because it is too large Load Diff