(root)/
libredwg-0.13/
src/
spec.h
       1  /*****************************************************************************/
       2  /*  LibreDWG - free implementation of the DWG file format                    */
       3  /*                                                                           */
       4  /*  Copyright (C) 2018-2024 Free Software Foundation, Inc.                   */
       5  /*                                                                           */
       6  /*  This library is free software, licensed under the terms of the GNU       */
       7  /*  General Public License as published by the Free Software Foundation,     */
       8  /*  either version 3 of the License, or (at your option) any later version.  */
       9  /*  You should have received a copy of the GNU General Public License        */
      10  /*  along with this program.  If not, see <http://www.gnu.org/licenses/>.    */
      11  /*****************************************************************************/
      12  
      13  #ifndef SPEC_H
      14  #  define SPEC_H
      15  
      16  #  undef _GNU_SOURCE
      17  #  define _GNU_SOURCE
      18  #  include <string.h>
      19  #  include "bits.h"
      20  #  include "codepages.h"
      21  #  include "decode.h"
      22  
      23  #  define DECODER if (0)
      24  #  define ENCODER if (0)
      25  #  define PRINT if (0)
      26  /* DECODER_ENCODER_OR_JSON really, or just NOT_DXF */
      27  #  define DECODER_OR_ENCODER if (0)
      28  #  define DXF_OR_PRINT if (0)
      29  #  define DXF_OR_FREE if (0)
      30  #  define DXF if (0)
      31  #  define JSON if (0)
      32  #  define FREE if (0)
      33  #  define IF_FREE_OR_SINCE(x) SINCE (x)
      34  #  define IF_FREE_OR_VERSIONS(x, y) VERSIONS (x, y)
      35  #  ifndef IF_ENCODE_FROM_EARLIER
      36  #    define IF_ENCODE_FROM_EARLIER if (0)
      37  #    define IF_ENCODE_FROM_EARLIER_OR_DXF if (0)
      38  #    define IF_ENCODE_FROM_PRE_R13 if (0)
      39  #    define IF_ENCODE_FROM_PRE_R2000 if (0)
      40  #  endif
      41  #  ifndef IF_ENCODE_SINCE_R13
      42  #    define IF_ENCODE_SINCE_R13 if (0)
      43  #  endif
      44  #  define IF_IS_ENCODER 0
      45  #  define IF_IS_DECODER 0
      46  #  define IF_IS_DXF 0
      47  #  define IF_IS_FREE 0
      48  
      49  #  ifndef ACTION
      50  #    error ACTION define missing: decode, encode, dxf, json, ...
      51  #  endif
      52  #  define _DWG_FUNC_N(ACTION, name) dwg_##ACTION##_##name
      53  #  define DWG_FUNC_N(ACTION, name) _DWG_FUNC_N (ACTION, name)
      54  #  define _DWG_PRIVATE_N(ACTION, name) dwg_##ACTION##_##name##_private
      55  #  define DWG_PRIVATE_N(ACTION, name) _DWG_PRIVATE_N (ACTION, name)
      56  
      57  #  define SET_PARENT(field, obj)
      58  #  define SET_PARENT_OBJ(field)
      59  #  define SET_PARENT_FIELD(field, what_parent, obj)
      60  
      61  #  ifndef ISFIRST
      62  #    define ISFIRST
      63  #    define SETFIRST
      64  #    define CLEARFIRST
      65  #  endif
      66  
      67  // for compile-time range checks with n=3,10,1000,5000,10000,20000,100000
      68  // #  define LOG2_APPROX(n) (size_t)((-0.344845 * (n) * (n)) + (2.024658 * (n))
      69  //- 1.674873) #  define _IN_RANGE     (sizeof (_obj->field) >= LOG2_APPROX
      70  //(maxvalue) / 8)
      71  #  define _IN_RANGE(var, n)                                                   \
      72      ((sizeof (var) == 1 && n <= 0xff) || (sizeof (var) == 2 && n <= 0xffff)   \
      73       || (sizeof (var) >= 4))
      74  
      75  #  ifndef IS_FREE
      76  #    define VALUEOUTOFBOUNDS(field, maxvalue)                                 \
      77        if (_IN_RANGE (_obj->field, maxvalue) && _obj->field > maxvalue)        \
      78          {                                                                     \
      79            LOG_ERROR ("Invalid %s." #field " %lu", obj ? obj->name : "",       \
      80                       (unsigned long)_obj->field);                             \
      81            _obj->field = 0;                                                    \
      82            return DWG_ERR_VALUEOUTOFBOUNDS;                                    \
      83          }
      84  #    define SUB_VALUEOUTOFBOUNDS(o, field, maxvalue)                          \
      85        if (_IN_RANGE (_obj->o.field, maxvalue) && _obj->o.field > maxvalue)    \
      86          {                                                                     \
      87            LOG_ERROR ("Invalid %s." #field " %lu", obj ? obj->name : "",       \
      88                       (unsigned long)_obj->o.field);                           \
      89            _obj->o.field = 0;                                                  \
      90            return DWG_ERR_VALUEOUTOFBOUNDS;                                    \
      91          }
      92  #  else
      93  #    define VALUEOUTOFBOUNDS(field, maxvalue)                                 \
      94        if (_IN_RANGE (_obj->field, maxvalue) && _obj->field > maxvalue)        \
      95          {                                                                     \
      96            return DWG_ERR_VALUEOUTOFBOUNDS;                                    \
      97          }
      98  #    define SUB_VALUEOUTOFBOUNDS(o, field, maxvalue)                          \
      99        if (_IN_RANGE (_obj->o.field, maxvalue) && _obj->o.field > maxvalue)    \
     100          {                                                                     \
     101            return DWG_ERR_VALUEOUTOFBOUNDS;                                    \
     102          }
     103  #  endif
     104  
     105  #endif /* SPEC_H */
     106  
     107  #ifndef VALUE_HANDLE
     108  #  define VALUE_HANDLE(value, nam, handle_code, dxf)
     109  #endif
     110  #ifndef VALUE_B
     111  #  define VALUE_B(value, dxf)
     112  #endif
     113  #ifndef VALUE_TV
     114  #  define VALUE_TV(value, dxf)
     115  #endif
     116  #ifndef VALUE_TF
     117  #  define VALUE_TF(value, dxf)
     118  #endif
     119  #ifndef VALUE_TFF
     120  #  define VALUE_TFF(value, dxf)
     121  #endif
     122  #ifndef VALUE_3BD
     123  #  define VALUE_3BD(value, dxf)
     124  #endif
     125  #ifndef VALUE_2RD
     126  #  define VALUE_2RD(value, dxf)
     127  #endif
     128  #ifndef VALUE_2BD
     129  #  define VALUE_2BD(value, dxf) VALUE_2RD (value, dxf)
     130  #endif
     131  #ifndef VALUE_3RD
     132  #  define VALUE_3RD(value, dxf) VALUE_3BD (value, dxf)
     133  #endif
     134  #ifndef VALUE_BS
     135  #  define VALUE_BS(value, dxf)
     136  #endif
     137  #ifndef VALUE_BSd
     138  #  define VALUE_BSd(value, dxf)
     139  #endif
     140  #ifndef VALUE_RSd
     141  #  define VALUE_RSd(value, dxf)
     142  #endif
     143  #ifndef VALUE_BL
     144  #  define VALUE_BL(value, dxf)
     145  #endif
     146  #ifndef VALUE_RLx
     147  #  define VALUE_RLx(value, dxf) VALUE_RL (value, dxf)
     148  #endif
     149  #ifndef KEY
     150  #  define KEY(nam)
     151  #endif
     152  #ifndef BLOCK_NAME
     153  #  define BLOCK_NAME(nam, dxf) FIELD_T (nam, dxf)
     154  #endif
     155  // sub fields
     156  #ifndef FIELDG
     157  #  define FIELDG(nam, type, dxf) FIELD (nam, type)
     158  #endif
     159  #ifndef SUB_FIELD_BSd
     160  #  define SUB_FIELD_BSd(o, nam, dxf) FIELD_BSd (o.nam, dxf)
     161  #endif
     162  #ifndef SUB_FIELD_BSx
     163  #  define SUB_FIELD_BSx(o, nam, dxf) FIELD_BSx (o.nam, dxf)
     164  #endif
     165  #ifndef SUB_FIELD_RSx
     166  #  define SUB_FIELD_RSx(o, nam, dxf) FIELD_RSx (o.nam, dxf)
     167  #endif
     168  #ifndef SUB_FIELD_RLLd
     169  #  define SUB_FIELD_RLLd(o, nam, dxf) FIELD_RLLd (o.nam, dxf)
     170  #endif
     171  #ifndef SUB_FIELD_TU
     172  #  define SUB_FIELD_TU(o, nam, dxf) FIELD_TU (o.nam, dxf)
     173  #endif
     174  #ifndef SUB_FIELD_T
     175  #  define SUB_FIELD_T(o, nam, dxf) FIELD_T (o.nam, dxf)
     176  #endif
     177  #ifndef SUB_FIELD_TV
     178  #  define SUB_FIELD_TV(o, nam, dxf) FIELD_TV (o.nam, dxf)
     179  #endif
     180  #ifndef SUB_FIELD_TF
     181  #  define SUB_FIELD_TF(o, nam, len, dxf) FIELD_TF (o.nam, _obj->o.len, dxf)
     182  #endif
     183  #ifndef SUB_FIELD_BLx
     184  #  define SUB_FIELD_BLx(o, nam, dxf) FIELD_BLx (o.nam, dxf)
     185  #endif
     186  #ifndef SUB_FIELD_RC
     187  #  define SUB_FIELD_RC(o, nam, dxf) SUB_FIELD (o, nam, RC, dxf)
     188  #endif
     189  #ifndef SUB_FIELD_BL
     190  #  define SUB_FIELD_B(o, nam, dxf) FIELDG (o.nam, B, dxf)
     191  #  define SUB_FIELD_BB(o, nam, dxf) FIELDG (o.nam, BB, dxf)
     192  #  define SUB_FIELD_3B(o, nam, dxf) FIELDG (o.nam, 3B, dxf)
     193  #  define SUB_FIELD_BS(o, nam, dxf) FIELDG (o.nam, BS, dxf)
     194  #  define SUB_FIELD_BL(o, nam, dxf) FIELDG (o.nam, BL, dxf)
     195  #  define SUB_FIELD_BLd(o, nam, dxf) FIELD_BLd (o.nam, dxf)
     196  #  define SUB_FIELD_RS(o, nam, dxf) FIELDG (o.nam, RS, dxf)
     197  #  define SUB_FIELD_RL(o, nam, dxf) FIELDG (o.nam, RL, dxf)
     198  #  define SUB_FIELD_BLL(o, nam, dxf) FIELDG (o.nam, BLL, dxf)
     199  #  define SUB_FIELD_RLL(o, nam, dxf) FIELDG (o.nam, RLL, dxf)
     200  #  define SUB_FIELD_BD(o, nam, dxf) FIELD_BD (o.nam, dxf)
     201  #  define SUB_FIELD_RD(o, nam, dxf) FIELD_RD (o.nam, dxf)
     202  #  define SUB_FIELD_2RD(o, nam, dxf) FIELD_2RD (o.nam, dxf)
     203  #  define SUB_FIELD_2BD(o, nam, dxf) FIELD_2BD (o.nam, dxf)
     204  #  define SUB_FIELD_2BD_1(o, nam, dxf) FIELD_2BD_1 (o.nam, dxf)
     205  #  define SUB_FIELD_3RD(o, nam, dxf) FIELD_3RD (o.nam, dxf)
     206  #  define SUB_FIELD_3BD(o, nam, dxf) FIELD_3BD (o.nam, dxf)
     207  #  define SUB_FIELD_3BD_inl(o, nam, dxf) FIELD_3BD (o, dxf)
     208  #  define SUB_FIELD_3DPOINT(o, nam, dxf) FIELD_3BD (o.nam, dxf)
     209  // # define SUB_FIELD_ENC(o,nam,dxf1,dxf2) FIELD_ENC(o.nam, dxf1,dxf2)
     210  #endif
     211  
     212  #ifndef SUB_HANDLE_VECTOR
     213  #  define SUB_HANDLE_VECTOR(o, nam, sizefield, code, dxf)                     \
     214      if (_obj->o.sizefield && _obj->o.nam)                                     \
     215        {                                                                       \
     216          BITCODE_BL _size = _obj->o.sizefield;                                 \
     217          for (vcount = 0; vcount < _size; vcount++)                            \
     218            {                                                                   \
     219              SUB_FIELD_HANDLE (o, nam[vcount], code, dxf);                     \
     220            }                                                                   \
     221        }
     222  #endif
     223  
     224  #ifndef SUB_FIELD_VECTOR
     225  #  define SUB_FIELD_VECTOR(o, nam, type, sizefield, dxf)                      \
     226      if (_obj->o.sizefield && _obj->o.nam)                                     \
     227        {                                                                       \
     228          BITCODE_BL _size = _obj->o.sizefield;                                 \
     229          for (vcount = 0; vcount < _size; vcount++)                            \
     230            {                                                                   \
     231              SUB_FIELD (o, nam[vcount], type, dxf);                            \
     232            }                                                                   \
     233        }
     234  #endif
     235  #ifndef SUB_FIELD_VECTOR_N
     236  #  define SUB_FIELD_VECTOR_N(o, nam, type, size, dxf)                         \
     237      if (size > 0 && _obj->o.nam != NULL)                                      \
     238        {                                                                       \
     239          BITCODE_BL _size = (BITCODE_BL)size;                                  \
     240          for (vcount = 0; vcount < _size; vcount++)                            \
     241            {                                                                   \
     242              SUB_FIELD (o, nam[vcount], type, dxf);                            \
     243            }                                                                   \
     244        }
     245  #endif
     246  #ifndef FIELD_VECTOR_INL
     247  #  define FIELD_VECTOR_INL(nam, type, size, dxf)                              \
     248      FIELD_VECTOR_N (nam, type, size, dxf)
     249  #endif
     250  #ifndef SUB_FIELD_VECTOR_INL
     251  #  define SUB_FIELD_VECTOR_INL(o, nam, type, size, dxf)                       \
     252      SUB_FIELD_VECTOR_N (o, nam, type, size, dxf)
     253  #endif
     254  #ifndef SUB_FIELD_2RD_VECTOR
     255  #  define SUB_FIELD_2RD_VECTOR(o, name, size, dxf)                            \
     256      if (_obj->o.size > 0)                                                     \
     257        {                                                                       \
     258          for (vcount = 0; vcount < (BITCODE_BL)_obj->o.size; vcount++)         \
     259            {                                                                   \
     260              SUB_FIELD_2RD (o, name[vcount], dxf);                             \
     261            }                                                                   \
     262        }
     263  #endif
     264  #ifndef SUB_FIELD_3BD_VECTOR
     265  #  define SUB_FIELD_3BD_VECTOR(o, name, size, dxf)                            \
     266      if (_obj->o.size > 0)                                                     \
     267        {                                                                       \
     268          for (vcount = 0; vcount < (BITCODE_BL)_obj->o.size; vcount++)         \
     269            {                                                                   \
     270              SUB_FIELD_3BD (o, name[vcount], dxf);                             \
     271            }                                                                   \
     272        }
     273  #endif
     274  #ifndef FIELD_VECTOR_T1
     275  #  define FIELD_VECTOR_T1(nam, type, size, dxf)                               \
     276      FIELD_VECTOR_T (nam, type, size, dxf)
     277  #endif
     278  #ifndef SUB_FIELD_VECTOR_TYPESIZE
     279  #  define SUB_FIELD_VECTOR_TYPESIZE(o, nam, size, typesize, dxf)              \
     280      if (_obj->o.size && _obj->o.nam)                                          \
     281        {                                                                       \
     282          for (vcount = 0; vcount < (BITCODE_BL)_obj->o.size; vcount++)         \
     283            {                                                                   \
     284              switch (typesize)                                                 \
     285                {                                                               \
     286                case 0:                                                         \
     287                  break;                                                        \
     288                case 1:                                                         \
     289                  SUB_FIELD (o, nam[vcount], RC, dxf);                          \
     290                  break;                                                        \
     291                case 2:                                                         \
     292                  SUB_FIELD (o, nam[vcount], RS, dxf);                          \
     293                  break;                                                        \
     294                case 4:                                                         \
     295                  SUB_FIELD (o, nam[vcount], RL, dxf);                          \
     296                  break;                                                        \
     297                case 8:                                                         \
     298                  SUB_FIELD (o, nam[vcount], RLL, dxf);                         \
     299                  break;                                                        \
     300                default:                                                        \
     301                  LOG_ERROR ("Unknown SUB_FIELD_VECTOR_TYPE " #nam              \
     302                             " typesize %d",                                    \
     303                             typesize);                                         \
     304                  break;                                                        \
     305                }                                                               \
     306            }                                                                   \
     307        }
     308  #endif
     309  
     310  #ifndef REPEAT_F
     311  // not allocating versions checked
     312  #  define _REPEAT_F(times, size, nam, type, idx)                              \
     313      if (_obj->times > (BITCODE_BL)size)                                       \
     314        {                                                                       \
     315          LOG_ERROR ("Invalid %s " FORMAT_BL " > %u", #nam,                     \
     316                     FIELD_VALUE (times), (unsigned)size);                      \
     317          FIELD_VALUE (times) = (BITCODE_BL)size;                               \
     318        }                                                                       \
     319      for (rcount##idx = 0; rcount##idx < (BITCODE_BL)_obj->times; rcount##idx++)
     320  #  define REPEAT_F(times, size, nam, type)                                    \
     321      _REPEAT_F (times, size, nam, type, 1)
     322  #endif
     323  
     324  // logging format overrides
     325  #ifndef FIELD_RLx
     326  #  define FIELD_RLx(name, dxf) FIELD_RL (name, dxf)
     327  #endif
     328  #ifndef FIELD_RSx
     329  #  define FIELD_RSx(name, dxf) FIELD_RS (name, dxf)
     330  #endif
     331  #ifndef FIELD_RCx
     332  #  define FIELD_RCx(name, dxf) FIELD_RC (name, dxf)
     333  #endif
     334  #ifndef FIELD_BLx
     335  #  define FIELD_BLx(name, dxf) FIELD_BL (name, dxf)
     336  #endif
     337  #ifndef FIELD_TFv
     338  #  define FIELD_TFv(name, len, dxf) FIELD_TV (name, dxf)
     339  #endif
     340  #ifndef FIELD_TFFx
     341  #  define FIELD_TFFx(name, len, dxf) FIELD_TFF (name, len, dxf)
     342  #endif
     343  #ifndef FIELD_TU32
     344  #  define FIELD_TU32(name, dxf) FIELD_TV (name, dxf)
     345  #endif
     346  #ifndef FIELD_RLd
     347  #  define FIELD_RLd(name, dxf) FIELD_RL (name, dxf)
     348  #endif
     349  #ifndef FIELD_BLd
     350  #  define FIELD_BLd(name, dxf) FIELD_BL (name, dxf)
     351  #endif
     352  #ifndef FIELD_BSx
     353  #  define FIELD_BSx(name, dxf) FIELD_BS (name, dxf)
     354  #endif
     355  #ifndef FIELD_BSd
     356  #  define FIELD_BSd(name, dxf) FIELD_BS (name, dxf)
     357  #endif
     358  #ifndef FIELD_RSd
     359  #  define FIELD_RSd(name, dxf) FIELD_RS (name, dxf)
     360  #endif
     361  #ifndef FIELD_RLLd
     362  #  define FIELD_RLLd(name, dxf) FIELD_RLL (name, dxf)
     363  #endif
     364  #ifndef FIELD_RCu
     365  #  define FIELD_RCu(name, dxf) FIELD_RC (name, dxf)
     366  #endif
     367  #ifndef FIELD_RCd
     368  #  define FIELD_RCd(name, dxf) FIELD_RC (name, dxf)
     369  #endif
     370  #ifndef VALUE_BINARY
     371  #  define VALUE_BINARY(value, len, dxf)
     372  #endif
     373  #ifndef FIELD_BINARY
     374  #  define FIELD_BINARY(name, len, dxf) FIELD_TF (name, len, dxf)
     375  #endif
     376  // force truecolor
     377  #ifndef FIELD_CMTC
     378  #  define FIELD_CMTC(name, dxf)                                               \
     379      {                                                                         \
     380        Dwg_Version_Type _ver = dat->version;                                   \
     381        if (dat->version < R_2004)                                              \
     382          dat->version = R_2004;                                                \
     383        FIELD_CMC (name, dxf);                                                  \
     384        if (_ver != dat->version)                                               \
     385          dat->version = _ver;                                                  \
     386      }
     387  #endif
     388  #ifndef SUB_FIELD_CMTC
     389  #  define SUB_FIELD_CMTC(o, name, dxf)                                        \
     390      {                                                                         \
     391        Dwg_Version_Type _ver = dat->version;                                   \
     392        Dwg_Version_Type _fver = dat->from_version;                             \
     393        if (dat->version < R_2004)                                              \
     394          dat->version = R_2004;                                                \
     395        if (dat->from_version < R_2004)                                         \
     396          dat->from_version = R_2004;                                           \
     397        SUB_FIELD_CMC (o, name, dxf);                                           \
     398        if (_ver != dat->version)                                               \
     399          dat->version = _ver;                                                  \
     400        if (_fver != dat->from_version)                                         \
     401          dat->from_version = _fver;                                            \
     402      }
     403  #endif
     404  // on DXF skip if 0
     405  #ifndef FIELD_BD0
     406  #  define FIELD_2RD0(name, dxf) FIELD_2RD (name, dxf)
     407  #  define FIELD_RD0(name, dxf) FIELD_RD (name, dxf)
     408  #  define FIELD_RD1(name, dxf) FIELD_RD (name, dxf)
     409  #  define FIELD_BD0(name, dxf) FIELD_BD (name, dxf)
     410  #  define FIELD_BD1(name, dxf) FIELD_BD (name, dxf)
     411  #  define FIELD_BL0(name, dxf) FIELD_BL (name, dxf)
     412  #  define SUB_FIELD_BL0(o, name, dxf) SUB_FIELD_BL (o, name, dxf)
     413  #  define FIELD_B0(name, dxf) FIELD_B (name, dxf)
     414  #  define FIELD_BS0(name, dxf) FIELD_BS (name, dxf)
     415  #  define FIELD_BS1(name, dxf) FIELD_BS (name, dxf)
     416  #  define FIELD_RC0(name, dxf) FIELD_RC (name, dxf)
     417  #  define FIELD_RS0(name, dxf) FIELD_RS (name, dxf)
     418  #  define FIELD_RL0(name, dxf) FIELD_RL (name, dxf)
     419  #  define FIELD_BT0(name, dxf) FIELD_BT (name, dxf)
     420  #  define VALUE_T0(name, dxf) VALUE_T (name, dxf)
     421  #  define FIELD_TV0(name, dxf) FIELD_TV (name, dxf)
     422  #  define FIELD_T0(name, dxf) FIELD_T (name, dxf)
     423  #  define FIELD_CMC0(color, dxf) FIELD_CMC (color, dxf)
     424  #  define FIELD_HANDLE0(name, code, dxf) FIELD_HANDLE (name, code, dxf)
     425  #  define SUB_FIELD_HANDLE0(o, name, code, dxf)                               \
     426      SUB_FIELD_HANDLE (o, name, code, dxf)
     427  #endif
     428  #ifndef VALUE_TV0
     429  #  define VALUE_TV0(name, dxf) VALUE_TV (name, dxf)
     430  #endif
     431  
     432  #ifndef FIELD_2RD_1
     433  #  define FIELD_2RD_1(nam, dxf) FIELD_2RD (nam, dxf)
     434  #endif
     435  
     436  // double to text
     437  #ifndef FIELD_D2T
     438  #  define FIELD_D2T(name, dxf) FIELD_TV (name, dxf)
     439  #endif
     440  #ifndef LOG_TRACE_TF
     441  #  define LOG_TRACE_TF(var, len)
     442  #  define LOG_INSANE_TF(var, len)
     443  #endif
     444  #ifndef SUBCLASS
     445  #  define SUBCLASS(text)
     446  #endif
     447  #ifndef DXF_3DSOLID
     448  #  define DXF_3DSOLID
     449  #endif
     450  #ifndef JSON_3DSOLID
     451  #  define JSON_3DSOLID
     452  #endif
     453  #ifndef FIELD_2PT_TRACE
     454  #  define FIELD_2PT_TRACE(name, type, dxf)                                    \
     455      LOG_TRACE (#name ": (" FORMAT_BD ", " FORMAT_BD ") [" #type " %d]\n",     \
     456                 _obj->name.x, _obj->name.y, dxf)
     457  #  define FIELD_3PT_TRACE(name, type, dxf)                                    \
     458      LOG_TRACE (#name ": (" FORMAT_BD ", " FORMAT_BD ", " FORMAT_BD            \
     459                       ") [" #type " %d]\n",                                    \
     460                 _obj->name.x, _obj->name.y, _obj->name.z, dxf)
     461  #endif
     462  #ifndef FIELD_ENC
     463  #  define FIELD_ENC(a, b, c) FIELD_CMC (a, b, c)
     464  #endif
     465  #ifndef SUB_FIELD_ENC
     466  #  define SUB_FIELD_ENC(a, b, c, d) SUB_FIELD_CMC (a, b, c, d)
     467  #endif
     468  
     469  #ifdef IS_ENCODER
     470  #  undef ENCODER
     471  #  undef IF_IS_ENCODER
     472  #  define IF_IS_ENCODER 1
     473  #  define ENCODER if (1)
     474  #  undef DECODER_OR_ENCODER
     475  #  define DECODER_OR_ENCODER if (1)
     476  #endif
     477  
     478  #ifdef IS_DECODER
     479  #  undef DECODER
     480  #  undef IF_IS_DECODER
     481  #  undef DECODER_OR_ENCODER
     482  #  define IF_IS_DECODER 1
     483  #  define DECODER if (1)
     484  #  define DECODER_OR_ENCODER if (1)
     485  #  undef SET_PARENT
     486  #  undef SET_PARENT_OBJ
     487  #  undef SET_PARENT_FIELD
     488  #  define SET_PARENT(field, to) _obj->field.parent = to
     489  #  define SET_PARENT_OBJ(field) SET_PARENT (field, _obj)
     490  #  define SET_PARENT_FIELD(field, what_parent, to) _obj->field.what_parent = to
     491  #else
     492  #  define TRACE_DD
     493  #endif
     494  
     495  #if defined(IS_PRINT)
     496  #  undef PRINT
     497  #  define PRINT if (1)
     498  #  undef DXF_OR_PRINT
     499  #  define DXF_OR_PRINT if (1)
     500  #endif
     501  
     502  #if defined(IS_DXF)
     503  #  undef DXF
     504  #  define DXF if (1)
     505  #  undef DXF_OR_PRINT
     506  #  define DXF_OR_PRINT if (1)
     507  #  undef DXF_OR_FREE
     508  #  define DXF_OR_FREE if (1)
     509  #  undef IF_IS_DXF
     510  #  define IF_IS_DXF 1
     511  #endif
     512  
     513  #if defined(IS_JSON)
     514  #  undef JSON
     515  #  define JSON if (1)
     516  #  undef DXF_OR_PRINT
     517  #  define DXF_OR_PRINT if (1)
     518  #  undef DECODER_OR_ENCODER
     519  #  define DECODER_OR_ENCODER if (1)
     520  #endif
     521  
     522  #if defined(IS_FREE)
     523  #  undef FREE
     524  #  define FREE if (1)
     525  #  undef DXF_OR_FREE
     526  #  define DXF_OR_FREE if (1)
     527  #  undef IF_IS_FREE
     528  #  define IF_IS_FREE 1
     529  #  undef IF_FREE_OR_SINCE
     530  #  define IF_FREE_OR_SINCE(x) if (1)
     531  #  undef IF_FREE_OR_VERSIONS
     532  #  define IF_FREE_OR_VERSIONS(x, y) if (1)
     533  #else
     534  #  ifndef END_REPEAT
     535  #    define END_REPEAT(field)
     536  #  endif
     537  #endif
     538  
     539  #ifndef END_REPEAT_F
     540  #  define END_REPEAT_F(field)
     541  #endif
     542  
     543  #ifndef R11OPTS
     544  #  define R11OPTS(b) (_ent->opts_r11 & (b))
     545  #  define R11FLAG(b) (_ent->flag_r11 & (b))
     546  #  define R11EXTRA(b) (_ent->extra_r11 & (b))
     547  #endif
     548  
     549  #if defined IS_JSON
     550  #  define HANDLE_UNKNOWN_BITS                                                 \
     551      {                                                                         \
     552        unsigned num_bytes = obj->num_unknown_bits / 8;                         \
     553        if (obj->num_unknown_bits & 8)                                          \
     554          num_bytes++;                                                          \
     555        KEY (num_unknown_bits);                                                 \
     556        VALUE_RL (obj->num_unknown_bits, 0);                                    \
     557        KEY (unknown_bits);                                                     \
     558        VALUE_BINARY (obj->unknown_bits, num_bytes, 0);                         \
     559      }
     560  #elif defined IS_DECODER
     561  #  define HANDLE_UNKNOWN_BITS                                                 \
     562      dwg_decode_unknown_bits (dat, (Dwg_Object *restrict)obj)
     563  #elif defined IS_ENCODER
     564  #  define HANDLE_UNKNOWN_BITS                                                 \
     565      if (dwg_encode_unknown_bits (dat, (Dwg_Object *restrict)obj))             \
     566        {                                                                       \
     567          if (hdl_dat != dat && hdl_dat->chain != dat->chain)                   \
     568            bit_chain_free (hdl_dat);                                           \
     569          return error;                                                         \
     570        }
     571  #elif defined IS_FREE
     572  #  define HANDLE_UNKNOWN_BITS VALUE_TF (obj->unknown_bits, 0)
     573  #elif defined IS_PRINT
     574  #  define HANDLE_UNKNOWN_BITS                                                 \
     575      LOG_TRACE ("unknown_bits: %u [TF]\n", (unsigned)obj->num_unknown_bits);   \
     576      LOG_TRACE_TF (obj->unknown_bits, obj->num_unknown_bits)
     577  #else
     578  #  define HANDLE_UNKNOWN_BITS
     579  #endif
     580  
     581  #if defined IS_JSON
     582  #  define UNKNOWN_BITS_REST                                                   \
     583      {                                                                         \
     584        unsigned num_bytes = obj->num_unknown_rest / 8;                         \
     585        if (obj->num_unknown_rest & 8)                                          \
     586          num_bytes++;                                                          \
     587        KEY (num_unknown_rest);                                                 \
     588        VALUE_RL (obj->num_unknown_rest, 0);                                    \
     589        KEY (unknown_bits);                                                     \
     590        VALUE_BINARY (obj->unknown_rest, num_bytes, 0);                         \
     591      }
     592  #elif defined IS_DECODER
     593  #  define UNKNOWN_BITS_REST                                                   \
     594      dwg_decode_unknown_rest (dat, (Dwg_Object *restrict)obj)
     595  #elif defined IS_ENCODER
     596  #  define UNKNOWN_BITS_REST                                                   \
     597      dwg_encode_unknown_rest (dat, (Dwg_Object *restrict)obj)
     598  #elif defined IS_FREE
     599  #  define UNKNOWN_BITS_REST VALUE_TF (obj->unknown_rest, 0)
     600  #else
     601  #  define UNKNOWN_BITS_REST
     602  #endif
     603  
     604  #ifndef START_OBJECT_HANDLE_STREAM
     605  #  define START_OBJECT_HANDLE_STREAM                                          \
     606      START_HANDLE_STREAM;                                                      \
     607      assert (obj->supertype == DWG_SUPERTYPE_OBJECT)
     608  #endif
     609  
     610  #ifndef CONTROL_HANDLE_STREAM
     611  #  define CONTROL_HANDLE_STREAM                                               \
     612      assert (obj->supertype == DWG_SUPERTYPE_OBJECT);                          \
     613      PRE (R_2007)                                                              \
     614      {                                                                         \
     615        hdl_dat->byte = dat->byte;                                              \
     616        hdl_dat->bit = dat->bit;                                                \
     617      }                                                                         \
     618      SINCE (R_13b1)                                                            \
     619      {                                                                         \
     620        VALUE_HANDLE (obj->tio.object->ownerhandle, ownerhandle, 4, 0);         \
     621        REACTORS (4)                                                            \
     622        XDICOBJHANDLE (3)                                                       \
     623      }
     624  #endif
     625  
     626  #ifndef LOG_FLAG_W
     627  #  define LOG_FLAG_W(token, w)                                                \
     628      if (_obj->flag & FLAG_##token##_##w)                                      \
     629      LOG_TRACE (#w " (%d) ", FLAG_##token##_##w)
     630  #  define LOG_FLAG_TABLE_W(w)                                                 \
     631      if (_obj->flag & FLAG_TABLE_##w)                                          \
     632      LOG_TRACE (#w " (%d) ", FLAG_TABLE_##w)
     633  #  define LOG_FLAG_TABLE_MAX(v)                                               \
     634      if (_obj->flag > v)                                                       \
     635      LOG_WARN ("Unknown flag (%d)", _obj->flag)
     636  #  define LOG_FLAG_TABLE_COMMON                                               \
     637      if (_obj->flag)                                                           \
     638        {                                                                       \
     639          LOG_TRACE ("      ");                                                 \
     640          LOG_FLAG_TABLE_W (IS_XREF_REF);                                       \
     641          LOG_FLAG_TABLE_W (IS_XREF_RESOLVED);                                  \
     642          LOG_FLAG_TABLE_W (IS_XREF_DEP);                                       \
     643          LOG_FLAG_TABLE_W (IS_REMOVED);                                        \
     644          LOG_FLAG_TABLE_MAX (255);                                             \
     645          LOG_TRACE ("\n");                                                     \
     646        }
     647  #  define LOG_FLAG_BLOCK_W(w)                                                 \
     648      if (_obj->flag & FLAG_BLOCK_##w)                                          \
     649      LOG_TRACE (#w " (%d) ", FLAG_BLOCK_##w)
     650  #  define LOG_FLAG_Block                                                      \
     651      if (_obj->flag)                                                           \
     652        {                                                                       \
     653          LOG_TRACE ("      ");                                                 \
     654          LOG_FLAG_W (BLOCK, ANONYMOUS);                                        \
     655          LOG_FLAG_W (BLOCK, HAS_ATTRIBS);                                      \
     656          LOG_FLAG_W (BLOCK, IS_EXT_REF);                                       \
     657          LOG_FLAG_W (BLOCK, IS_XREF_OVERLAY);                                  \
     658          LOG_FLAG_TABLE_W (IS_XREF_REF);                                       \
     659          LOG_FLAG_TABLE_W (IS_XREF_RESOLVED);                                  \
     660          LOG_FLAG_TABLE_W (IS_XREF_DEP);                                       \
     661          LOG_FLAG_TABLE_W (IS_REMOVED);                                        \
     662          LOG_FLAG_TABLE_MAX (255);                                             \
     663          LOG_TRACE ("\n");                                                     \
     664        }
     665  #  define LOG_FLAG_Layer                                                      \
     666      if (_obj->flag)                                                           \
     667        {                                                                       \
     668          LOG_TRACE ("      ");                                                 \
     669          LOG_FLAG_W (LAYER, FROZEN);                                           \
     670          LOG_FLAG_W (LAYER, FROZEN_IN_NEW);                                    \
     671          LOG_FLAG_W (LAYER, LOCKED);                                           \
     672          LOG_FLAG_W (LAYER, PLOTFLAG);                                         \
     673          LOG_FLAG_TABLE_W (IS_XREF_REF);                                       \
     674          LOG_FLAG_TABLE_W (IS_XREF_RESOLVED);                                  \
     675          LOG_FLAG_TABLE_W (IS_XREF_DEP);                                       \
     676          LOG_FLAG_TABLE_W (IS_REMOVED);                                        \
     677          LOG_FLAG_TABLE_MAX (255);                                             \
     678          LOG_TRACE ("\n");                                                     \
     679        }
     680  #  define LOG_FLAG_TextStyle                                                  \
     681      if (_obj->flag)                                                           \
     682        {                                                                       \
     683          LOG_TRACE ("      ");                                                 \
     684          LOG_FLAG_W (STYLE, SHAPE);                                            \
     685          LOG_FLAG_W (STYLE, VERTICAL_TEXT);                                    \
     686          LOG_FLAG_TABLE_W (IS_XREF_REF);                                       \
     687          LOG_FLAG_TABLE_W (IS_XREF_RESOLVED);                                  \
     688          LOG_FLAG_TABLE_W (IS_XREF_DEP);                                       \
     689          LOG_FLAG_TABLE_W (IS_REMOVED);                                        \
     690          LOG_FLAG_TABLE_MAX (255);                                             \
     691          LOG_TRACE ("\n");                                                     \
     692        }
     693  #  define LOG_FLAG_View                                                       \
     694      if (_obj->flag)                                                           \
     695        {                                                                       \
     696          LOG_TRACE ("      ");                                                 \
     697          LOG_FLAG_W (VIEW, PSPACE);                                            \
     698          LOG_FLAG_TABLE_W (IS_XREF_REF);                                       \
     699          LOG_FLAG_TABLE_W (IS_XREF_RESOLVED);                                  \
     700          LOG_FLAG_TABLE_W (IS_XREF_DEP);                                       \
     701          LOG_FLAG_TABLE_W (IS_REMOVED);                                        \
     702          LOG_FLAG_TABLE_MAX (255);                                             \
     703          LOG_TRACE ("\n");                                                     \
     704        }
     705  #  define LOG_FLAG_VX                                                         \
     706      if (_obj->flag)                                                           \
     707        {                                                                       \
     708          LOG_TRACE ("      ");                                                 \
     709          LOG_FLAG_W (VX, IS_ON);                                               \
     710          LOG_FLAG_TABLE_W (IS_XREF_REF);                                       \
     711          LOG_FLAG_TABLE_W (IS_XREF_RESOLVED);                                  \
     712          LOG_FLAG_TABLE_W (IS_XREF_DEP);                                       \
     713          LOG_FLAG_TABLE_W (IS_REMOVED);                                        \
     714          LOG_FLAG_TABLE_MAX (255);                                             \
     715          LOG_TRACE ("\n");                                                     \
     716        }
     717  #  define LOG_FLAG_Viewport LOG_FLAG_TABLE_COMMON
     718  #  define LOG_FLAG_RegApp LOG_FLAG_TABLE_COMMON
     719  #  define LOG_FLAG_DimStyle LOG_FLAG_TABLE_COMMON
     720  #  define LOG_FLAG_Linetype LOG_FLAG_TABLE_COMMON
     721  #  define LOG_FLAG_UCS LOG_FLAG_TABLE_COMMON
     722  #endif
     723  
     724  #ifndef COMMON_TABLE_FLAGS
     725  #  define COMMON_TABLE_FLAGS(acdbname)                                        \
     726      assert (obj->supertype == DWG_SUPERTYPE_OBJECT);                          \
     727      PRE (R_13b1)                                                              \
     728      {                                                                         \
     729        if (strcmp (#acdbname, "Layer") == 0)                                   \
     730          {                                                                     \
     731            FIELD_CAST (flag, RC, RS, 70);                                      \
     732          }                                                                     \
     733        else                                                                    \
     734          {                                                                     \
     735            FIELD_CAST (flag, RC, RC, 70);                                      \
     736          }                                                                     \
     737        DECODER_OR_ENCODER { LOG_FLAG_##acdbname }                              \
     738        FIELD_TFv (name, 32, 2);                                                \
     739        VERSION (R_11)                                                          \
     740          FIELD_RSd (used, 0);                                                  \
     741      }                                                                         \
     742      LATER_VERSIONS                                                            \
     743      {                                                                         \
     744        FIELD_T (name, 2);                                                      \
     745        UNTIL (R_2004)                                                          \
     746        {                                                                       \
     747          FIELD_B (is_xref_ref, 0);       /* always 1, 70 bit 6 */              \
     748          FIELD_BS (is_xref_resolved, 0); /* 0 or 256 */                        \
     749          FIELD_B (is_xref_dep, 0);       /* 70 bit 4 */                        \
     750        }                                                                       \
     751        LATER_VERSIONS                                                          \
     752        {                                                                       \
     753          FIELD_VALUE (is_xref_ref) = 1;                                        \
     754          FIELD_BS (is_xref_resolved, 0); /* 0 or 256 */                        \
     755          if (FIELD_VALUE (is_xref_resolved) == 256)                            \
     756            FIELD_VALUE (is_xref_dep) = 1;                                      \
     757        }                                                                       \
     758        FIELD_HANDLE (xref, 5, 0); /* NULLHDL without is_xref_dep */            \
     759        FIELD_VALUE (flag)                                                      \
     760            |= FIELD_VALUE (is_xref_dep) << 4 | FIELD_VALUE (is_xref_ref) << 6; \
     761      }                                                                         \
     762      RESET_VER
     763  #endif
     764  
     765  #ifndef FIELD_VECTOR_N1
     766  #  define FIELD_VECTOR_N1(name, type, size, dxf)                              \
     767      FIELD_VECTOR_N (name, type, size, dxf)
     768  #endif
     769  
     770  #ifndef REPEAT_BLOCK
     771  #  define REPEAT_BLOCK {
     772  #  define END_REPEAT_BLOCK }
     773  #endif
     774  
     775  /* REPEAT names:
     776    _ adds idx
     777    C does no checks
     778    N does constant times (else _obj->times)
     779    F does not calloc/free
     780  */
     781  
     782  // unchecked with constant times
     783  #ifndef REPEAT
     784  #  define REPEAT_CN(times, name, type)                                        \
     785      if (_obj->name != NULL)                                                   \
     786        for (rcount1 = 0; rcount1 < (BITCODE_BL)times; rcount1++)
     787  // checked with constant times
     788  #  define REPEAT_N(times, name, type)                                         \
     789      if (dat->version >= R_2000 && (BITCODE_BL)times > 20000)                  \
     790        {                                                                       \
     791          LOG_ERROR ("Invalid %s." #name " rcount1 %ld", SAFEDXFNAME,           \
     792                     (long)times);                                              \
     793          return DWG_ERR_VALUEOUTOFBOUNDS;                                      \
     794        }                                                                       \
     795      if (_obj->name != NULL)                                                   \
     796        for (rcount1 = 0; rcount1 < (BITCODE_BL)times; rcount1++)
     797  
     798  // checked with var. times
     799  #  define _REPEAT(times, name, type, idx)                                     \
     800      if (dat->version >= R_2000 && (BITCODE_BL)_obj->times > 20000)            \
     801        {                                                                       \
     802          LOG_ERROR ("Invalid %s." #name " rcount" #idx " %ld", SAFEDXFNAME,    \
     803                     (long)_obj->times);                                        \
     804          return DWG_ERR_VALUEOUTOFBOUNDS;                                      \
     805        }                                                                       \
     806      if (_obj->times > 0 && _obj->name != NULL)                                \
     807        for (rcount##idx = 0; rcount##idx < (BITCODE_BL)_obj->times;            \
     808             rcount##idx++)
     809  // unchecked with var. times
     810  #  ifndef _REPEAT_C
     811  #    define _REPEAT_C(times, name, type, idx)                                 \
     812        if (_obj->times > 0 && _obj->name != NULL)                              \
     813          for (rcount##idx = 0; rcount##idx < (BITCODE_BL)_obj->times;          \
     814               rcount##idx++)
     815  #  endif
     816  #  define REPEAT(times, name, type) _REPEAT (times, name, type, 1)
     817  #  define REPEAT2(times, name, type) _REPEAT (times, name, type, 2)
     818  #  define REPEAT3(times, name, type) _REPEAT (times, name, type, 3)
     819  #  define REPEAT4(times, name, type) _REPEAT (times, name, type, 4)
     820  #  define REPEAT_C(times, name, type) _REPEAT_C (times, name, type, 1)
     821  #  define REPEAT2_C(times, name, type) _REPEAT_C (times, name, type, 2)
     822  #  define REPEAT3_C(times, name, type) _REPEAT_C (times, name, type, 3)
     823  #  define REPEAT4_C(times, name, type) _REPEAT_C (times, name, type, 4)
     824  #endif
     825  // unchecked with constant times
     826  #ifndef _REPEAT_CN
     827  #  define _REPEAT_CN(times, name, type, idx)                                  \
     828      if (_obj->name != NULL)                                                   \
     829        for (rcount##idx = 0; rcount##idx < (BITCODE_BL)times; rcount##idx++)
     830  #endif
     831  // not allocating versions:
     832  // unchecked
     833  #ifndef _REPEAT_CNF
     834  #  define _REPEAT_CNF(times, name, type, idx)                                 \
     835      if (_obj->name != NULL)                                                   \
     836        for (rcount##idx = 0; rcount##idx < (BITCODE_BL)times; rcount##idx++)
     837  #endif
     838  #ifndef _REPEAT_NF
     839  // checked
     840  #  define _REPEAT_NF(times, name, type, idx)                                  \
     841      if (dat->version >= R_2000 && times > 0x7ff)                              \
     842        {                                                                       \
     843          LOG_ERROR ("Invalid %s." #name " rcount" #idx " %ld", SAFEDXFNAME,    \
     844                     (long)times);                                              \
     845          return DWG_ERR_VALUEOUTOFBOUNDS;                                      \
     846        }                                                                       \
     847      if (_obj->name != NULL)                                                   \
     848        for (rcount##idx = 0; rcount##idx < (BITCODE_BL)times; rcount##idx++)
     849  #endif
     850  
     851  #define DWG_SUBCLASS_DECL(parenttype, subtype)                                \
     852    static int DWG_PRIVATE_N (ACTION, parenttype##_##subtype) (                 \
     853        Dwg_Object_##parenttype *restrict _obj, Bit_Chain * dat,                \
     854        Bit_Chain * hdl_dat, Bit_Chain * str_dat, Dwg_Object *restrict obj)
     855  
     856  #define DWG_SUBCLASS(parenttype, subtype)                                     \
     857    static int DWG_PRIVATE_N (ACTION, parenttype##_##subtype) (                 \
     858        Dwg_Object_##parenttype *restrict _obj, Bit_Chain * dat,                \
     859        Bit_Chain * hdl_dat, Bit_Chain * str_dat, Dwg_Object *restrict obj)     \
     860    {                                                                           \
     861      BITCODE_BL vcount, rcount3, rcount4;                                      \
     862      Dwg_Data *dwg = obj->parent;                                              \
     863      int error = 0;                                                            \
     864      subtype##_fields;                                                         \
     865      return error;                                                             \
     866    }
     867  
     868  #define CALL_SUBCLASS(_xobj, parenttype, subtype)                             \
     869    error |= DWG_PRIVATE_N (ACTION, parenttype##_##subtype) (                   \
     870        _xobj, dat, hdl_dat, str_dat, (Dwg_Object *)obj)
     871  // if the name is compile-time known
     872  #define CALL_ENTITY(name, xobj)                                               \
     873    error |= DWG_PRIVATE_N (ACTION, name) (dat, hdl_dat, str_dat,               \
     874                                           (Dwg_Object *)xobj)
     875  // TODO: dispatch on the type
     876  #define CALL_SUBENT(hdl, dxf)
     877  // error |= DWG_PRIVATE_N (ACTION, xobj->fixedtype) (dat, hdl_dat, str_dat,
     878  // (Dwg_Object *)xobj)
     879  #define CALL_SUBCURVE(hdl, curvetype)
     880  
     881  #ifndef UNKNOWN_UNTIL
     882  #  define UNKNOWN_UNTIL(pos)                                                  \
     883      LOG_TRACE ("unknown (%ld): ", pos - dat->byte);                           \
     884      dat->byte = pos
     885  #endif
     886  
     887  #define LOG_FLAG_MAX(value, w)                                                \
     888    if (value > w)                                                              \
     889    LOG_WARN ("Unknown flag (0x%x)", value & ~(w))
     890  
     891  #ifndef LOG_TEXT_GENERATION
     892  #  define LOG_TEXT_GENERATION_W(w)                                            \
     893      if (_obj->generation & TEXT_GENERATION_##w)                               \
     894      LOG_TRACE (#w "(0x%x) ", TEXT_GENERATION_##w)
     895  #  define LOG_TEXT_GENERATION                                                 \
     896      DECODER_OR_ENCODER                                                        \
     897      {                                                                         \
     898        if (_obj->generation)                                                   \
     899          {                                                                     \
     900            LOG_TRACE ("            ");                                         \
     901            LOG_TEXT_GENERATION_W (BACKWARDS);                                  \
     902            LOG_TEXT_GENERATION_W (UPSIDE_DOWN);                                \
     903            LOG_FLAG_MAX (_obj->generation, 7);                                 \
     904            LOG_TRACE ("\n");                                                   \
     905          }                                                                     \
     906      }
     907  #endif
     908  
     909  #ifndef LOG_HORIZ_ALIGNMENT
     910  #  define LOG_HORIZ_ALIGNMENT_W(w)                                            \
     911      if (_obj->horiz_alignment == HORIZ_ALIGNMENT_##w)                         \
     912      LOG_TRACE (#w "(0x%x) ", HORIZ_ALIGNMENT_##w)
     913  #  define LOG_HORIZ_ALIGNMENT                                                 \
     914      DECODER_OR_ENCODER                                                        \
     915      {                                                                         \
     916        if (_obj->horiz_alignment)                                              \
     917          {                                                                     \
     918            LOG_TRACE ("                 ");                                    \
     919            LOG_HORIZ_ALIGNMENT_W (LEFT);                                       \
     920            LOG_HORIZ_ALIGNMENT_W (CENTER);                                     \
     921            LOG_HORIZ_ALIGNMENT_W (RIGHT);                                      \
     922            LOG_HORIZ_ALIGNMENT_W (ALIGNED);                                    \
     923            LOG_HORIZ_ALIGNMENT_W (MIDDLE);                                     \
     924            LOG_HORIZ_ALIGNMENT_W (FIT);                                        \
     925            LOG_FLAG_MAX (_obj->horiz_alignment, HORIZ_ALIGNMENT_FIT);          \
     926            LOG_TRACE ("\n");                                                   \
     927          }                                                                     \
     928      }
     929  #endif
     930  
     931  #ifndef LOG_VERT_ALIGNMENT
     932  #  define LOG_VERT_ALIGNMENT_W(w)                                             \
     933      if (_obj->vert_alignment == VERT_ALIGNMENT_##w)                           \
     934      LOG_TRACE (#w "(0x%x) ", VERT_ALIGNMENT_##w)
     935  #  define LOG_VERT_ALIGNMENT                                                  \
     936      DECODER_OR_ENCODER                                                        \
     937      {                                                                         \
     938        if (_obj->vert_alignment)                                               \
     939          {                                                                     \
     940            LOG_TRACE ("                ");                                     \
     941            LOG_VERT_ALIGNMENT_W (BASELINE);                                    \
     942            LOG_VERT_ALIGNMENT_W (BOTTOM);                                      \
     943            LOG_VERT_ALIGNMENT_W (MIDDLE);                                      \
     944            LOG_VERT_ALIGNMENT_W (TOP);                                         \
     945            LOG_FLAG_MAX (_obj->vert_alignment, VERT_ALIGNMENT_TOP);            \
     946            LOG_TRACE ("\n");                                                   \
     947          }                                                                     \
     948      }
     949  #endif
     950  
     951  #ifndef LOG_FLAG_ATTDEF
     952  #  define LOG_FLAG_ATTDEF_W(w)                                                \
     953      if (_obj->flags & FLAG_ATTDEF_##w)                                        \
     954      LOG_TRACE (#w "(0x%x) ", FLAG_ATTDEF_##w)
     955  #  define LOG_FLAG_ATTDEF                                                     \
     956      DECODER_OR_ENCODER                                                        \
     957      {                                                                         \
     958        if (_obj->flags)                                                        \
     959          {                                                                     \
     960            LOG_TRACE ("       ");                                              \
     961            LOG_FLAG_ATTDEF_W (INVISIBLE);                                      \
     962            LOG_FLAG_ATTDEF_W (CONSTANT);                                       \
     963            LOG_FLAG_ATTDEF_W (VERIFY);                                         \
     964            LOG_FLAG_ATTDEF_W (PRESET);                                         \
     965            LOG_FLAG_MAX (_obj->flags, 15);                                     \
     966            LOG_TRACE ("\n");                                                   \
     967          }                                                                     \
     968      }
     969  #endif
     970  
     971  #ifndef LOG_FLAG_ATTRIB
     972  #  define LOG_FLAG_ATTRIB_W(w)                                                \
     973      if (_obj->flags & FLAG_ATTRIB_##w)                                        \
     974      LOG_TRACE (#w "(0x%x) ", FLAG_ATTRIB_##w)
     975  #  define LOG_FLAG_ATTRIB                                                     \
     976      DECODER_OR_ENCODER                                                        \
     977      {                                                                         \
     978        if (_obj->flags)                                                        \
     979          {                                                                     \
     980            LOG_TRACE ("       ");                                              \
     981            LOG_FLAG_ATTRIB_W (INVISIBLE);                                      \
     982            LOG_FLAG_ATTRIB_W (CONSTANT);                                       \
     983            LOG_FLAG_ATTRIB_W (VERIFY);                                         \
     984            LOG_FLAG_ATTRIB_W (PRESET);                                         \
     985            LOG_FLAG_MAX (_obj->flags, 15);                                     \
     986            LOG_TRACE ("\n");                                                   \
     987          }                                                                     \
     988      }
     989  #endif
     990  
     991  #ifndef LOG_FLAG_LWPOLYLINE
     992  #  define LOG_FLAG_LWPOLYLINE_W(w)                                            \
     993      if (_obj->flag & FLAG_LWPOLYLINE_##w)                                     \
     994      LOG_TRACE (#w "(0x%x) ", FLAG_LWPOLYLINE_##w)
     995  #  define LOG_FLAG_LWPOLYLINE                                                 \
     996      DECODER_OR_ENCODER                                                        \
     997      {                                                                         \
     998        if (_obj->flag)                                                         \
     999          {                                                                     \
    1000            LOG_TRACE ("      ");                                               \
    1001            LOG_FLAG_LWPOLYLINE_W (HAS_EXTRUSION);                              \
    1002            LOG_FLAG_LWPOLYLINE_W (HAS_THICKNESS);                              \
    1003            LOG_FLAG_LWPOLYLINE_W (HAS_CONSTWIDTH);                             \
    1004            LOG_FLAG_LWPOLYLINE_W (HAS_ELEVATION);                              \
    1005            LOG_FLAG_LWPOLYLINE_W (HAS_NUM_BULGES);                             \
    1006            LOG_FLAG_LWPOLYLINE_W (HAS_NUM_WIDTHS);                             \
    1007            LOG_FLAG_LWPOLYLINE_W (UNKNOWN_64);                                 \
    1008            LOG_FLAG_LWPOLYLINE_W (PLINEGEN);                                   \
    1009            LOG_FLAG_LWPOLYLINE_W (UNKNOWN_256);                                \
    1010            LOG_FLAG_LWPOLYLINE_W (CLOSED);                                     \
    1011            LOG_FLAG_LWPOLYLINE_W (VERTEXIDCOUNT);                              \
    1012            LOG_FLAG_MAX (_obj->flag, 2047);                                    \
    1013            LOG_TRACE ("\n");                                                   \
    1014          }                                                                     \
    1015      }
    1016  #endif
    1017  
    1018  #ifndef LOG_FLAG_POLYLINE
    1019  #  define LOG_FLAG_POLYLINE_W(w)                                              \
    1020      if (_obj->flag & FLAG_POLYLINE_##w)                                       \
    1021      LOG_TRACE (#w "(0x%x) ", FLAG_POLYLINE_##w)
    1022  #  define LOG_FLAG_POLYLINE                                                   \
    1023      DECODER_OR_ENCODER                                                        \
    1024      {                                                                         \
    1025        if (_obj->flag)                                                         \
    1026          {                                                                     \
    1027            LOG_TRACE ("      ");                                               \
    1028            LOG_FLAG_POLYLINE_W (CLOSED);                                       \
    1029            LOG_FLAG_POLYLINE_W (CURVE_FIT);                                    \
    1030            LOG_FLAG_POLYLINE_W (SPLINE_FIT);                                   \
    1031            LOG_FLAG_POLYLINE_W (3D);                                           \
    1032            LOG_FLAG_POLYLINE_W (MESH);                                         \
    1033            LOG_FLAG_POLYLINE_W (MESH_CLOSED);                                  \
    1034            LOG_FLAG_POLYLINE_W (PFACE_MESH);                                   \
    1035            LOG_FLAG_POLYLINE_W (LT_PATTERN_CONTINUES);                         \
    1036            LOG_FLAG_MAX (_obj->flag, 255);                                     \
    1037            LOG_TRACE ("\n");                                                   \
    1038          }                                                                     \
    1039      }
    1040  #endif
    1041  
    1042  #ifndef LOG_FLAG_VERTEX
    1043  #  define LOG_FLAG_VERTEX_W(w)                                                \
    1044      if (_obj->flag & FLAG_VERTEX_##w)                                         \
    1045      LOG_TRACE (#w "(0x%x) ", FLAG_VERTEX_##w)
    1046  #  define LOG_FLAG_VERTEX                                                     \
    1047      DECODER_OR_ENCODER                                                        \
    1048      {                                                                         \
    1049        if (_obj->flag)                                                         \
    1050          {                                                                     \
    1051            LOG_TRACE ("      ");                                               \
    1052            LOG_FLAG_VERTEX_W (EXTRA_VERTEX);                                   \
    1053            LOG_FLAG_VERTEX_W (CURVE_FIT);                                      \
    1054            LOG_FLAG_VERTEX_W (UNUSED_4);                                       \
    1055            LOG_FLAG_VERTEX_W (SPLINE_FIT);                                     \
    1056            LOG_FLAG_VERTEX_W (SPLINE_FRAME_CONTROL_POINT);                     \
    1057            LOG_FLAG_VERTEX_W (3D);                                             \
    1058            LOG_FLAG_VERTEX_W (MESH);                                           \
    1059            LOG_FLAG_VERTEX_W (PFACE_MESH);                                     \
    1060            LOG_FLAG_MAX (_obj->flag, 255);                                     \
    1061            LOG_TRACE ("\n");                                                   \
    1062          }                                                                     \
    1063      }
    1064  #endif
    1065  
    1066  #ifndef LOG_POLYLINE_CURVETYPE
    1067  #  define LOG_POLYLINE_CURVETYPE_W(w)                                         \
    1068      if (_obj->curve_type == POLYLINE_CURVETYPE_##w)                           \
    1069      LOG_TRACE (#w "(0x%x) ", POLYLINE_CURVETYPE_##w)
    1070  #  define LOG_POLYLINE_CURVETYPE                                              \
    1071      DECODER_OR_ENCODER                                                        \
    1072      {                                                                         \
    1073        if (_obj->curve_type)                                                   \
    1074          {                                                                     \
    1075            LOG_TRACE ("            ");                                         \
    1076            LOG_POLYLINE_CURVETYPE_W (DEFAULT);                                 \
    1077            LOG_POLYLINE_CURVETYPE_W (QUADR_BSPLINE);                           \
    1078            LOG_POLYLINE_CURVETYPE_W (CUBIC_BSPLINE);                           \
    1079            LOG_POLYLINE_CURVETYPE_W (BEZIER_SURFACE);                          \
    1080            LOG_FLAG_MAX (_obj->curve_type, 8);                                 \
    1081            LOG_TRACE ("\n");                                                   \
    1082          }                                                                     \
    1083      }
    1084  #endif
    1085  
    1086  #ifndef LOG_LEADER_PATHTYPE
    1087  #  define LOG_LEADER_PATHTYPE_W(w)                                            \
    1088      if (_obj->path_type == LEADER_PATHTYPE_##w)                               \
    1089      LOG_TRACE (#w "(0x%x) ", LEADER_PATHTYPE_##w)
    1090  #  define LOG_LEADER_PATHTYPE                                                 \
    1091      DECODER_OR_ENCODER                                                        \
    1092      {                                                                         \
    1093        if (_obj->path_type)                                                    \
    1094          {                                                                     \
    1095            LOG_TRACE ("           ");                                          \
    1096            LOG_LEADER_PATHTYPE_W (STRAIGHT);                                   \
    1097            LOG_LEADER_PATHTYPE_W (SPLINE);                                     \
    1098            LOG_FLAG_MAX (_obj->path_type, 3);                                  \
    1099            LOG_TRACE ("\n");                                                   \
    1100          }                                                                     \
    1101      }
    1102  #endif
    1103  
    1104  #ifndef LOG_LEADER_ANNOTTYPE
    1105  #  define LOG_LEADER_ANNOTTYPE_W(w)                                           \
    1106      if (_obj->annot_type == LEADER_ANNOTTYPE_##w)                             \
    1107      LOG_TRACE (#w "(0x%x) ", LEADER_ANNOTTYPE_##w)
    1108  #  define LOG_LEADER_ANNOTTYPE                                                \
    1109      DECODER_OR_ENCODER                                                        \
    1110      {                                                                         \
    1111        if (_obj->annot_type)                                                   \
    1112          {                                                                     \
    1113            LOG_TRACE ("            ");                                         \
    1114            LOG_LEADER_ANNOTTYPE_W (MTEXT);                                     \
    1115            LOG_LEADER_ANNOTTYPE_W (TOLERANCE);                                 \
    1116            LOG_LEADER_ANNOTTYPE_W (INSERT);                                    \
    1117            LOG_LEADER_ANNOTTYPE_W (NO_ANNOT);                                  \
    1118            LOG_FLAG_MAX (_obj->annot_type, 15);                                \
    1119            LOG_TRACE ("\n");                                                   \
    1120          }                                                                     \
    1121      }
    1122  #endif
    1123  
    1124  #ifndef LOG_MLINE_FLAGS
    1125  #  define LOG_MLINE_FLAGS_W(w)                                                \
    1126      if (_obj->flags & MLINE_FLAGS_##w)                                        \
    1127      LOG_TRACE (#w "(0x%x) ", MLINE_FLAGS_##w)
    1128  #  define LOG_MLINE_FLAGS                                                     \
    1129      DECODER_OR_ENCODER                                                        \
    1130      {                                                                         \
    1131        if (_obj->flags)                                                        \
    1132          {                                                                     \
    1133            LOG_TRACE ("     ");                                                \
    1134            LOG_MLINE_FLAGS_W (HAS_VERTEX);                                     \
    1135            LOG_MLINE_FLAGS_W (CLOSED);                                         \
    1136            LOG_MLINE_FLAGS_W (SUPPRESS_START_CAPS);                            \
    1137            LOG_MLINE_FLAGS_W (SUPPRESS_END_CAPS);                              \
    1138            LOG_FLAG_MAX (_obj->flags, 15);                                     \
    1139            LOG_TRACE ("\n");                                                   \
    1140          }                                                                     \
    1141      }
    1142  #endif
    1143  
    1144  #ifndef LOG_MLINE_JUSTIFICATION
    1145  #  define LOG_MLINE_JUSTIFICATION_W(w)                                        \
    1146      if (_obj->justification == MLINE_JUSTIFICATION_##w)                       \
    1147      LOG_TRACE (#w "(0x%x) ", MLINE_JUSTIFICATION_##w)
    1148  #  define LOG_MLINE_JUSTIFICATION                                             \
    1149      DECODER_OR_ENCODER                                                        \
    1150      {                                                                         \
    1151        if (_obj->justification)                                                \
    1152          {                                                                     \
    1153            LOG_TRACE ("             ");                                        \
    1154            LOG_MLINE_JUSTIFICATION_W (TOP);                                    \
    1155            LOG_MLINE_JUSTIFICATION_W (MIDDLE);                                 \
    1156            LOG_MLINE_JUSTIFICATION_W (BOTTOM);                                 \
    1157            LOG_FLAG_MAX (_obj->justification, 3);                              \
    1158            LOG_TRACE ("\n");                                                   \
    1159          }                                                                     \
    1160      }
    1161  #endif
    1162  
    1163  #ifndef LOG_SPLINE_SCENARIO
    1164  #  define LOG_SPLINE_SCENARIO_W(w)                                            \
    1165      if (_obj->scenario == SPLINE_SCENARIO_##w)                                \
    1166      LOG_TRACE (#w "(0x%x) ", SPLINE_SCENARIO_##w)
    1167  #  define LOG_SPLINE_SCENARIO                                                 \
    1168      DECODER_OR_ENCODER                                                        \
    1169      {                                                                         \
    1170        if (_obj->scenario)                                                     \
    1171          {                                                                     \
    1172            LOG_TRACE ("         ");                                            \
    1173            LOG_SPLINE_SCENARIO_W (SPLINE);                                     \
    1174            LOG_SPLINE_SCENARIO_W (BEZIER);                                     \
    1175            LOG_FLAG_MAX (_obj->scenario, 2);                                   \
    1176            LOG_TRACE ("\n");                                                   \
    1177          }                                                                     \
    1178      }
    1179  #endif
    1180  #ifndef LOG_SPLINE_SPLINEFLAGS
    1181  #  define LOG_SPLINE_SPLINEFLAGS_W(w)                                         \
    1182      if (_obj->splineflags & SPLINE_SPLINEFLAGS_##w)                           \
    1183      LOG_TRACE (#w "(0x%x) ", SPLINE_SPLINEFLAGS_##w)
    1184  #  define LOG_SPLINE_SPLINEFLAGS                                              \
    1185      DECODER_OR_ENCODER                                                        \
    1186      {                                                                         \
    1187        if (_obj->splineflags)                                                  \
    1188          {                                                                     \
    1189            LOG_TRACE ("            ");                                         \
    1190            LOG_SPLINE_SPLINEFLAGS_W (METHOD_FIT_POINTS);                       \
    1191            LOG_SPLINE_SPLINEFLAGS_W (CV_FRAME_SHOW);                           \
    1192            LOG_SPLINE_SPLINEFLAGS_W (CLOSED);                                  \
    1193            LOG_FLAG_MAX (_obj->splineflags, 7);                                \
    1194            LOG_TRACE ("\n");                                                   \
    1195          }                                                                     \
    1196      }
    1197  #endif
    1198  #ifndef LOG_SPLINE_KNOTPARAM
    1199  #  define LOG_SPLINE_KNOTPARAM_W(w)                                           \
    1200      if (_obj->knotparam == SPLINE_KNOTPARAM_##w)                              \
    1201      LOG_TRACE (#w "(0x%x) ", SPLINE_KNOTPARAM_##w)
    1202  #  define LOG_SPLINE_KNOTPARAM                                                \
    1203      DECODER_OR_ENCODER                                                        \
    1204      {                                                                         \
    1205        if (_obj->knotparam)                                                    \
    1206          {                                                                     \
    1207            LOG_TRACE ("          ");                                           \
    1208            LOG_SPLINE_KNOTPARAM_W (CHORD);                                     \
    1209            LOG_SPLINE_KNOTPARAM_W (SQUARE_ROOT);                               \
    1210            LOG_SPLINE_KNOTPARAM_W (UNIFORM);                                   \
    1211            LOG_SPLINE_KNOTPARAM_W (CUSTOM);                                    \
    1212            LOG_FLAG_MAX (_obj->knotparam, 15);                                 \
    1213            LOG_TRACE ("\n");                                                   \
    1214          }                                                                     \
    1215      }
    1216  #endif
    1217  
    1218  #ifndef LOG_LIGHT_TYPE
    1219  #  define LOG_LIGHT_TYPE_W(w)                                                 \
    1220      if (_obj->type == LIGHT_TYPE_##w)                                         \
    1221      LOG_TRACE (#w "(0x%x) ", LIGHT_TYPE_##w)
    1222  #  define LOG_LIGHT_TYPE                                                      \
    1223      DECODER_OR_ENCODER                                                        \
    1224      {                                                                         \
    1225        if (_obj->type)                                                         \
    1226          {                                                                     \
    1227            LOG_TRACE ("      ");                                               \
    1228            LOG_LIGHT_TYPE_W (DISTANT);                                         \
    1229            LOG_LIGHT_TYPE_W (POINT);                                           \
    1230            LOG_LIGHT_TYPE_W (SPOT);                                            \
    1231            LOG_FLAG_MAX (_obj->type, 3);                                       \
    1232            LOG_TRACE ("\n");                                                   \
    1233          }                                                                     \
    1234      }
    1235  #endif
    1236  
    1237  #ifndef LOG_LIGHT_ATTENUATION_TYPE
    1238  #  define LOG_LIGHT_ATTENUATION_W(w)                                          \
    1239      if (_obj->attenuation_type == LIGHT_ATTENUATION_TYPE_##w)                 \
    1240      LOG_TRACE (#w "(0x%x) ", LIGHT_ATTENUATION_TYPE_##w)
    1241  #  define LOG_LIGHT_ATTENUATION_TYPE                                          \
    1242      DECODER_OR_ENCODER                                                        \
    1243      {                                                                         \
    1244        LOG_TRACE ("      ");                                                   \
    1245        LOG_LIGHT_ATTENUATION_W (NONE);                                         \
    1246        LOG_LIGHT_ATTENUATION_W (INV_LINEAR);                                   \
    1247        LOG_LIGHT_ATTENUATION_W (INV_SQUARE);                                   \
    1248        LOG_FLAG_MAX (_obj->attenuation_type, 2);                               \
    1249        LOG_TRACE ("\n");                                                       \
    1250      }
    1251  #endif
    1252  
    1253  #ifndef LOG_LIGHT_EXTLIGHT_SHAPE
    1254  #  define LOG_EXTLIGHT_SHAPE_W(w)                                             \
    1255      if (_obj->extlight_shape == LIGHT_EXTLIGHT_SHAPE_##w)                     \
    1256      LOG_TRACE (#w "(0x%x) ", LIGHT_EXTLIGHT_SHAPE_##w)
    1257  #  define LOG_LIGHT_EXTLIGHT_SHAPE                                            \
    1258      DECODER_OR_ENCODER                                                        \
    1259      {                                                                         \
    1260        LOG_TRACE ("      ");                                                   \
    1261        LOG_EXTLIGHT_SHAPE_W (LINEAR);                                          \
    1262        LOG_EXTLIGHT_SHAPE_W (RECT);                                            \
    1263        LOG_EXTLIGHT_SHAPE_W (DISK);                                            \
    1264        LOG_EXTLIGHT_SHAPE_W (CYLINDER);                                        \
    1265        LOG_EXTLIGHT_SHAPE_W (SPHERE);                                          \
    1266        LOG_FLAG_MAX (_obj->extlight_shape, 4);                                 \
    1267        LOG_TRACE ("\n");                                                       \
    1268      }
    1269  #endif
    1270  
    1271  #ifndef LOG_3DFACE_INVISIBLE
    1272  #  define LOG_INVISIBLE_W(w)                                                  \
    1273      if (_obj->invis_flags & _3DFACE_INVISIBLE_##w)                            \
    1274      LOG_TRACE (#w "(0x%x) ", _3DFACE_INVISIBLE_##w)
    1275  #  define LOG_3DFACE_INVISIBLE                                                \
    1276      DECODER_OR_ENCODER                                                        \
    1277      {                                                                         \
    1278        if (_obj->invis_flags)                                                  \
    1279          {                                                                     \
    1280            LOG_TRACE ("             ");                                        \
    1281            LOG_INVISIBLE_W (EDGE1);                                            \
    1282            LOG_INVISIBLE_W (EDGE2);                                            \
    1283            LOG_INVISIBLE_W (EDGE3);                                            \
    1284            LOG_INVISIBLE_W (EDGE4);                                            \
    1285            LOG_FLAG_MAX (_obj->invis_flags, 15);                               \
    1286            LOG_TRACE ("\n");                                                   \
    1287          }                                                                     \
    1288      }
    1289  #endif
    1290  
    1291  #ifdef IS_DECODER
    1292  #  define PRER13_SECTION_HDR(name)                                            \
    1293      if (decode_preR13_section_hdr (#name, SECTION_##name, dat, dwg))          \
    1294      return DWG_ERR_SECTIONNOTFOUND
    1295  #elif defined IS_ENCODER
    1296  #  define PRER13_SECTION_HDR(name)                                            \
    1297      encode_preR13_section_hdr (#name, SECTION_##name, dat, dwg)
    1298  #  define DWG_TABLE(token) DWG_OBJECT (token)
    1299  #else
    1300  #  define PRER13_SECTION_HDR(name)
    1301  #  define DWG_TABLE(token) DWG_OBJECT (token)
    1302  #endif