(root)/
libredwg-0.13/
programs/
dwglayers.c
       1  /*****************************************************************************/
       2  /*  LibreDWG - free implementation of the DWG file format                    */
       3  /*                                                                           */
       4  /*  Copyright (C) 2018-2019 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  /*
      14   * dwglayers.c: print list of layers in a DWG
      15   *
      16   * written by Reini Urban
      17   */
      18  
      19  #include "../src/config.h"
      20  #include <stdio.h>
      21  #include <stdlib.h>
      22  #include <string.h>
      23  #include <assert.h>
      24  #include "my_getopt.h"
      25  #ifdef HAVE_VALGRIND_VALGRIND_H
      26  #  include <valgrind/valgrind.h>
      27  #endif
      28  
      29  #include <dwg.h>
      30  #include "common.h"
      31  #include "bits.h"
      32  #include "logging.h"
      33  
      34  static int
      35  usage (void)
      36  {
      37    printf ("\nUsage: dwglayers [-f|--flags] [--on] <input_file.dwg>\n");
      38    return 1;
      39  }
      40  static int
      41  opt_version (void)
      42  {
      43    printf ("dwglayers %s\n", PACKAGE_VERSION);
      44    return 0;
      45  }
      46  static int
      47  help (void)
      48  {
      49    printf ("\nUsage: dwglayers [OPTION]... DWGFILE\n");
      50    printf ("Print list of layers.\n"
      51            "\n");
      52  #ifdef HAVE_GETOPT_LONG
      53    printf ("  -x, --extnames            prints EXTNAMES (r13-r14 only)\n"
      54            "                i.e. space instead of _\n");
      55    printf ("  -f, --flags               prints also flags:\n"
      56            "                3 chars for: f for frozen, + or - for ON or OFF, l "
      57            "for locked\n");
      58    printf ("  -o, --on                  prints only ON layers\n");
      59    printf ("  -h, --help                display this help and exit\n");
      60    printf ("      --version             output version information and exit\n"
      61            "\n");
      62  #else
      63    printf ("  -x            prints EXTNAMES (r13-r14 only)\n"
      64            "                i.e. space instead of _\n");
      65    printf ("  -f            prints also flags:\n"
      66            "                3 chars for: f for frozen, + or - for ON or OFF, l "
      67            "for locked\n");
      68    printf ("  -o            prints only ON layers\n");
      69    printf ("  -h            display this help and exit\n");
      70    printf ("  -i            output version information and exit\n"
      71            "\n");
      72  #endif
      73    printf ("GNU LibreDWG online manual: "
      74            "<https://www.gnu.org/software/libredwg/>\n");
      75    return 0;
      76  }
      77  
      78  int
      79  main (int argc, char *argv[])
      80  {
      81    int error;
      82    long i = 1;
      83    int flags = 0, on = 0, extnames = 0;
      84    char *filename_in;
      85    Dwg_Data dwg;
      86    Dwg_Object *obj;
      87    Dwg_Object_LAYER *layer;
      88    Dwg_Object_LAYER_CONTROL *_ctrl;
      89    int c;
      90  #ifdef HAVE_GETOPT_LONG
      91    int option_index = 0;
      92    static struct option long_options[]
      93        = { { "flags", 0, 0, 'f' }, { "extnames", 0, 0, 'x' },
      94            { "on", 0, 0, 'o' },    { "help", 0, 0, 0 },
      95            { "version", 0, 0, 0 }, { NULL, 0, NULL, 0 } };
      96  #endif
      97  
      98    while
      99  #ifdef HAVE_GETOPT_LONG
     100        ((c = getopt_long (argc, argv, "xfoh", long_options, &option_index))
     101         != -1)
     102  #else
     103        ((c = getopt (argc, argv, "xfohi")) != -1)
     104  #endif
     105      {
     106        if (c == -1)
     107          break;
     108        switch (c)
     109          {
     110  #ifdef HAVE_GETOPT_LONG
     111          case 0:
     112            if (!strcmp (long_options[option_index].name, "version"))
     113              return opt_version ();
     114            if (!strcmp (long_options[option_index].name, "help"))
     115              return help ();
     116            break;
     117  #else
     118          case 'i':
     119            return opt_version ();
     120  #endif
     121          case 'x':
     122            extnames = 1;
     123            break;
     124          case 'f':
     125            flags = 1;
     126            break;
     127          case 'o':
     128            on = 1;
     129            break;
     130          case 'h':
     131            return help ();
     132          case '?':
     133            fprintf (stderr, "%s: invalid option '-%c' ignored\n", argv[0],
     134                     optopt);
     135            break;
     136          default:
     137            return usage ();
     138          }
     139      }
     140    i = optind;
     141    if (i >= argc)
     142      return usage ();
     143  
     144    filename_in = argv[i];
     145    memset (&dwg, 0, sizeof (Dwg_Data));
     146    error = dwg_read_file (filename_in, &dwg);
     147    if (error >= DWG_ERR_CRITICAL)
     148      {
     149        fprintf (stderr, "READ ERROR %s: 0x%x\n", filename_in, error);
     150        goto done;
     151      }
     152  
     153    obj = dwg_get_first_object (&dwg, DWG_TYPE_LAYER_CONTROL);
     154    if (!obj)
     155      {
     156        fprintf (stderr, "No layers found\n");
     157        goto done;
     158      }
     159    _ctrl = obj->tio.object->tio.LAYER_CONTROL;
     160    for (i = 0; i < _ctrl->num_entries; i++)
     161      {
     162        char *name;
     163        assert (_ctrl->entries);
     164        if (!_ctrl->entries[i]) // NULL BITCODE_H
     165          continue;
     166        obj = _ctrl->entries[i]->obj;
     167        if (!obj || obj->type != DWG_TYPE_LAYER) // can be DICTIONARY also
     168          continue;
     169        assert (_ctrl->entries[i]->obj->tio.object);
     170        layer = _ctrl->entries[i]->obj->tio.object->tio.LAYER;
     171        if (on && (!layer->on || layer->frozen))
     172          continue;
     173        if (flags)
     174          printf ("%s%s%s\t", layer->frozen ? "f" : " ", layer->on ? "+" : "-",
     175                  layer->locked ? "l" : " ");
     176        if (extnames && dwg.header.from_version >= R_13b1
     177            && dwg.header.from_version < R_2000)
     178          {
     179            if (!(name = dwg_find_table_extname (&dwg, obj)))
     180              name = layer->name;
     181          }
     182        else
     183          name = layer->name;
     184        if (!name)
     185          {
     186            LOG_ERROR ("Invalid layer " FORMAT_RLLx " ignored, empty name",
     187                       _ctrl->entries[i]->obj->handle.value)
     188          }
     189        else
     190          {
     191            // since r2007 unicode, converted to utf-8
     192            if (dwg.header.from_version >= R_2007)
     193              {
     194                char *utf8 = bit_convert_TU ((BITCODE_TU)name);
     195                printf ("%s\n", utf8);
     196                free (utf8);
     197              }
     198            else
     199              printf ("%s\n", name);
     200          }
     201        fflush (stdout);
     202      }
     203  
     204  done:
     205    // forget about valgrind. really huge DWG's need endlessly here.
     206    if ((dwg.header.version && dwg.num_objects < 1000)
     207  #if defined __SANITIZE_ADDRESS__ || __has_feature(address_sanitizer)
     208        || 1
     209  #endif
     210  #ifdef HAVE_VALGRIND_VALGRIND_H
     211        || (RUNNING_ON_VALGRIND)
     212  #endif
     213    )
     214      dwg_free (&dwg);
     215    return error >= DWG_ERR_CRITICAL ? 1 : 0;
     216  }