dwg_decode (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
{
  int i;
  char version[7];

  dwg->num_object_refs = 0;
  // dwg->num_layers = 0; // see now dwg->layer_control->num_entries
  dwg->num_entities = 0;
  dwg->num_objects = 0;
  dwg->num_classes = 0;
  dwg->thumbnail.size = 0;
  dwg->thumbnail.chain = NULL;
  dwg->header.num_sections = 0;
  dwg->header.section_infohdr.num_desc = 0;
  dwg->dwg_class = NULL;
  dwg->object_ref = NULL;
  dwg->object = NULL;
  dwg->object_map = hash_new (dat->size / 1000);
  if (!dwg->object_map)
    {
      // whatever, we are obviously on a tiny system
      dwg->object_map = hash_new (1024);
      if (!dwg->object_map)
        {
          LOG_ERROR ("Out of memory");
          return DWG_ERR_OUTOFMEM;
        }
    }
  dwg->dirty_refs = 1;

  // memset (&dwg->header, 0, sizeof (dwg->header)); // nope. needed for
  // version
  memset (&dwg->header_vars, 0, sizeof (dwg->header_vars));
  memset (&dwg->summaryinfo, 0, sizeof (dwg->summaryinfo));
  memset (&dwg->r2004_header.file_ID_string[0], 0, sizeof (dwg->r2004_header));
  memset (&dwg->auxheader.aux_intro[0], 0, sizeof (dwg->auxheader));
  memset (&dwg->second_header, 0, sizeof (dwg->second_header));

  if (dwg->opts)
    {
      loglevel = dwg->opts & DWG_OPTS_LOGLEVEL;
      dat->opts = dwg->opts;
    }

#ifdef USE_TRACING
  /* Before starting, set the logging level, but only do so once.  */
  if (!env_var_checked_p)
    {
      char *probe = getenv ("LIBREDWG_TRACE");
      if (probe)
        loglevel = atoi (probe);
      env_var_checked_p = true;
    }
#endif /* USE_TRACING */

  /* Version */
  dat->byte = 0;
  dat->bit = 0;
  if (!dat->chain || dat->size < 58)
    {
      LOG_ERROR ("dwg too small: %lu bytes", dat->size);
      return DWG_ERR_INVALIDDWG;
    }
  strncpy (version, (const char *)dat->chain, 6);
  version[6] = '\0';

  dwg->header.version = 0;
  for (i = 0; i < R_AFTER; i++)
    {
      if (strEQ (version, version_codes[(Dwg_Version_Type)i]))
        {
          dwg->header.version = (Dwg_Version_Type)i;
          break;
        }
    }
  if (!dwg->header.version)
    {
      if (strncmp (version, "AC", 2)) // let's ignore MC0.0 for now
        {
          LOG_ERROR ("Invalid DWG, magic: %s", version);
        }
      else
        {
          LOG_ERROR ("Invalid or unimplemented DWG version code %s", version);
        }
      return DWG_ERR_INVALIDDWG;
    }
  dat->version = dwg->header.version;
  dwg->header.from_version = dat->version;
  dat->from_version = dat->version;
  LOG_INFO ("This file's version code is: %s (%s)\n", version,
            dwg_version_type(dat->version))

#define WE_CAN                                                                \
  "This version of LibreDWG is only capable of decoding "                     \
  "version R13-R2018 (code: AC1012-AC1032) DWG files.\n"

  PRE (R_13)
  {
    LOG_ERROR (WE_CAN "We don't decode many entities and no blocks yet.")
#ifndef IS_RELEASE
    return decode_preR13 (dat, dwg);
#endif
  }

  VERSIONS (R_13, R_2000) { return decode_R13_R2000 (dat, dwg); }
  VERSION (R_2004) { return decode_R2004 (dat, dwg); }
  VERSION (R_2007) { return decode_R2007 (dat, dwg); }
  SINCE (R_2010)
  {
    read_r2007_init (dwg);
    return decode_R2004 (dat, dwg);
  }

  // This line should not be reached
  LOG_ERROR ("LibreDWG does not support this version: %s.", version)
  return DWG_ERR_INVALIDDWG;
}
dwg_decode (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
{
  int i;
  char version[7];

  dwg->num_object_refs = 0;
   
  dwg->num_entities = 0;
  dwg->num_objects = 0;
  dwg->num_classes = 0;
  dwg->thumbnail.size = 0;
  dwg->thumbnail.chain = NULL;
  dwg->header.num_sections = 0;
  dwg->header.section_infohdr.num_desc = 0;
  dwg->dwg_class = NULL;
  dwg->object_ref = NULL;
  dwg->object = NULL;
  dwg->object_map = hash_new (dat->size / 1000);
  if (!dwg->object_map)
    {
       
      dwg->object_map = hash_new (1024);
      if (!dwg->object_map)
        {
          LOG_ERROR ("Out of memory");
          return DWG_ERR_OUTOFMEM;
        }
    }
  dwg->dirty_refs = 1;

   
   
  memset (&dwg->header_vars, 0, sizeof (dwg->header_vars));
  memset (&dwg->summaryinfo, 0, sizeof (dwg->summaryinfo));
  memset (&dwg->r2004_header.file_ID_string[0], 0, sizeof (dwg->r2004_header));
  memset (&dwg->auxheader.aux_intro[0], 0, sizeof (dwg->auxheader));
  memset (&dwg->second_header, 0, sizeof (dwg->second_header));

  if (dwg->opts)
    {
      loglevel = dwg->opts & DWG_OPTS_LOGLEVEL;
      dat->opts = dwg->opts;
    }

#ifdef USE_TRACING
   
  if (!env_var_checked_p)
    {
      char *probe = getenv ("LIBREDWG_TRACE");
      if (probe)
        loglevel = atoi (probe);
      env_var_checked_p = true;
    }
#endif  

   
  dat->byte = 0;
  dat->bit = 0;
  if (!dat->chain || dat->size < 58)
    {
      LOG_ERROR ("dwg too small: %lu bytes", dat->size);
      return DWG_ERR_INVALIDDWG;
    }
  strncpy (version, (const char *)dat->chain, 6);
  version[6] = '\0';

  dwg->header.version = 0;
  for (i = 0; i < R_AFTER; i++)
    {
      if (strEQ (version, version_codes[(Dwg_Version_Type)i]))
        {
          dwg->header.version = (Dwg_Version_Type)i;
          break;
        }
    }
  if (!dwg->header.version)
    {
      if (strncmp (version, "AC", 2))  
        {
          LOG_ERROR ("Invalid DWG, magic: %s", version);
        }
      else
        {
          LOG_ERROR ("Invalid or unimplemented DWG version code %s", version);
        }
      return DWG_ERR_INVALIDDWG;
    }
  dat->version = dwg->header.version;
  dwg->header.from_version = dat->version;
  dat->from_version = dat->version;
  LOG_INFO ("This file's version code is: %s (%s)\n", version,
            dwg_version_type(dat->version))

#define WE_CAN                                                                \
  "This version of LibreDWG is only capable of decoding "                     \
  "version R13-R2018 (code: AC1012-AC1032) DWG files.\n"

  PRE (R_13)
  {
    LOG_ERROR (WE_CAN "We don't decode many entities and no blocks yet.")
#ifndef IS_RELEASE
    return decode_preR13 (dat, dwg);
#endif
  }

  VERSIONS (R_13, R_2000) { return decode_R13_R2000 (dat, dwg); }
  VERSION (R_2004) { return decode_R2004 (dat, dwg); }
  VERSION (R_2007) { return decode_R2007 (dat, dwg); }
  SINCE (R_2010)
  {
    read_r2007_init (dwg);
    return decode_R2004 (dat, dwg);
  }

   
  LOG_ERROR ("LibreDWG does not support this version: %s.", version)
  return DWG_ERR_INVALIDDWG;
}