示例#1
0
int main
(  int                  argc
,  const char*          argv[]
)
   {  mcxIO      *xfin        =  mcxIOnew("-", "r")
   ;  mcxIO      *xfout       =  mcxIOnew("-", "w")
   ;  mclMatrix  *mx          =  NULL
   ;  mclx* cmapx = NULL, *rmapx = NULL
   ;  const char* me          =  "mcxmap"
   ;  long        cshift      =  0
   ;  long        rshift      =  0
   ;  long        cmul        =  1
   ;  long        rmul        =  1
   ;  mcxIO*     xf_cannc     =  NULL
   ;  mcxIO*     xf_cannr     =  NULL
   ;  mcxstatus   status      =  STATUS_OK
   ;  mcxbool     invert      =  FALSE
   ;  mcxbool     invertr     =  FALSE
   ;  mcxbool     invertc     =  FALSE
   ;  mcxIO* xf_map_c = NULL, *xf_map_r = NULL, *xf_map = NULL, *xf_tab = NULL

   ;  mcxOption* opts, *opt
   ;  mcxstatus parseStatus = STATUS_OK

   ;  mcxLogLevel =
      MCX_LOG_AGGR | MCX_LOG_MODULE | MCX_LOG_IO | MCX_LOG_GAUGE | MCX_LOG_WARN
   ;  mclxIOsetQMode("MCLXIOVERBOSITY", MCL_APP_VB_NO)
   ;  mclx_app_init(stderr)
   
   ;  mcxOptAnchorSortById(options, sizeof(options)/sizeof(mcxOptAnchor) -1)
   ;  opts = mcxOptParse(options, (char**) argv, argc, 1, 0, &parseStatus)

   ;  if (!opts)
      exit(0)

   ;  for (opt=opts;opt->anch;opt++)
      {  mcxOptAnchor* anch = opt->anch

      ;  switch(anch->id)
         {  case MY_OPT_HELP
         :  case MY_OPT_APROPOS
         :  mcxOptApropos(stdout, me, syntax, 0, 0, options)
         ;  return 0
         ;

            case MY_OPT_VERSION
         :  app_report_version(me)
         ;  return 0
         ;

            case MY_OPT_IMX
         :  mcxIOnewName(xfin, opt->val)
         ;  break
         ;

            case MY_OPT_OUT
         :  mcxIOnewName(xfout, opt->val)
         ;  break
         ;

            case MY_OPT_MUL
         :  cmul =  atol(opt->val)
         ;  rmul =  cmul
         ;  break
         ;

            case MY_OPT_CMUL
         :  cmul =  atol(opt->val)
         ;  break
         ;

            case MY_OPT_RMUL
         :  rmul =  atol(opt->val)
         ;  break
         ;

            case MY_OPT_SHIFT
         :  cshift =  atol(opt->val)
         ;  rshift =  atol(opt->val)
         ;  break
         ;

            case MY_OPT_CSHIFT
         :  cshift =  atol(opt->val)
         ;  break
         ;

            case MY_OPT_RSHIFT
         :  rshift =  atol(opt->val)
         ;  break
         ;

            case MY_OPT_MAP
         :  xf_map =  mcxIOnew(opt->val, "r")
         ;  invert =  FALSE
         ;  break
         ;

            case MY_OPT_CMAP
         :  invertc  =  FALSE  
         ;  xf_map_c =  mcxIOnew(opt->val, "r")
         ;  break
         ;

            case MY_OPT_RMAP
         :  invertr  =  FALSE  
         ;  xf_map_r =  mcxIOnew(opt->val, "r")
         ;  break
         ;

            case MY_OPT_MAPI
         :  invert =  TRUE  
         ;  xf_map =  mcxIOnew(opt->val, "r")
         ;  break
         ;

            case MY_OPT_CMAPI
         :  invertc  =  TRUE  
         ;  xf_map_c =  mcxIOnew(opt->val, "r")
         ;  break
         ;

            case MY_OPT_RMAPI
         :  invertr  =  TRUE  
         ;  xf_map_r =  mcxIOnew(opt->val, "r")
         ;  break
         ;

            case MY_OPT_MAKE_MAP
         :  xf_cannc = mcxIOnew(opt->val, "w")
         ;  xf_cannr = xf_cannc
         ;  break
         ;

            case MY_OPT_MAKE_MAPC
         :  xf_cannc = mcxIOnew(opt->val, "w")
         ;  break
         ;

            case MY_OPT_MAKE_MAPR
         :  xf_cannr = mcxIOnew(opt->val, "w")
         ;  break
         ;

            case MY_OPT_TAB
         :  xf_tab = mcxIOnew(opt->val, "r")
         ;  break
         ;
         }
      }

                     /* little special case. restructure when it grows */
      if (xf_tab)
      {  mclTab* tab1, *tab2
      ;  if (xf_map)
         {  mcxIOopen(xf_map, EXIT_ON_FAIL)
         ;  cmapx = mclxRead(xf_map, EXIT_ON_FAIL)  
      ;  }
         else
         mcxDie(1, me, "-tab option requires -map option")

      ;  tab1 = mclTabRead(xf_tab, NULL, EXIT_ON_FAIL)
      ;  if ((tab2 = mclTabMap(tab1, cmapx)))
         mclTabWrite(tab2, xfout, NULL, EXIT_ON_FAIL)
       ; else
         mcxDie(1, me, "map file error (subsumption/bijection)")

      ;  return 0
   ;  }

      mx = mclxRead(xfin, EXIT_ON_FAIL)

   ;  if (xf_map)
      {  mcxIOopen(xf_map, EXIT_ON_FAIL)
      ;  cmapx = mclxRead(xf_map, EXIT_ON_FAIL)  
      ;  rmapx = cmapx
   ;  }
      else
      {  if (xf_map_c)
         {  mcxIOopen(xf_map_c, EXIT_ON_FAIL)
         ;  cmapx = mclxRead(xf_map_c, EXIT_ON_FAIL)  
      ;  }
         else if (cshift || cmul > 1)
         cmapx
         =  mclxMakeMap
            (  mclvCopy(NULL, mx->dom_cols)
            ,  mclvMap(NULL, cmul, cshift, mx->dom_cols)
            )
      ;  else if (xf_cannc)      /* fixme slightly flaky interface */
         {  cmapx 
            =  mclxMakeMap
               (  mclvCopy(NULL, mx->dom_cols)
               ,  mclvCanonical(NULL, mx->dom_cols->n_ivps, 1.0)
               )
         ;  mclxWrite(cmapx, xf_cannc, MCLXIO_VALUE_GETENV, RETURN_ON_FAIL)
      ;  }

         if (xf_map_r)
         {  mcxIOopen(xf_map_r, EXIT_ON_FAIL)
         ;  rmapx = mclxRead(xf_map_r, EXIT_ON_FAIL)  
      ;  }
         else if (rshift || rmul > 1)
         rmapx
         =  mclxMakeMap
            (  mclvCopy(NULL, mx->dom_rows)
            ,  mclvMap(NULL, rmul, rshift, mx->dom_rows)
            )
      ;  else if (xf_cannr)
         {  rmapx 
            =  mclxMakeMap
               (  mclvCopy(NULL, mx->dom_rows)
               ,  mclvCanonical(NULL, mx->dom_rows->n_ivps, 1.0)
               )
         ;  if (xf_cannr != xf_cannc)
            mclxWrite(rmapx, xf_cannr, MCLXIO_VALUE_GETENV, RETURN_ON_FAIL)
         ;  else if (!mclxIsGraph(mx))
            mcxErr(me, "row map not written but matrix is not a graph")
      ;  }
      }

      if (invert && cmapx && cmapx == rmapx)
      {  mclx* cmapxi = mclxTranspose(cmapx)
      ;  mclxFree(&cmapx)
      ;  cmapx = rmapx = cmapxi
   ;  }
      else
      {  if ((invert || invertr) && rmapx)
         {  mclx* rmapxi = mclxTranspose(rmapx)
         ;  mclxFree(&rmapx)
         ;  rmapx = rmapxi
      ;  }
         if ((invert || invertc) && cmapx)
         {  mclx* cmapxi = mclxTranspose(cmapx)
         ;  mclxFree(&cmapx)
         ;  cmapx = cmapxi
      ;  }
      }

   ;  status = STATUS_FAIL

   ;  do
      {  if (cmapx && mclxMapCols(mx, cmapx))
         break
      ;  if (rmapx && mclxMapRows(mx, rmapx))
         break
      ;  status = STATUS_OK
   ;  }
      while (0)

   ;  if (status)
      {  mcxErr(me, "error, nothing written")
      ;  return 1
   ;  }

      mclxWrite(mx, xfout, MCLXIO_VALUE_GETENV, EXIT_ON_FAIL)
   ;  return 0
;  }
示例#2
0
int main
(  int                  argc
,  const char*          argv[]
)
   {  mcxIO* xf_tab     =  NULL
   ;  mcxIO* xf_tabr    =  NULL
   ;  mcxIO* xf_tabc    =  NULL
   ;  mcxIO* xf_restrict_tab     =  NULL
   ;  mcxIO* xf_restrict_tabr    =  NULL
   ;  mcxIO* xf_restrict_tabc    =  NULL
   ;  mcxIO* xf_mx      =  mcxIOnew("-", "r")
   ;  mcxIO* xfout    =  NULL
   ;  const char*  fndump  =  "-"
   ;  mclTab* tabr      =  NULL
   ;  mclTab* tabc      =  NULL
   ;  mclTab* restrict_tabr =  NULL
   ;  mclTab* restrict_tabc =  NULL
   ;  mcxbool transpose =  FALSE
   ;  mcxbool lazy_tab  =  FALSE
   ;  mcxbool write_tabc =  FALSE
   ;  mcxbool write_tabr =  FALSE
   ;  mcxbool cat       =  FALSE
   ;  mcxbool tree      =  FALSE
   ;  mcxbool skel      =  FALSE
   ;  mcxbool newick    =  FALSE
   ;  mcxbits newick_bits = 0
   ;  mcxbits cat_bits  =  0
   ;  dim catmax        =  1
   ;  dim n_max         =  0
   ;  dim table_nlines  =  0
   ;  dim table_nfields =  0
   ;  int split_idx     =  1
   ;  int split_inc     =  1
   ;  const char* split_stem =  NULL
   ;  const char* sort_mode = NULL
   ;  mcxTing* line     =  mcxTingEmpty(NULL, 10)

   ;  mcxbits modes     =  MCLX_DUMP_VALUES

   ;  mcxbits mode_dump =  MCLX_DUMP_PAIRS
   ;  mcxbits mode_part =  0
   ;  mcxbits mode_loop =  MCLX_DUMP_LOOP_ASIS
   ;  mcxbits mode_matrix = 0
   ;  int digits        =  MCLXIO_VALUE_GETENV

   ;  mcxOption* opts, *opt
   ;  mcxstatus parseStatus = STATUS_OK

   ;  mcxLogLevel =
      MCX_LOG_AGGR | MCX_LOG_MODULE | MCX_LOG_IO | MCX_LOG_GAUGE | MCX_LOG_WARN
   ;  mclxIOsetQMode("MCLXIOVERBOSITY", MCL_APP_VB_YES)
   ;  mclx_app_init(stderr)
   
   ;  mcxOptAnchorSortById(options, sizeof(options)/sizeof(mcxOptAnchor) -1)
   ;  opts = mcxOptParse(options, (char**) argv, argc, 1, 0, &parseStatus)

   ;  if (!opts)
      exit(0)

   ;  for (opt=opts;opt->anch;opt++)
      {  mcxOptAnchor* anch = opt->anch

      ;  switch(anch->id)
         {  case MY_OPT_HELP
         :  case MY_OPT_APROPOS
         :  mcxOptApropos(stdout, me, syntax, 0, 0, options)
         ;  return 0
         ;

            case MY_OPT_VERSION
         :  app_report_version(me)
         ;  return 0
         ;

            case MY_OPT_TAB
         :  xf_tab = mcxIOnew(opt->val, "r")
         ;  break
         ;

            case MY_OPT_TABC
         :  xf_tabc = mcxIOnew(opt->val, "r")
         ;  break
         ;

            case MY_OPT_TABR
         :  xf_tabr = mcxIOnew(opt->val, "r")
         ;  break
         ;

            case MY_OPT_OUTPUT
         :  fndump = opt->val
         ;  break
         ;

            case MY_OPT_SEP_LEAD
         :  sep_lead_g = opt->val
         ;  break
         ;

            case MY_OPT_SEP_FIELD
         :  sep_row_g = opt->val
         ;  break
         ;

            case MY_OPT_SEP_CAT
         :  sep_cat_g = opt->val
         ;  break
         ;

            case MY_OPT_SEP_VAL
         :  sep_val_g = opt->val
         ;  break
         ;

            case MY_OPT_PREFIXC
         :  prefixc_g = opt->val
         ;  break
         ;

            case MY_OPT_RESTRICT_TAB
         :  xf_restrict_tab = mcxIOnew(opt->val, "r")
         ;  break
         ;

            case MY_OPT_RESTRICT_TABC
         :  xf_restrict_tabc = mcxIOnew(opt->val, "r")
         ;  break
         ;

            case MY_OPT_RESTRICT_TABR
         :  xf_restrict_tabr = mcxIOnew(opt->val, "r")
         ;  break
         ;

            case MY_OPT_LAZY_TAB
         :  lazy_tab = TRUE
         ;  break
         ;

            case MY_OPT_NO_VALUES
         :  BIT_OFF(modes, MCLX_DUMP_VALUES)
         ;  break
         ;

            case MY_OPT_DUMP_RLINES
         :  mode_dump = MCLX_DUMP_LINES
         ;  BIT_ON(modes, MCLX_DUMP_NOLEAD)
         ;  break
         ;

            case MY_OPT_DUMP_VLINES
         :  mode_dump = MCLX_DUMP_LINES
         ;  BIT_ON(modes, MCLX_DUMP_LEAD_VALUE)
         ;  break
         ;

            case MY_OPT_DUMP_LINES
         :  mode_dump = MCLX_DUMP_LINES
         ;  break
         ;

            case MY_OPT_OMIT_EMPTY
         :  BIT_ON(modes, MCLX_DUMP_OMIT_EMPTY)
         ;  break
         ;

            case MY_OPT_SORT
         :  sort_mode = opt->val
         ;  break
         ;

            case MY_OPT_NO_LOOPS
         :  mode_loop = MCLX_DUMP_LOOP_NONE
         ;  break
         ;

            case MY_OPT_CAT_LIMIT
         :  n_max = atoi(opt->val)
         ;  break
         ;

            case MY_OPT_SPLIT_STEM
         :  split_stem = opt->val
         ;  sep_cat_g = NULL
         ;  break
         ;

            case MY_OPT_FORCE_LOOPS
         :  mode_loop = MCLX_DUMP_LOOP_FORCE
         ;  break
         ;

            case MY_OPT_SKEL
         :  skel = TRUE
         ;  break
         ;

            case MY_OPT_WRITE_TABC
         :  write_tabc = TRUE
         ;  break
         ;

            case MY_OPT_DIGITS
         :  digits = strtol(opt->val, NULL, 10)
         ;  break
         ;

            case MY_OPT_WRITE_TABR
         :  write_tabr = TRUE
         ;  break
         ;

            case MY_OPT_DUMP_RDOM
         :  transpose = TRUE
         ;  skel = TRUE
         ;  mode_dump = MCLX_DUMP_LINES
         ;  break
         ;

            case MY_OPT_DUMP_CDOM
         :  skel = TRUE
         ;  mode_dump = MCLX_DUMP_LINES
         ;  break
         ;

            case MY_OPT_IMX
         :  mcxIOnewName(xf_mx, opt->val)
         ;  break
         ;

            case MY_OPT_ICL
         :  mcxIOnewName(xf_mx, opt->val)
         ;  mode_dump = MCLX_DUMP_LINES
         ;  BIT_ON(modes, MCLX_DUMP_NOLEAD)
         ;  BIT_OFF(modes, MCLX_DUMP_VALUES)
         ;  break
         ;

            case MY_OPT_TREECAT
         :  mcxIOnewName(xf_mx, opt->val)
         ;  tree = TRUE
         ;  cat_bits |= MCLX_PRODUCE_DOMSTACK
         ;  break
         ;

            case MY_OPT_CAT
         :  mcxIOnewName(xf_mx, opt->val)
         ;  cat = TRUE
         ;  break
         ;

            case MY_OPT_DUMP_MATRIX
         :  mode_matrix |= MCLX_DUMP_MATRIX
         ;  break
         ;

            case MY_OPT_TRANSPOSE
         :  transpose = TRUE
         ;  break
         ;

            case MY_OPT_DUMP_UPPER
         :  mode_part = MCLX_DUMP_PART_UPPER
         ;  break
         ;

            case MY_OPT_DUMP_UPPERI
         :  mode_part = MCLX_DUMP_PART_UPPERI
         ;  break
         ;

            case MY_OPT_DUMP_LOWER
         :  mode_part = MCLX_DUMP_PART_LOWER
         ;  break
         ;

            case MY_OPT_DUMP_LOWERI
         :  mode_part = MCLX_DUMP_PART_LOWERI
         ;  break
         ;

            case MY_OPT_DUMP_NOLEAD
         :  BIT_ON(modes, MCLX_DUMP_NOLEAD)
         ;  break
         ;

            case MY_OPT_NEWICK_MODE
         :  if (strchr(opt->val, 'N'))
            newick_bits |= (MCLX_NEWICK_NONL | MCLX_NEWICK_NOINDENT)
         ;  if (strchr(opt->val, 'I'))
            newick_bits |= MCLX_NEWICK_NOINDENT
         ;  if (strchr(opt->val, 'B'))
            newick_bits |= MCLX_NEWICK_NONUM
         ;  if (strchr(opt->val, 'S'))
            newick_bits |= MCLX_NEWICK_NOPTHS
         ;  newick = TRUE
         ;  break
         ;

            case MY_OPT_DUMP_NEWICK
         :  newick = TRUE
         ;  break
         ;

            case MY_OPT_DUMP_TABLE
         :  mode_dump = MCLX_DUMP_TABLE
         ;  break
         ;

            case MY_OPT_TABLE_NFIELDS
         :  table_nfields = atoi(opt->val)
         ;  break
         ;

            case MY_OPT_TABLE_NLINES
         :  table_nlines = atoi(opt->val)
         ;  break
         ;

            case MY_OPT_DUMP_PAIRS
         :  mode_dump = MCLX_DUMP_PAIRS
         ;  break
      ;  }
      }

   ;  if (skel)
      cat_bits |= MCLX_READ_SKELETON

   ;  modes |= mode_loop | mode_dump | mode_part | mode_matrix

   ;  xfout = mcxIOnew(fndump, "w")
   ;  mcxIOopen(xfout, EXIT_ON_FAIL)

   ;  mcxIOopen(xf_mx, EXIT_ON_FAIL)

   ;  if (cat || tree)
      catmax = n_max ? n_max : 0

   ;  if ((write_tabc || write_tabr) && !xf_tab)
      mcxDie(1, me, "need a single tab file (-tab option) with --write-tabc or --write-tabr")

   ;  if (xf_tab && mcxIOopen(xf_tab, RETURN_ON_FAIL))
      mcxDie(1, me, "no tab")
   ;  else
      {  if (xf_tabr && mcxIOopen(xf_tabr, RETURN_ON_FAIL))
         mcxDie(1, me, "no tabr")
      ;  if (xf_tabc && mcxIOopen(xf_tabc, RETURN_ON_FAIL))
         mcxDie(1, me, "no tabc")
   ;  }

      {  if (xf_restrict_tab && mcxIOopen(xf_restrict_tab, RETURN_ON_FAIL))
         mcxDie(1, me, "no restriction tab")
      ;  else
         {  if (xf_restrict_tabr && mcxIOopen(xf_restrict_tabr, RETURN_ON_FAIL))
            mcxDie(1, me, "no restriction tabr")
         ;  if (xf_restrict_tabc && mcxIOopen(xf_restrict_tabc, RETURN_ON_FAIL))
            mcxDie(1, me, "no restriction tabc")
      ;  }
                              /* fixme: below is pretty boilerplate, happens in other places as well */
         if (xf_restrict_tab)
         {  if (!(restrict_tabr = mclTabRead (xf_restrict_tab, NULL, RETURN_ON_FAIL)))
            mcxDie(1, me, "error reading restriction tab")
         ;  restrict_tabc = restrict_tabr
         ;  mcxIOclose(xf_restrict_tab)
      ;  }
         else
         {  if (xf_restrict_tabr)
            {  if (!(restrict_tabr = mclTabRead(xf_restrict_tabr, NULL, RETURN_ON_FAIL)))
               mcxDie(1, me, "error reading restriction tabr")
            ;  mcxIOclose(xf_restrict_tabr)
         ;  }
            if (xf_restrict_tabc)
            {  if (!(restrict_tabc = mclTabRead(xf_restrict_tabc, NULL, RETURN_ON_FAIL)))
               mcxDie(1, me, "error reading restriction tabc")
            ;  mcxIOclose(xf_restrict_tabc)
         ;  }
         }
      }

                        /* fixme: restructure code to include bit below */

      if (write_tabc || write_tabr)
      {  mclv* dom_cols = mclvInit(NULL)
      ;  mclv* dom_rows = mclvInit(NULL)
      ;  mclv* dom = write_tabc ? dom_cols : dom_rows

      ;  if (!(tabc =  mclTabRead(xf_tab, NULL, RETURN_ON_FAIL)))
         mcxDie(1, me, "error reading tab file")

      ;  if (mclxReadDomains(xf_mx, dom_cols, dom_rows))
         mcxDie(1, me, "error reading matrix file")
      ;  mcxIOclose(xf_mx)

                                       /* fixme check status */
      ;  mclTabWrite(tabc, xfout, dom, RETURN_ON_FAIL) 

      ;  mcxIOclose(xfout)
      ;  return 0
   ;  }

      if (newick)
      {  mcxTing* thetree
      ;  mclxCat  cat

      ;  if (xf_tab && !(tabr =  mclTabRead(xf_tab, NULL, RETURN_ON_FAIL)))
         mcxDie(1, me, "error reading tab file")

      ;  mclxCatInit(&cat)

      ;  if
         (  mclxCatRead
            (  xf_mx
            ,  &cat
            ,  0
            ,  NULL
            ,  tabr ? tabr->domain : NULL
            ,  MCLX_CATREAD_CLUSTERTREE | MCLX_ENSURE_ROOT
            )
         )
         mcxDie(1, me, "failure reading file")
      ;  thetree = mclxCatNewick(&cat, tabr, newick_bits)
      ;  fwrite(thetree->str, 1, thetree->len, xfout->fp)
      ;  fputc('\n', xfout->fp)
      ;  mcxIOclose(xfout)
      ;  return 0
   ;  }

      while (1)
      {  mclxIOdumper dumper
      ;  mclxCat    cat
      ;  dim i

      ;  if (xf_tab && !lazy_tab)
         cat_bits |= MCLX_REQUIRE_GRAPH

      ;  mclxCatInit(&cat)

      ;  if (mclxCatRead(xf_mx, &cat, catmax, NULL, NULL, cat_bits))
         break

      ;  for (i=0;i<cat.n_level;i++)
         {  mclx* mx = cat.level[i].mx

         ;  if (restrict_tabr || restrict_tabc)
            {  mclx* sub
            ;  sub
               =  mclxSub
                  (  mx
                  ,  restrict_tabc
                     ?  restrict_tabc->domain
                     :  mx->dom_cols
                  ,  restrict_tabr
                     ?  restrict_tabr->domain
                     :  mx->dom_rows
                  )
            ;  mx = sub
         ;  }
            /* noteme fixme dangersign mx now may violate some 'cat' invariant */

            if (sort_mode)
            {  if (!strcmp(sort_mode, "size-ascending"))
               mclxColumnsRealign(mx, mclvSizeCmp)
            ;  else if (!strcmp(sort_mode, "size-descending"))
               mclxColumnsRealign(mx, mclvSizeRevCmp)
            ;  else
               mcxErr(me, "unknown sort mode <%s>", sort_mode)
            ;  if (catmax != 1)
               mcxErr(me, "-sort option and cat mode may fail or corrupt")
         ;  }

            if (xf_tab && !tabr)
            {  if (!(  tabr = mclTabRead
                       (xf_tab, lazy_tab ? NULL : mx->dom_rows, RETURN_ON_FAIL)
                  ) )
               mcxDie(1, me, "consider using --lazy-tab option")
            ;  tabc = tabr
            ;  mcxIOclose(xf_tab)
         ;  }
            else
            {  if (!tabr && xf_tabr)
               {  if (!(tabr =  mclTabRead
                        (xf_tabr, lazy_tab ? NULL : mx->dom_rows, RETURN_ON_FAIL)
                     ) )
                  mcxDie(1, me, "consider using --lazy-tab option")
               ;  mcxIOclose(xf_tabr)
            ;  }
               if (!tabc && xf_tabc)
               {  if (!( tabc = mclTabRead
                        (xf_tabc, lazy_tab ? NULL : mx->dom_cols, RETURN_ON_FAIL)
                     ) )
                  mcxDie(1, me, "consider using --lazy-tab option")
               ;  mcxIOclose(xf_tabc)
            ;  }
            }

         ;  if (transpose)
            {  mclx* tp = mclxTranspose(mx)
            ;  mclxFree(&mx)
            ;  mx = tp
            ;  if (tabc || tabr)
               {  mclTab* tabt = tabc
               ;  tabc = tabr
               ;  tabr = tabt
            ;  }
            }

            if (mode_dump == MCLX_DUMP_TABLE)
            BIT_ON(modes, MCLX_DUMP_TABLE_HEADER)

         ;  mclxIOdumpSet(&dumper, modes, sep_lead_g, sep_row_g, sep_val_g)
         ;  dumper.table_nlines  = table_nlines
         ;  dumper.table_nfields = table_nfields
         ;  dumper.prefixc = prefixc_g

         ;  if (split_stem)
            {  mcxTing* ting = mcxTingPrint(NULL, "%s.%03d", split_stem, split_idx)
            ;  mcxIOclose(xfout)
            ;  mcxIOrenew(xfout, ting->str, "w")
            ;  split_idx += split_inc
         ;  }

            if
            (  mclxIOdump
               (  mx
               ,  xfout
               ,  &dumper
               ,  tabc
               ,  tabr
               ,  digits
               ,  RETURN_ON_FAIL
             ) )
            mcxDie(1, me, "something suboptimal")

         ;  mclxFree(&mx)

         ;  if (sep_cat_g && i+1 < cat.n_level)
            fprintf(xfout->fp, "%s\n", sep_cat_g)
      ;  }
         break
   ;  }

      mcxIOfree(&xf_mx)
   ;  mcxIOfree(&xfout)
   ;  mcxIOfree(&xf_tab)
   ;  mcxIOfree(&xf_tabr)
   ;  mcxIOfree(&xf_tabc)
   ;  mcxTingFree(&line)
   ;  return 0
;  }