/* Scan DWG program -- for scanning a DWG file Copyright (C) 1995, 1996 Frans Faase, Reini Urban This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Authors: Frans Faase, http://www.iwriteiam.nl/ Reini Urban, rurban at sbox.tu-graz.ac.at Contributions by: Stan Hunkins, shunkins@msn.com GNU General Public License: http://home.wxs.nl/~faase009/GNU.txt */ /*-----------------22.10.95 22:59------------------- changed by Reini Urban: new features: Julian dates formatted DIMSTYLE Table section (former P12) VIEW Table section (former P8) UCS Table section (former P9) VPORT Table section found some header vars from the active VPORT at scan_header() changed ADS to APPID in table section group 3 in BLOCK entity with opt 2 for debugging: defined POINTER_VALUE changed all pointer output from long to hex "%ld" -> "%05lX" (for my hex editor) added output of pointer values to some functions in []: echo_16_bytes(), get_pointer() moved rest of header to scan_header() comment: somewhere the last handle must be stored, (only in the DWG, not in the DXF) missing flags opts: 01 01 PLINE 01 01 VERTEX 01 S/BEND 40 INSERT --------------------------------------------------*/ #include #include #include #include #include #define TRUE 1 #define FALSE 0 #define DEBUG_P(X) printf X #define MIN(x,y) ((x) < (y) ? (x) : (y)) typedef unsigned char byte; typedef unsigned int word; typedef unsigned long int longword; typedef int bool; #define POINTER_VALUE longword cur_pos, last_pos; typedef struct { longword start, nr; word size; } ttable, *ptable; /* prototypes: */ int main(int argc, char *argv[]); void scan_table_position(char *name, ptable pt); void check_table_pos(char *name, ptable pt, int t_nr); void scan_header(void); void scan_blocks(ptable pt); void scan_layers(ptable pt); void scan_styles(ptable pt); void scan_ltypes(ptable pt); void scan_ads_table(ptable pt); /* new name */ void scan_ucs_table(char *name, ptable pt); void scan_view_table(char *name, ptable pt); void scan_vport_table(char *name, ptable pt); void scan_dim_table(ptable pt); void scan_table(char *name, ptable pt); void scan_entities(longword start, longword endi, longword sce_offset); void scan_xdata(void); void scan_handle(void); void scan_point(bool z_coord); void scan_fixed_ident(int len); void echo_16_bytes(word len); void echo_bytes(long int len); longword get_pointer(); void check_pointer(longword p); void get_check_2(void); void get_check_32(void); void skip_to_check_2(longword p); void goto_pointer(longword p); /* fio prototypes: */ void _assign(FILE *file); longword _tell(void); void _seek(long int pos); void _advance(word steps); bool _eof(void); byte _read_byte(void); short _read_word(void); longword _read_long(void); double _read_date(void); float _read_float(); double _read_double(void); char *_read_string(void); char *_read_fixed_string(int len); /*-----------------25.10.95 21:47------------------- conversion from julian date to string --------------------------------------------------*/ char *date_string (char *s, double date); longword pointer[20]; #define P_ENTITIES 0 #define P_ENTEND 1 #define P_BLOCKSEC 2 #define P_BSEND 3 ttable table[11]; /*-----------------22.10.95 00:56------------------- missing tables VIEW, UCS, VPORT added */ #define T_BLOCK 1 #define T_LAYER 2 #define T_STYLE 3 #define T_LTYPE 4 #define T_VIEW 5 /* changed */ #define T_UCS 6 /* changed */ #define T_VPORT 7 #define T_APPID 8 /* APPID section */ #define T_DIMSTYLE 9 #define T_13 10 static bool version_13 = FALSE; int main(int argc, char *argv[]) { char version[13]; { char *file1 = NULL; word i; bool error = FALSE; FILE *f; for (i = 1; i < argc && !error ; i++) { if (argv[i][0] == '/') { printf("No options"); error = TRUE; } else if (file1 == NULL) file1 = argv[i]; else { printf("dwg: too many arguments\n\n"); error = TRUE; } } if (!error && file1 == NULL) { printf("dwg: too few arguments.\n\n"); error = TRUE; } if (error) { printf("Usages: dwg file1\n"); return 2; } if (!(f = fopen(file1, "rb"))) { printf("dwg: cannot open %s - No such file\n", file1); return 2; } _assign(f); } strcpy(version, _read_fixed_string(12)); DEBUG_P(("Version: %s", version)); version_13 = !strcmp(version, "AC1010"); { int b1 = _read_byte(), w1 = _read_word(), w2 = _read_word(), w3 = _read_word(), b2 = _read_byte(); DEBUG_P((" %d %d %d %d %d\n", b1, w1, w2, w3, b2)); } pointer[P_ENTITIES] = _read_long(); pointer[P_ENTEND] = _read_long(); DEBUG_P(("ENTITIES (%05lX-%05lX)\n", pointer[P_ENTITIES], pointer[P_ENTEND])); DEBUG_P(("BLOCK SECTION ")); pointer[P_BLOCKSEC] = get_pointer(); echo_bytes(4); pointer[P_BSEND] = get_pointer(); echo_bytes(4); DEBUG_P(("\n")); DEBUG_P(("BSEC (%05lX-%05lX)\n", pointer[P_BLOCKSEC], pointer[P_BSEND])); scan_table_position("BLOCK", &table[T_BLOCK]); scan_table_position("LAYER", &table[T_LAYER]); scan_table_position("STYLE", &table[T_STYLE]); scan_table_position("LTYPE", &table[T_LTYPE]); scan_table_position("VIEW", &table[T_VIEW]); DEBUG_P(("HEADER\n")); scan_header(); scan_table_position("UCS", &table[T_UCS]); echo_bytes(0x500 - cur_pos); scan_table_position("VPORT", &table[T_VPORT]); echo_bytes(8); scan_table_position("APPID", &table[T_APPID]); echo_bytes(6); scan_table_position("DIMSTYLE", &table[T_DIMSTYLE]); /* prev. P12 */ echo_bytes(0x69F - cur_pos); scan_table_position("P13", &table[T_13]); echo_bytes(38); scan_entities(pointer[P_ENTITIES], pointer[P_ENTEND], 0L); echo_bytes(19); scan_blocks(&table[T_BLOCK]); scan_layers(&table[T_LAYER]); scan_styles(&table[T_STYLE]); scan_ltypes(&table[T_LTYPE]); scan_view_table("VIEW TABLE", &table[T_VIEW]); /* new */ scan_ucs_table("UCS TABLE", &table[T_UCS]); /* new */ scan_vport_table("VPORT TABLE", &table[T_VPORT]);/* new */ scan_ads_table(&table[T_APPID]); /* new name */ scan_dim_table(&table[T_DIMSTYLE]); /* new */ scan_table("P13 TABLE", &table[T_13]); DEBUG_P(("BLOCK SECTION\n")); scan_entities(pointer[P_BLOCKSEC], pointer[P_BSEND], pointer[P_BLOCKSEC] - 0x40000000); DEBUG_P(("P3\n")); /* new Header vars */ echo_bytes(36); check_pointer(pointer[P_ENTITIES]); check_pointer(pointer[P_ENTEND]); check_pointer(pointer[P_BLOCKSEC]); check_pointer(pointer[P_BSEND]); echo_bytes(12); check_table_pos("BLOCK", &table[T_BLOCK], 1); check_table_pos("LAYER", &table[T_LAYER], 2); check_table_pos("STYLE", &table[T_STYLE], 3); check_table_pos("LTYPE", &table[T_LTYPE], 5); check_table_pos("VIEW", &table[T_VIEW], 6); check_table_pos("UCS", &table[T_UCS], 7); check_table_pos("VPORT", &table[T_VPORT], 8); check_table_pos("APPID", &table[T_APPID], 9); check_table_pos("DIMSTYLE", &table[T_DIMSTYLE], 10); check_table_pos("P13", &table[T_13], 11); DEBUG_P(("P?: ")); get_pointer(); echo_bytes(last_pos - cur_pos); return 0; } void scan_table_position(char *name, ptable pt) { pt->size = _read_word(); pt->nr = _read_long(); pt->start = _read_long(); DEBUG_P(("%-8.8s %05lX size: %3d (%05lX-%05lX)\n", name, pt->nr, pt->size, pt->start, pt->start + pt->size * pt->nr)); } void check_table_pos(char *name, ptable pt, int t_nr) { word t, size, nr; longword start; t = _read_word(); size = _read_word(); nr = _read_word(); start = _read_long(); printf("%-8.8s %05x size: %3d (%05lx) table:%d", name, nr, size, start, t); if (t != t_nr) printf(" t %d!=%d", t, t_nr); if (nr != (pt->nr & 0xFFFF)) printf(" nr %d!=%ld", nr, pt->nr); if (size != pt->size) printf(" size %d!=%d", size, pt->size); if (start != pt->start) printf(" start %ld!=%ld", start, pt->start); printf("\n"); } void scan_header() { char tmpstr[40]; double date; DEBUG_P(("\n?w %d", _read_word())); DEBUG_P(("\n$INSBASE ")); scan_point(TRUE); DEBUG_P(("\n$EXTMIN ")); scan_point(TRUE); DEBUG_P(("\n$EXTMAX ")); scan_point(TRUE); DEBUG_P(("\n$LIMMIN ")); scan_point(FALSE); DEBUG_P(("\n$LIMMAX ")); scan_point(FALSE); /*-----------------22.10.95 01:01------------------- active vport: groups 12 ?? 40 --------------------------------------------------*/ DEBUG_P(("\n$VIEWCTR (%f,%f) ", _read_double() , _read_double())); DEBUG_P(("\nf? %f " , _read_double())); /*?*/ DEBUG_P(("\n$VIEWSIZE %f " , _read_double())); DEBUG_P(("\nw? %d ", _read_word())); /*-----------------22.10.95 01:01------------------- active vport: groups 14 or 15 --------------------------------------------------*/ DEBUG_P(("\n$SNAPUNIT (%f,%f) ", _read_double() , _read_double())); echo_bytes(56); DEBUG_P(("\nf? %f ", _read_double())); DEBUG_P(("\nf? %f ", _read_double())); DEBUG_P(("\nf? %f ", _read_double())); echo_bytes(18); DEBUG_P(("\nf? %f ", _read_double())); /* rest of header */ DEBUG_P(("\nw? %d ", _read_word())); DEBUG_P(("\nw? %d ", _read_word())); echo_bytes(44); /* DEBUG_P(("\nf? %f ", _read_double())); echo_bytes(12); */ /* menuname: length of pathstr 128 ?? */ echo_bytes((22*16)+2); DEBUG_P(("\n$DIMBLK: %s ", _read_fixed_string(32))); DEBUG_P(("\nb? %d ", _read_byte())); DEBUG_P(("\nb? %d ", _read_byte())); DEBUG_P(("\nw? %d ", _read_word())); DEBUG_P(("\nw? %d ", _read_word())); DEBUG_P(("\nb? %d ", _read_byte())); DEBUG_P(("\nb? %d ", _read_byte())); DEBUG_P(("\nb? %d ", _read_byte())); date = _read_date(); DEBUG_P(("\n$TDCREATE: %.8f %s ", date, date_string(tmpstr,date))); /* at 0x31E */ date = _read_date(); DEBUG_P(("\n$TDUPDATE: %.8f %s ", date, date_string(tmpstr,date))); /* at 0x327 */ echo_bytes(0x379 - cur_pos); DEBUG_P(("\nf? %f ", _read_double())); echo_bytes(0x3c5 - cur_pos); DEBUG_P(("\nf? %f ", _read_double())); DEBUG_P(("\nf? %f ", _read_double())); echo_bytes(0x3EF - cur_pos); } void scan_blocks(ptable pt) { longword i; DEBUG_P(("\nBLOCK TABLE\n")); for (i = 0L; i < pt->nr; i++) { longword begin = pt->start + i * pt->size, end = begin + pt->size - 2; byte flag, b1, b2; word used, w1, w2, w3, w4; goto_pointer(begin); flag = _read_byte(); scan_fixed_ident(32); used = _read_word(); b1 = _read_byte(); w1 = _read_word(); b2 = _read_byte(); w3 = _read_word(); w4 = _read_word(); DEBUG_P(("%02x %5d %3d %5d %3d %5d %5d %5d", flag, used, b1, w1, b2, w2, w3, w4)); skip_to_check_2(end); } get_check_32(); } void scan_layers(ptable pt) { longword i; DEBUG_P(("\nLAYER TABLE\n")); for (i = 0L; i < pt->nr; i++) { longword begin = pt->start + i * pt->size, end = begin + pt->size - 2; int flag, used, color, style; goto_pointer(begin); flag = _read_byte(); scan_fixed_ident(32); used = _read_word(); color = _read_word(); style = _read_word(); DEBUG_P(("%6d %s %s %s %s color: %3d ltype: %3d ", used, color < 0 ? "off" : "on ", flag & 1 ? "fr" : " ", flag & 4 ? "lc" : " ", flag & 64 ? " " : "used", color < 0 ? -color : color, style)); skip_to_check_2(end); } get_check_32(); } void scan_styles(ptable pt) { longword i; DEBUG_P(("\nSTYLE TABLE\n")); for (i = 0L; i < pt->nr; i++) { longword begin = pt->start + i * pt->size, end = begin + pt->size - 2; int flag; goto_pointer(begin); printf("%02X ", flag = _read_byte()); scan_fixed_ident(32); printf("?w: %5d ", _read_word()); printf("%f ", _read_double()); printf("%f ", _read_double()); printf("%f ", _read_double()); printf("%02X ",_read_byte()); printf("%f ", _read_double()); printf("`%s'", _read_fixed_string(128)); skip_to_check_2(end); } get_check_32(); } void scan_ltypes(ptable pt) { longword i; DEBUG_P(("\nLTYPE TABLE\n")); for (i = 0L; i < pt->nr; i++) { longword begin = pt->start + i * pt->size, end = begin + pt->size - 2; goto_pointer(begin); printf("%02X ", _read_byte()); scan_fixed_ident(32); printf("%5d ", _read_word()); printf("`%s' ", _read_fixed_string(48)); printf("%02X ", _read_byte()); { word j, k = _read_byte(); for (j = 0; j < 13; j++) printf("%s%f ", j < k ? "" : "*", _read_double()); } skip_to_check_2(end); } get_check_32(); } void scan_ads_table(ptable pt) { longword i; DEBUG_P(("\nAPPID TABLE\n")); for (i = 0L; i < pt->nr; i++) { longword begin = pt->start + i * pt->size, end = begin + pt->size - 2; goto_pointer(begin); printf("%02X ", _read_byte()); scan_fixed_ident(32); printf("?w: %5d ", _read_word()); skip_to_check_2(end); } get_check_32(); } #define OPTS(X) if (opts & (1 << (X-1))) #define SCAN_POINT(G,C) { printf(" %d:", G); scan_point(C); } #define SCAN_DOUBLE(G) printf(" %d:%f", G, _read_double()); #define SCAN_STRING(G) printf(" %d:`%s'", G, _read_string()); /* new */ #define SCAN_FIXED_STRING(G,L) printf(" %d:`%s'", G, _read_fixed_string(L)); #define SCAN_BYTE(G) printf(" %d:%02X", G, _read_byte()); #define SCAN_WORD(G) printf(" %d:%d", G, _read_word()); #define SCAN_LONG(G) printf(" %d:%ld", G, _read_long()); /*-----------------23.10.95 11:14------------------- new: --------------------------------------------------*/ void scan_dim_table(ptable pt) { longword i; DEBUG_P(("\nDIMSTYLE TABLE\n")); for (i = 0L; i < pt->nr; i++) { longword begin = pt->start + i * pt->size, end = begin + pt->size - 2; int flag; goto_pointer(begin); printf("70: %02X ", flag = _read_byte()); scan_fixed_ident(32); printf("?w: %5d ", _read_word()); printf ("\n"); SCAN_DOUBLE(40); /* DIMSCALE: */ SCAN_DOUBLE(41); /* DIMASZ: */ SCAN_DOUBLE(42); /* DIMEXO: */ SCAN_DOUBLE(43); /* DIMDLI: */ SCAN_DOUBLE(44); /* DIMEXE: */ SCAN_DOUBLE(45); /* DIMRND: */ SCAN_DOUBLE(46); /* DIMDLE: */ SCAN_DOUBLE(47); /* DIMTP: */ SCAN_DOUBLE(48); /* DIMTM: */ printf ("\n"); SCAN_DOUBLE(140); /* DIMTXT : */ SCAN_DOUBLE(141); /* DIMCEN : */ SCAN_DOUBLE(142); /* DIMTSZ : */ SCAN_DOUBLE(143); /* DIMALTF: */ SCAN_DOUBLE(144); /* DIMLFAC: */ SCAN_DOUBLE(145); /* DIMTVP : */ printf ("\n"); SCAN_BYTE (71); SCAN_BYTE (72); SCAN_BYTE (73); SCAN_BYTE (74); SCAN_BYTE (75); SCAN_BYTE (76); SCAN_BYTE (77); SCAN_BYTE (78); printf ("\n"); SCAN_BYTE (170); SCAN_BYTE (171); SCAN_BYTE (172); SCAN_BYTE (173); SCAN_BYTE (174); /*?*/ SCAN_BYTE (175); /*?*/ SCAN_FIXED_STRING (3,16); /* length ? */ SCAN_FIXED_STRING (4,16); /* length ? */ SCAN_FIXED_STRING (5,32); SCAN_FIXED_STRING (6,32); SCAN_FIXED_STRING (7,32); echo_bytes (3); /*?*/ SCAN_WORD (176); /* Colors as int ? */ SCAN_WORD (177); SCAN_WORD (178); SCAN_DOUBLE(146); /* DIMTFAC */ SCAN_DOUBLE(147); /* DIMDIST */ skip_to_check_2(end); } get_check_32(); } /*-----------------23.10.95 11:14------------------- new: --------------------------------------------------*/ void scan_view_table(char *name, ptable pt) { longword i; DEBUG_P(("\n%s\n", name)); for (i = 0L; i < pt->nr; i++) { longword begin = pt->start + i * pt->size, end = begin + pt->size - 2; goto_pointer(begin); printf("70: %02X ", _read_byte()); scan_fixed_ident(32); printf("used: %5d\n", _read_word()); /* used */ SCAN_DOUBLE(40); SCAN_POINT(10,FALSE); SCAN_DOUBLE(41); SCAN_POINT(11,TRUE); SCAN_POINT(12,TRUE); SCAN_WORD(71); /*?*/ SCAN_DOUBLE(42); SCAN_DOUBLE(43); SCAN_DOUBLE(44); SCAN_DOUBLE(50); echo_bytes(2); /*?*/ skip_to_check_2(end); } get_check_32(); } /*-----------------23.10.95 11:14------------------- new: --------------------------------------------------*/ void scan_ucs_table(char *name, ptable pt) { longword i; DEBUG_P(("\n%s\n", name)); for (i = 0L; i < pt->nr; i++) { longword begin = pt->start + i * pt->size, end = begin + pt->size - 2; goto_pointer(begin); printf("70: %02X ", _read_byte()); scan_fixed_ident(32); printf("used: %5d\n", _read_word()); /* used */ SCAN_POINT(10,TRUE); SCAN_POINT(11,TRUE); SCAN_POINT(12,TRUE); skip_to_check_2(end); } get_check_32(); } /*-----------------23.10.95 11:14------------------- new: --------------------------------------------------*/ void scan_vport_table(char *name, ptable pt) { longword i; DEBUG_P(("\n%s\n", name)); for (i = 0L; i < pt->nr; i++) { longword begin = pt->start + i * pt->size, end = begin + pt->size - 2; goto_pointer(begin); printf("70: %02X ", _read_byte()); scan_fixed_ident(32); printf("used: %5d\n", _read_word()); /* used */ SCAN_POINT(10,FALSE); SCAN_POINT(11,FALSE); printf ("\n"); SCAN_POINT(17,TRUE); SCAN_POINT(16,TRUE); /*43-51 */ printf ("\n"); SCAN_DOUBLE(50); SCAN_DOUBLE(40); SCAN_POINT(12,FALSE); printf ("\n"); SCAN_DOUBLE(41); SCAN_DOUBLE(42); SCAN_DOUBLE(43); SCAN_DOUBLE(44); printf ("\n"); SCAN_WORD(71); /*?*/ SCAN_WORD(72); SCAN_WORD(73); SCAN_WORD(74); SCAN_WORD(75); SCAN_WORD(76); SCAN_WORD(77); SCAN_WORD(78); printf ("\n"); SCAN_DOUBLE(51); printf ("\n"); SCAN_POINT(13,FALSE); SCAN_POINT(14,FALSE); SCAN_POINT(15,FALSE); skip_to_check_2(end); } get_check_32(); } void scan_table(char *name, ptable pt) { longword i; DEBUG_P(("\n%s\n", name)); for (i = 0L; i < pt->nr; i++) { longword begin = pt->start + i * pt->size, end = begin + pt->size - 2; int flag; goto_pointer(begin); printf("70: %02X ", flag = _read_byte()); scan_fixed_ident(32); printf("used: %5d\n", _read_word()); /* used */ skip_to_check_2(end); } get_check_32(); } #define NR_ENT 25 struct { char *name; int kn_flag, kn_opts; } ent_type[NR_ENT] = { { NULL, 0, 0 }, { "LINE ", 0x6F /* 1 2 4 8 .. 20 40 .. */, 0x03 /* 1 2 . . .. .. .. .. */}, { "POINT ", 0x6F /* 1 2 4 8 .. 20 40 .. */, 0x03 /* 1 2 . . .. .. .. .. */}, { "CIRCLE ", 0x6F /* 1 2 4 8 .. 20 40 .. */, 0x03 /* 1 2 . . .. .. .. .. */}, { "SHAPE ", 0x6B /* 1 2 . 8 .. 20 40 .. */, 0x03 /* 1 2 . . .. .. .. .. */}, { NULL, 0, 0 }, { NULL, 0, 0 }, { "TEXT ", 0x6B /* 1 2 . 8 .. 20 40 .. */, 0x17B/* 1 2 + 8 10 20 40 ++ 50 41 51 7 71 72 72p ? 73 1 . . . .. .. .. .. */}, { "ARC ", 0x6D /* 1 . 4 8 .. 20 40 .. */, 0x03 /* 1 2 . . .. .. .. .. */}, { "TRACE ", 0x6B /* 1 2 . 8 .. 20 40 .. */, 0x03 /* 1 2 . . .. .. .. .. */}, { NULL, 0, 0 }, { "SOLID ", 0x6B /* 1 2 . 8 .. 20 40 .. */, 0x03 /* 1 2 . . .. .. .. .. */}, /*-----------------23.10.95 12:59------------------- opts changed --------------------------------------------------*/ { "BLOCK ", 0 /* . . . . .. .. .. .. */, 0x06 /* . 2 4 . .. .. .. .. */}, { "ENDBLK ", 0, 0x004 }, { "INSERT ", 0xA2 /* . 2 . . .. 20 .. 80 */, 0x0F /* 1 2 4 8 .. .. .. .. */}, { "ATTDEF ", 0x6B /* 1 2 . 8 .. 20 40 .. */, 0x030/* + + + + 10 20 ++ ++ 73 50 41 51 7 71 72 72' 1 . . . .. .. .. .. */}, { "ATTRIB ", 0x22 /* . . . . .. .. .. .. */, 0x116/* + 2 4 + 10 ++ ++ ++ 1 . . . .. .. .. .. */}, /* 1 */ { "S/BEND ", 0x22 /* . 2 . . .. 20 .. .. */, 0x00 /* . . . . .. .. .. .. */}, { NULL, 0, 0 }, { "PLINE ", 0xA2 /* . 2 . . .. 20 .. 80 */, 0x01 /* 1 . . . .. .. .. .. */}, { "VERTEX ", 0x22 /* . 2 . . .. 20 .. .. */, 0x04 /* + + . . .. .. .. .. */}, { NULL, 0, 0 }, { "3DFACE ", 0x26 /* . 2 . . .. 20 .. .. */, 0x00 /* . . . . .. .. .. .. */}, { "DIM ", 0x22 /* . . . . .. .. .. .. */, 0x11A/* + 2 + 8 10 ++ ++ ++ 1 . . . .. .. .. .. */}, { "VPORT ", 0x63 /* 1 2 . . .. 20 40 .. */, 0x00 /* . . . . .. .. .. .. */}, }; void scan_entities(longword start, longword end, longword sce_offset) { long s_comp_ent = 0L; DEBUG_P(("ENTITIES\n")); goto_pointer(start); while (cur_pos < end - 32L) { word kind, flag, length, layer, opts, color = 0, extra = 0; longword b_pos = cur_pos, pos = cur_pos; /*printf("cur_pos %ld end %ld\n", cur_pos, end);*/ DEBUG_P(("[%05lX]", cur_pos)); kind = _read_byte(); flag = _read_byte(); length = _read_word(); pos += (long)(length - 2); if (pos > end - 2) pos = end - 2; /* printf("cur_pos %ld, till %ld, end %ld", cur_pos, pos, end); */ if (kind < NR_ENT && ent_type[kind].name != NULL) { printf("%s %02X ", ent_type[kind].name, (int)flag); if (flag & ~ent_type[kind].kn_flag) printf("!%02X", flag & ~ent_type[kind].kn_flag); } else printf("ENT_%d! %02X (%d) ", (int)kind, (int)flag, length); layer = _read_word(); opts = _read_word(); printf("l:%d %04X ", layer, opts); if ( ent_type[kind].name != NULL && opts & ~ent_type[kind].kn_opts) printf("!%02X", opts & ~ent_type[kind].kn_opts); if (flag & 1) color = _read_byte(); printf("c:%d ", color); if (flag & 0x40) extra = _read_byte(); if (extra & ~6) /* . 2 4 . .. .. .. .. */ printf("!(extra)"); if (extra & 2) scan_xdata(); if (flag & 2) printf(" TYPE:%d ", _read_word()); if (flag & 4 && kind > 2 && kind != 22) { printf(" z:"); printf("%1.2f", _read_double()); } if (flag & 8) { printf(" TH:"); printf("%1.2f", _read_double()); } if (flag & 0x20) scan_handle(); if (extra & 4) printf(" PAPER:%d", _read_word()); switch (kind) { case 1: /* LINE */ SCAN_POINT(10, !(flag & 4)); SCAN_POINT(11, !(flag & 4)); OPTS(1) SCAN_POINT(210, TRUE); OPTS(2) SCAN_DOUBLE(38); break; case 2: /* POINT */ SCAN_POINT(10, !(flag & 4)); OPTS(1) SCAN_POINT(210, TRUE); OPTS(2) SCAN_DOUBLE(38); break; case 3: /* CIRCLE */ SCAN_POINT(10, FALSE); SCAN_DOUBLE(40); OPTS(1) SCAN_POINT(210, TRUE); OPTS(2) SCAN_DOUBLE(38); break; case 4: /* SHAPE */ SCAN_POINT(10, FALSE); SCAN_WORD(2); OPTS(1) SCAN_POINT(210, TRUE); OPTS(2) SCAN_DOUBLE(38); break; case 7: /* TEXT */ SCAN_POINT(10, FALSE); SCAN_DOUBLE(40); SCAN_STRING(1); OPTS(1) SCAN_DOUBLE(50); OPTS(2) SCAN_DOUBLE(41); OPTS(3) SCAN_DOUBLE(51); /*?*/ OPTS(4) SCAN_BYTE(7); OPTS(5) SCAN_BYTE(71); OPTS(6) SCAN_BYTE(72); OPTS(7) SCAN_POINT(11, FALSE); OPTS(9) SCAN_BYTE(73); break; case 8: /* ARC */ SCAN_POINT(10, FALSE); SCAN_DOUBLE(40); SCAN_DOUBLE(50); SCAN_DOUBLE(51); OPTS(1) SCAN_POINT(210, TRUE); OPTS(2) SCAN_DOUBLE(38); break; case 9: /* TRACE */ SCAN_POINT(10, FALSE); SCAN_POINT(11, FALSE); SCAN_POINT(12, FALSE); SCAN_POINT(13, FALSE); OPTS(1) SCAN_POINT(210, TRUE); OPTS(2) SCAN_DOUBLE(38); break; case 11: /* SOLID */ SCAN_POINT(11, FALSE); SCAN_POINT(12, FALSE); SCAN_POINT(13, FALSE); SCAN_POINT(14, FALSE); OPTS(1) SCAN_POINT(210, TRUE); OPTS(2) SCAN_DOUBLE(38); break; case 12: /* BLOCK */ SCAN_POINT(10,FALSE); /*?*/ SCAN_STRING(1); OPTS(2) SCAN_STRING(3); /* nur bei opts 2 */ break; case 13: /* ENDBLK */ break; case 14: /* INSERT */ s_comp_ent = b_pos - sce_offset; SCAN_WORD(1); SCAN_POINT(10, FALSE); OPTS(1) SCAN_DOUBLE(41); OPTS(2) SCAN_DOUBLE(42); OPTS(3) SCAN_DOUBLE(43); OPTS(4) SCAN_DOUBLE(50); OPTS(5) SCAN_WORD(70); OPTS(6) SCAN_WORD(71); OPTS(7) SCAN_DOUBLE(44); /*?*/ OPTS(8) SCAN_DOUBLE(45); /*?*/ break; case 15: /* ATTDEF */ SCAN_POINT(10, FALSE); SCAN_DOUBLE(40); SCAN_STRING(1); SCAN_STRING(3); SCAN_STRING(2); SCAN_BYTE(70); OPTS(1) SCAN_BYTE(73); /*?*/ OPTS(2) SCAN_DOUBLE(50); /*?*/ OPTS(3) SCAN_DOUBLE(41); OPTS(4) SCAN_DOUBLE(42); OPTS(5) SCAN_BYTE(7); OPTS(6) SCAN_BYTE(71); OPTS(7) SCAN_BYTE(72); OPTS(8) SCAN_POINT(11, FALSE); /*?*/ OPTS(9) SCAN_POINT(210, TRUE); OPTS(10) SCAN_DOUBLE(38); /*?*/ break; case 16: /* ATTRIB */ SCAN_POINT(10, FALSE); SCAN_DOUBLE(40); SCAN_STRING(1); SCAN_STRING(2); SCAN_BYTE(70); OPTS(1) SCAN_BYTE(73); /*?*/ OPTS(2) SCAN_DOUBLE(50); /*?*/ OPTS(3) SCAN_DOUBLE(41); OPTS(4) SCAN_DOUBLE(42); OPTS(5) SCAN_BYTE(7); OPTS(6) SCAN_BYTE(71); OPTS(7) SCAN_BYTE(72); OPTS(8) SCAN_POINT(11, FALSE); /*?*/ OPTS(9) SCAN_POINT(210, TRUE); OPTS(10) SCAN_DOUBLE(38); /*?*/ break; case 17: /* S/BEND */ { longword p = _read_long(); if (p != s_comp_ent) printf("!!%04lX != %04lX", s_comp_ent, p); } break; case 19: /* PLINE */ s_comp_ent = b_pos - sce_offset; OPTS(1) SCAN_BYTE(70); OPTS(2) SCAN_DOUBLE(40); /*?*/ OPTS(3) SCAN_BYTE(71); /*?*/ OPTS(4) SCAN_BYTE(72); /*?*/ OPTS(5) SCAN_BYTE(73); /*?*/ OPTS(6) SCAN_BYTE(74); /*?*/ OPTS(7) SCAN_BYTE(75); /*?*/ break; case 20: /* VERTEX */ SCAN_POINT(10, FALSE); OPTS(1) SCAN_DOUBLE(40); /*?*/ OPTS(2) SCAN_DOUBLE(41); /*?*/ OPTS(3) SCAN_DOUBLE(50); /*?*/ OPTS(4) SCAN_BYTE(70); /*?*/ break; case 22: /* 3DFACE */ SCAN_POINT(10, !(flag & 4)); SCAN_POINT(11, !(flag & 4)); SCAN_POINT(12, !(flag & 4)); SCAN_POINT(13, !(flag & 4)); break; case 23: /* DIM */ SCAN_WORD(1); SCAN_POINT(10, TRUE); SCAN_POINT(11, FALSE); /*?*/ OPTS(2) SCAN_BYTE(70); OPTS(1) SCAN_POINT(12, TRUE); /*?*/ OPTS(3) SCAN_STRING(1); OPTS(4) SCAN_POINT(13, TRUE); OPTS(5) SCAN_POINT(14, TRUE); OPTS(6) SCAN_POINT(15, TRUE); OPTS(7) SCAN_POINT(16, TRUE); OPTS(8) SCAN_DOUBLE(40); OPTS(9) SCAN_DOUBLE(50); OPTS(10) SCAN_DOUBLE(51); OPTS(11) SCAN_DOUBLE(52); OPTS(12) SCAN_DOUBLE(53); break; case 24: /* VPORT */ SCAN_POINT(10, TRUE); SCAN_DOUBLE(40); SCAN_DOUBLE(41); SCAN_WORD(68); break; } skip_to_check_2(pos); } get_check_32(); } void scan_xdata() { int xd_length = _read_word(), i; bool go = TRUE; printf("XDATA %d: (", xd_length); while (xd_length > 0 && go) { int c = _read_byte(); xd_length--; printf(" %d:", c); switch (c) { case 0: if (xd_length < 0) go = FALSE; else { int l = _read_byte(); xd_length--; if (version_13) { _read_byte(); xd_length--; } if (l <= xd_length) { printf("`%s'", _read_fixed_string(l)); xd_length -= l; } else go = FALSE; } break; case 1: case 3: case 70: if (xd_length < 2) go = FALSE; else { printf("%d", _read_word()); xd_length -= 2; } break; case 2: if (xd_length < 1) go = FALSE; else { printf("%c", _read_byte() == 0 ? '{' : '}'); xd_length--; } break; case 5: case 40: case 41: case 42: if (xd_length < 8) go = FALSE; else { printf("%1.2f", _read_double()); xd_length -= 8; } break; case 10: case 11: case 12: if (xd_length < 24) go = FALSE; else { scan_point(TRUE); xd_length -= 24; } break; case 71: if (xd_length < 4) go = FALSE; else { printf("%ld", _read_long()); xd_length -= 4; } break; default: go = FALSE; } } if (!go) printf("!"); for (i = 0; i < xd_length; i++) { int w = _read_byte(); if (w < 0) w += 256; printf("%02X ", w); } printf(") "); } void scan_handle() { int n = _read_byte(), i; printf(" 5:"); for (i = 0; i < n; i++) { int w = _read_byte(); if (w < 0) w += 256; printf("%02X", w); } } void echo_16_bytes(word len) { int i; char buffer[16]; printf("[%05lX] ", cur_pos); for (i = 0; i < len; i++) buffer[i] = _read_byte(); for (i = 0; i < 16; i++) { if (i > 0 && i % 4 == 0) printf("| "); if (i < len) { int w = buffer[i]; if (w < 0) w += 256; printf("%02X ", w); } else printf(" "); } printf(" "); for (i = 0; i < len; i++) { char c = buffer[i]; if ((c >= 0) && (c < 32)) printf("."); else printf("%c", c); } printf("\n"); } void echo_bytes(long int len) { printf("\ndata: %ld\n", len); while(len > 0) { int len16 = (int)MIN(len, 16); echo_16_bytes(len16); len -= (longword)len16; } } void scan_point(bool z_coord) { double x = _read_double(), y = _read_double(), z = z_coord ? _read_double() : 0.0; if (z_coord) printf("(%f,%f,%f)", x, y, z); else printf("(%f,%f)", x, y); } void scan_fixed_ident(int len) { char *s = _read_fixed_string(len); if (version_13) s++; printf("`%-*.*s'", len, len, s); } longword get_pointer() { longword result = _read_long(); #ifdef POINTER_VALUE printf("(pointer: %05lX)\n", result); #else printf("(pointer)\n"); #endif return result; } void check_pointer(longword p) { printf("(pointer: %05lX) %s\n", p,_read_long() == p ? "Correct" : "Wrong"); } void get_check_2() { printf("(check_2)\n"); _advance(2); } void get_check_32() { printf("(check_32)\n"); _advance(32); } void skip_to_check_2(longword pos) { if (cur_pos < pos) { printf("!\n"); echo_bytes(pos - cur_pos); } if (cur_pos > pos) { printf("!%05lX>", cur_pos - pos); _seek(pos); } get_check_2(); } void goto_pointer(longword pos) { if (cur_pos != pos) { printf("!(pointer: %05lX)\n", pos - cur_pos); /* /n inserted */ _seek(pos); } } /************** File IO *************************/ static FILE *f = NULL; #define MAX_STRING_LENGTH 1000 static char str_buffer[MAX_STRING_LENGTH]; #define GETBYTE (byte)fgetc(f) void _assign(file) FILE *file; { int fh = fileno(file); f = file; cur_pos = 0; last_pos = lseek(fh, 0L, SEEK_END); lseek(fh, 0L, SEEK_SET); } void _advance(word len) { fseek(f, len, SEEK_CUR); cur_pos += len; } longword _tell() { return cur_pos; } void _seek(long int pos) { cur_pos = pos; fseek(f, pos, SEEK_SET); } bool _eof() { return cur_pos >= last_pos; } byte _read_byte() { cur_pos++; return GETBYTE; } short _read_word() { short result; *((byte *)&result) = GETBYTE; *((byte *)&result + 1) = GETBYTE; cur_pos += 2; return result; } longword _read_long() { longword result; { short i; byte *p = (byte *)&result; for (i = 0; i < sizeof(longword); i++) *p++ = GETBYTE; } cur_pos += sizeof(longword); return result; } float _read_float() { float result; { short i; byte *p = (byte *)&result; for (i = 0; i < sizeof(double); i++) *p++ = GETBYTE; } cur_pos += sizeof(float); return result; } /*-----------------23.10.95 23:38------------------- corrected version --------------------------------------------------*/ double _read_date() { longword l1,l2; double d1; /* . */ /* seconds = 86400 * */ l1 = _read_long(); l2 = _read_long(); d1 = (double)l1; d1 += (double)l2 * 1e-8; /* here was an error in the prev. version!*/ return d1; } double _read_double() { double result; { short i; byte *p = (byte *)&result; for (i = 0; i < sizeof(double); i++) *p++ = GETBYTE; } cur_pos += sizeof(double); return result; } char *_read_string() { return _read_fixed_string(_read_word()); } char *_read_fixed_string(len) int len; { int i; char *str = str_buffer; for (i = 0; i < len; i++) *str++ = GETBYTE; *str = '\0'; cur_pos += len; return str_buffer; } /*-----------------25.10.95 21:47------------------- conversion of julian date into calendar date returns formatted date output from "Numerical Recipes in Pascal", p.12 room for s must be allocated! --------------------------------------------------*/ char *date_string (char *s, double date) { double t,ss; int y,m,d,hh,mm; long ja,jalpha,jb,jc,jd,je; #define TRUNC(n) (long) floor(n) t = 86400*(date-floor(date)); /* in seconds */ date = floor (date); if ( date>2299161.0 ) { jalpha = TRUNC(((date-1867216)-0.25)/36524.25); ja = (long) (date+1+jalpha-TRUNC(0.25*jalpha)); } else ja = (long)date; jb = ja+1524; jc = TRUNC(6680.0+((jb-2439870)-122.1)/365.25); jd = 365*jc+TRUNC(0.25*jc); je = TRUNC((jb-jd)/30.6001); d = (int) (jb-jd-TRUNC(30.6001*je)); m = (int) (je-1); if ( m>12 ) mm -= 12; y = (int) (jc-4715); if ( m>2 ) y--; if ( y<=0 ) y--; hh = (int) floor(t/3600.0); t -= hh*3600.0; mm = (int) floor(t/60.0); ss = t- (mm*60.0); sprintf (s, "%02d.%02d.%4d %02d:%02d:%05.2f", d,m,y,hh,mm,ss); return s; }