Ejemplo n.º 1
0
void MADIMPENTRY( RegUpdateEnd )( mad_registers *mr, unsigned flags, unsigned bit_start, unsigned bit_size )
{
    unsigned    i;
    unsigned    bit_end;

    mr = mr; flags = flags;

    bit_end = bit_start + bit_size;
    #define IN_RANGE( i, bit )  \
      ((bit) >= RegList[i].info.bit_start && (bit) < (unsigned)( RegList[i].info.bit_start + RegList[i].info.bit_size ))
    for( i = 0; i < IDX_LAST_ONE; ++i ) {
        if( IN_RANGE( i, bit_start ) || IN_RANGE( i, bit_end ) ) {
            MCNotify( MNT_MODIFY_REG, (void *)&RegSet[RegList[i].reg_set] );
            break;
        }
    }
    switch( bit_start ) {
    case BIT_OFF( iar ):
        MCNotify( MNT_MODIFY_IP, NULL );
        break;
    case BIT_OFF( u1 ): // sp
        MCNotify( MNT_MODIFY_SP, NULL );
        break;
    case BIT_OFF( r31 ): // fp NYI: can float
        MCNotify( MNT_MODIFY_FP, NULL );
        break;
    }
}
Ejemplo n.º 2
0
void MADIMPENTRY( RegUpdateEnd )( mad_registers *mr, unsigned flags, unsigned bit_start, unsigned bit_size )
{
    unsigned    i;
    unsigned    bit_end;

    mr = mr;
    flags = flags;
    memset( &mr->axp.u31, 0, sizeof( mr->axp.u31 ) );
    memset( &mr->axp.f31, 0, sizeof( mr->axp.f31 ) );
    bit_end = bit_start + bit_size;
    #define IN_RANGE( i, bit )  \
      ((bit) >= RegList[i].info.bit_start && (bit) < (unsigned)( RegList[i].info.bit_start + RegList[i].info.bit_size ))
    for( i = 0; i < IDX_LAST_ONE; ++i ) {
        if( (IN_RANGE(i, bit_start) || IN_RANGE( i, bit_end ))
         && (RegList[i].pal == PAL_all || RegList[i].pal == mr->axp.active_pal) ) {
            MCNotify( MNT_MODIFY_REG, (void *)&RegSet[RegList[i].reg_set] );
            break;
        }
    }
    switch( bit_start ) {
    case BIT_OFF( pal.nt.fir ):
        MCNotify( MNT_MODIFY_IP, NULL );
        break;
    case BIT_OFF( u30 ): // sp
        MCNotify( MNT_MODIFY_SP, NULL );
        break;
    case BIT_OFF( u15 ): // fp
        MCNotify( MNT_MODIFY_FP, NULL );
        break;
    }
}
Ejemplo n.º 3
0
mad_status MADIMPENTRY( RegModified )( const mad_reg_set_data *rsd, const mad_reg_info *ri, const mad_registers *old, const mad_registers *cur )
{
    unsigned_64 new_ip;
    unsigned_8  *p_old;
    unsigned_8  *p_cur;
    unsigned    mask;
    unsigned    size;

    rsd = rsd;
    if( ri->bit_start == BIT_OFF( pal.nt.fir ) ) {
        new_ip = old->axp.pal.nt.fir;
        //NYI: 64 bit
        new_ip.u._32[0] += sizeof( unsigned_32 );
        if( new_ip.u._32[0] != cur->axp.pal.nt.fir.u._32[0] ) {
            return( MS_MODIFIED_SIGNIFICANTLY );
        } else if( old->axp.pal.nt.fir.u._32[0] != cur->axp.pal.nt.fir.u._32[0] ) {
            return( MS_MODIFIED );
        }
    } else {
        p_old = (unsigned_8 *)old + BYTEIDX( ri->bit_start );
        p_cur = (unsigned_8 *)cur + BYTEIDX( ri->bit_start );
        size = ri->bit_size;
        if( size >= BYTES2BITS( 1 ) ) {
            /* it's going to be byte aligned */
            return( memcmp( p_old, p_cur, BITS2BYTES( size ) ) != 0 ? MS_MODIFIED_SIGNIFICANTLY : MS_OK );
        } else {
            mask = (1 << size) - 1;
            #define GET_VAL( w ) (((*p_##w >> BITIDX( ri->bit_start ))) & mask)
            return( GET_VAL( old ) != GET_VAL( cur ) ? MS_MODIFIED_SIGNIFICANTLY : MS_OK );
        }
    }
    return( MS_OK );
}
Ejemplo n.º 4
0
void Character::move(Vec2 dir)
{
	if ((_state & BAN_MOVE))return;
	if (_state & IS_MOVING)return;
	//if (LOCK)return;
	//dir.y-=0.1f;
	if (dir.x < 0)dir = Vec2(-MOVE_SPEED_PER_F,0);
	else dir=Vec2(MOVE_SPEED_PER_F, 0);
	
	//if(dir.x>0?CH_RIGHT:CH_LEFT;
	
	auto call = [&]()  { BIT_OFF(_state,IS_MOVING); };
	//	auto callEnd = [&]()  {  //this->stateFlag&=~flag;};   
	auto action = MoveBy::create(MOVE_DURATION, dir);
	auto actionSeq = Sequence::create(
												action,
												CallFunc::create(call),
												NULL
											);
	BIT_ON(_state, IS_MOVING);
	actionSeq->setTag(MOVE_TAG);
	this->runAction(actionSeq);
	//this->runActionWithFlag(actionMove,flag);
	log("WH:ch moved to (%f,%f)" , this->getPositionX() , this->getPositionY());
}
Ejemplo n.º 5
0
mad_status DIGENTRY MIRegModified( const mad_reg_set_data *rsd, const mad_reg_info *ri, const mad_registers *old, const mad_registers *cur )
{
    unsigned_64 new_ip;
    unsigned_8  *p_old;
    unsigned_8  *p_cur;
    unsigned    mask;
    unsigned    size;

    if( ri->bit_start == BIT_OFF( iar ) ) {
        new_ip = old->ppc.iar;
        //NYI: 64 bit
        new_ip.u._32[I64LO32] += sizeof( unsigned_32 );
        if( new_ip.u._32[I64LO32] != cur->ppc.iar.u._32[I64LO32] ) {
            return( MS_MODIFIED_SIGNIFICANTLY );
        } else if( old->ppc.iar.u._32[I64LO32] != cur->ppc.iar.u._32[I64LO32] ) {
            return( MS_MODIFIED );
        }
    } else {
        p_old = (unsigned_8 *)old + (ri->bit_start / BITS_PER_BYTE);
        p_cur = (unsigned_8 *)cur + (ri->bit_start / BITS_PER_BYTE);
        size = ri->bit_size;
        if( size >= BITS_PER_BYTE ) {
            /* it's going to be byte aligned */
            return( memcmp( p_old, p_cur, size / BITS_PER_BYTE ) != 0 ? MS_MODIFIED_SIGNIFICANTLY : MS_OK );
        } else {
            mask = (1 << size) - 1;
            #define GET_VAL( w ) (((*p_##w >> (ri->bit_start % BITS_PER_BYTE))) & mask)
            return( GET_VAL( old ) != GET_VAL( cur ) ? MS_MODIFIED_SIGNIFICANTLY : MS_OK );
        }
    }
    return( MS_OK );
}
Ejemplo n.º 6
0
/*
        Query whether a register value differs between the two register
        sets 'old' and 'cur'. The following return codes are possible:

                MS_OK                           - value is unchanged
                MS_MODIFIED                     - value is different
                MS_MODIFIED_SIGNIFICANTLY       - value has changed
                                                  in a way that the user
                                                  cares about

*/
mad_status DIGENTRY MIRegModified( const mad_reg_set_data *rsd, const mad_reg_info *ri, const mad_registers *old, const mad_registers *cur )
{
    addr_ptr    new_ip;
    unsigned_8  *p_old;
    unsigned_8  *p_cur;
    unsigned    mask;
    unsigned    size;

    if( ri->bit_start == BIT_OFF( pc ) ) {
        new_ip = old->jvm.pc;
        //NYI: find length of instruction
        new_ip.offset += sizeof( unsigned_32 );
        if( new_ip.segment != cur->jvm.pc.segment ||
            new_ip.offset != cur->jvm.pc.offset ) {
            return( MS_MODIFIED_SIGNIFICANTLY );
        } else if( old->jvm.pc.segment != cur->jvm.pc.segment ||
                   old->jvm.pc.offset != cur->jvm.pc.offset ) {
            return( MS_MODIFIED );
        }
    } else {
        p_old = (unsigned_8 *)old + (ri->bit_start / BITS_PER_BYTE);
        p_cur = (unsigned_8 *)cur + (ri->bit_start / BITS_PER_BYTE);
        size = ri->bit_size;
        if( size >= BITS_PER_BYTE ) {
            /* it's going to be byte aligned */
            return( memcmp( p_old, p_cur, size / BITS_PER_BYTE ) != 0 ? MS_MODIFIED_SIGNIFICANTLY : MS_OK );
        } else {
            mask = (1 << size) - 1;
            #define GET_VAL( w ) (((*p_##w >> (ri->bit_start % BITS_PER_BYTE))) & mask)
            return( GET_VAL( old ) != GET_VAL( cur ) ? MS_MODIFIED_SIGNIFICANTLY : MS_OK );
        }
    }
    return( MS_OK );
}
Ejemplo n.º 7
0
void Character::resetTo(Vec2 pos)
{
	//this->stopActionByTag(DROP_TAG);
	//this->stopActionByTag(JUMPSEQ_TAG);
	//BIT_ON(_state, IS_MOVING);
	
	//this->setRotation(0);
	//auto size = this->getContentSize();
	//auto prePos = this->getPosition();
	this->setPosition(Vec2(pos.x,pos.y));
	this->stopAllActions();

	_jumpCnt = 0;
	BIT_OFF(_state,IS_JUMPING) ;
	BIT_OFF(_state, IS_DROPPING);
	BIT_OFF(_state, IS_MOVING);
	//_state = 0;
}
Ejemplo n.º 8
0
/*
        The client has just finished modifying a register (or registers).
        The MAD should take this chance to notify the client on what displays
        need to be updated. MCNotify should be called for the following

                MNT_MODIFY_REG  - to notify client which register set has
                                  changed (2d parm is register set pointer).
                MNT_MODIFY_IP   - instruction pointer special reg has changed.
                MNT_MODIFY_SP   - stack pointer special reg has changed.
                MNT_MODIFY_FP   - frame pointer special reg has changed.

*/
void            DIGENTRY MIRegUpdateEnd( mad_registers *mr, unsigned flags, unsigned bit_start, unsigned bit_size )
{
    unsigned    bit_end;

    bit_end = bit_start + bit_size;
    MCNotify( MNT_MODIFY_REG, (void *)&RegSet[CPU_REG_SET] );
    switch( bit_start ) {
    case BIT_OFF( pc ):
        MCNotify( MNT_MODIFY_IP, NULL );
        break;
    case BIT_OFF( optop ):
        MCNotify( MNT_MODIFY_SP, NULL );
        break;
    case BIT_OFF( frame ):
        MCNotify( MNT_MODIFY_FP, NULL );
        break;
    }
}
Ejemplo n.º 9
0
mad_status      DIGENTRY MIRegInspectAddr( const mad_reg_info *ri, mad_registers const *mr, address *a )
{
    unsigned    bit_start;
    unsigned_64 *p;

    memset( a, 0, sizeof( *a ) );
    bit_start = ri->bit_start;
    if( bit_start == BIT_OFF( iar ) ) {
        a->mach.offset = mr->ppc.iar.u._32[I64LO32];
        return( MS_OK );
    }
    if( bit_start >= BIT_OFF( f0 ) && bit_start < (BIT_OFF( f31 ) + 64) ) {
        return( MS_FAIL );
    }
    p = (unsigned_64 *)((unsigned_8 *)mr + (bit_start / BITS_PER_BYTE));
    a->mach.offset = p->u._32[I64LO32];
    return( MS_OK );
}
Ejemplo n.º 10
0
mad_status MADIMPENTRY( RegSetDisplayModify )( const mad_reg_set_data *rsd, const mad_reg_info *ri, const mad_modify_list **possible_p, int *num_possible_p )
{
    rsd = rsd;
    switch( ri->bit_start ) {
    case BIT_OFF( u31 ):
    case BIT_OFF( f31 ):
        *possible_p = NULL;
        *num_possible_p = 0;
        return( MS_FAIL );
    }
    *num_possible_p = 1;
    if( ri->type == AXPT_DOUBLE ) {
        *possible_p = &FltReg;
    } else {
        *possible_p = &IntReg;
    }
    return( MS_OK );
}
Ejemplo n.º 11
0
mad_status MADIMPENTRY( RegInspectAddr )( const mad_reg_info *ri, const mad_registers *mr, address *a )
{
    unsigned    bit_start;
    unsigned_32 *p;

    memset( a, 0, sizeof( *a ) );
    bit_start = ri->bit_start;
    if( bit_start == BIT_OFF( pal.nt.fir ) ) {
        a->mach.offset = mr->axp.pal.nt.fir.u._32[0];
        return( MS_OK );
    }
    if( IS_FP_BIT( bit_start ) ) {
        return( MS_FAIL );
    }
    if( bit_start >= BIT_OFF( pal ) ) {
        return( MS_FAIL );
    }
    p = (unsigned_32 *)((unsigned_8 *)mr + BYTEIDX( bit_start ));
    a->mach.offset = *p;
    return( MS_OK );
}
Ejemplo n.º 12
0
mcxstatus mclpARextend
(  mclpAR*  ar
,  long     idx
,  double   val
)
   {  mclp* ivp = NULL
   ;  if (ar->n_ivps >= ar->n_alloc)
      {  long n_new_alloc = 4 + 1.22 * ar->n_alloc
      ;  if
         (! (  ar->ivps
            =  mcxNRealloc
               (  ar->ivps
               ,  n_new_alloc
               ,  ar->n_alloc
               ,  sizeof(mclp)
               ,  mclpInit_v
               ,  RETURN_ON_FAIL
         )  )  )
         return STATUS_FAIL
      ;  ar->n_alloc = n_new_alloc
   ;  }

      ivp = ar->ivps + ar->n_ivps
   ;  ivp->val =  val
   ;  ivp->idx =  idx

   ;  if (ar->n_ivps && ivp[-1].idx >= idx)
      {  if (ivp[-1].idx > idx)
         BIT_OFF(ar->sorted, MCLPAR_SORTED | MCLPAR_UNIQUE)
      ;  else
         BIT_OFF(ar->sorted, MCLPAR_UNIQUE)
   ;  }

      ar->n_ivps++
   ;  return STATUS_OK
;  }
Ejemplo n.º 13
0
//=========================================================================
// blinkLED: routine that will blink an led when vxWorks is running
//=========================================================================
//  from winSH:  -> show_active starts the thread
//               -> td "show_active" kills the thread
//=========================================================================
static void blinkLED()
{ 
    static int count=0;
    int leds=GET_LEDS;
  
    while (1)
    {
        if(count)
            BIT_ON(leds,HOST_ACTIVE_LED);
        else
            BIT_OFF(leds,HOST_ACTIVE_LED);
        SET_LEDS(leds);
        count=count?0:1;
        taskDelay(calcSysClkTicks(83));  /* taskDelay(5); */
    }
}
Ejemplo n.º 14
0
mad_status MADIMPENTRY( RegInspectAddr )( const mad_reg_info *ri, mad_registers const *mr, address *a )
{
    unsigned    bit_start;
    unsigned_64 *p;

    memset( a, 0, sizeof( *a ) );
    bit_start = ri->bit_start;
    if( bit_start == BIT_OFF( iar ) ) {
        a->mach.offset = mr->ppc.iar.u._32[I64LO32];
        return( MS_OK );
    }
    if( IS_FP_BIT( bit_start ) ) {
        return( MS_FAIL );
    }
    p = (unsigned_64 *)((unsigned_8 *)mr + BYTEIDX( bit_start ));
    a->mach.offset = p->u._32[I64LO32];
    return( MS_OK );
}
Ejemplo n.º 15
0
void Character::drop()
{
	//if (_state & IS_DROPPING)return;
	//this->stopActionByTag(JUMP_TAG);
	//_jumpAction->retain();
	//auto pos = this->getParent()->convertToWorldSpace(this->getPosition());

	/*auto pos = this->getPosition();
	auto height = pos.y + DROP_HEIGHT_EX;
	auto downAction = MoveBy::create(height / DROP_SPEED_PER_H, Vec2(0, -height));
	//downAction->setTag(DROP_TAG);
	auto esiDown = EaseSineIn::create(downAction);
	esiDown->setTag(DROP_TAG);*/

	BIT_OFF(_state, IS_JUMPING);

	//BIT_ON(_state, IS_DROPPING);
	//this->runAction(esiDown);
	//this->runAction(downAction);

	//BIT_OFF(_state,IN_AIR);
	//_playerState = PS_JUMPBACK;
}
Ejemplo n.º 16
0
int main
(  int                  argc
,  const char*          argv[]
)  
   {  mcxIO
         *xfcl    =  NULL
      ,  *xfctrl  =  NULL
      ,  *xfcoarse=  NULL
      ,  *xfbase  =  NULL
      ,  *xfcone  =  NULL
      ,  *xfstack =  NULL

   ;  mclx* mxbase, *cl, *cl_coarse, *clprev, *clctrl = NULL

   ;  mcxTing* shared = mcxTingNew("-I 4 -overlap split")
   ;  mcxbool root = TRUE
   ;  mcxbool have_bootstrap = FALSE
   ;  const char* plexprefix = NULL
   ;  const char* stem = "mcl"
   ;  mcxbool same = FALSE
   ;  mcxbool plex = TRUE
   ;  mcxbool add_transpose = FALSE
   ;  const char* b2opts = NULL
   ;  const char* b1opts = NULL
   ;  mcxbits write_modes = 0

   ;  mclAlgParam* mlp        =  NULL
   ;  mcxstatus status        =  STATUS_OK
   ;  mcxstatus parse_status  =  STATUS_OK
   ;  int multiplex_idx = 1
   ;  int N = 0
   ;  int n_ite = 0
   ;  dim n_components = 0, n_cls = 0


   ;  int a =  1, i= 0
   ;  int n_arg_read = 0
   ;  int delta = 0
   ;  mcxOption* opts, *opt
   ;  mcxTing* cline = mcxOptArgLine(argv+1, argc-1, '\'')
   ;  mclgTF* transform  =  NULL
   ;  mcxTing* transform_spec = NULL


   ;  double iaf = 0.84

   ;  mclx_app_init(stderr)

   ;  if (0)
      mcxLogLevel =
      MCX_LOG_AGGR | MCX_LOG_MODULE | MCX_LOG_IO | MCX_LOG_GAUGE | MCX_LOG_WARN
   ;  else
      mcxLogLevelSetByString("xf4g1")

   ;  mcxOptAnchorSortById(options, sizeof(options)/sizeof(mcxOptAnchor) -1)

   ;  if (argc == 2 && argv[1][0] == '-' && mcxOptIsInfo(argv[1], options))
      delta = 1
   ;  else if (argc < 2)
      {  help(options, shared)
      ;  exit(0)
   ;  }

      opts = mcxOptExhaust
            (options, (char**) argv, argc, 2-delta, &n_arg_read, &parse_status)

   ;  if (parse_status != STATUS_OK)
      {  mcxErr(me, "initialization failed")
      ;  exit(1)
   ;  }

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

      ;  switch(anch->id)
         {  case MY_OPT_HELP
         :  help(options, shared)
         ;  exit(0)
         ;

            case MY_OPT_APROPOS
         :  help(options, shared)
         ;  exit(0)
         ;  break
         ;

            case MY_OPT_NMAX
         :  N = atoi(opt->val)
         ;  break
         ;

            case MY_OPT_Z
         :  help(NULL, shared)
         ;  exit(0)
         ;  break
         ;

            case MY_OPT_SHARED
         :  mcxTingPrintAfter(shared, " %s", opt->val)
         ;  break
         ;

            case MY_OPT_TRANSFORM
         :  transform_spec = mcxTingNew(opt->val)
         ;  break
         ;

            case MY_OPT_B1
         :  b1opts = opt->val
         ;  break
         ;

            case MY_OPT_B2
         :  b2opts = opt->val
         ;  break
         ;

            case ALG_OPT_SETENV
         :  mcxSetenv(opt->val)
         ;  break
         ;

            case ALG_OPT_QUIET
         :  mcxLogLevelSetByString(opt->val)
         ;  break
         ;

            case MY_OPT_HDP
         :  hdp_g = atof(opt->val)
         ;  break
         ;

            case MY_OPT_ADDTP
         :  add_transpose = TRUE
         ;  break
         ;

            case MY_OPT_ANNOT       /* only used in command-line copying */
         :  break
         ;

            case MY_OPT_IAF
         :  iaf = atof(opt->val) / 100
         ;  break
         ;

            case MY_OPT_WRITE
         :  if (strstr(opt->val, "stack"))
            write_modes |= OUTPUT_STACK
         ;  if (strstr(opt->val, "cone"))
            write_modes |= OUTPUT_CONE
         ;  if (strstr(opt->val, "levels"))
            write_modes |= OUTPUT_STEPS
         ;  if (strstr(opt->val, "coarse"))
            write_modes |= OUTPUT_COARSE
         ;  if (strstr(opt->val, "base"))
            write_modes |= OUTPUT_BASE
         ;  break
         ;

            case MY_OPT_BASENAME
         :  xfbase = mcxIOnew(opt->val, "w")
         ;  break
         ;

            case MY_OPT_COARSE
         :  xfcoarse = mcxIOnew(opt->val, "w")
         ;  break
         ;

            case MY_OPT_CONE
         :  xfcone = mcxIOnew(opt->val, "w")
         ;  break
         ;

            case MY_OPT_ROOT
         :  root = strchr("1yY", (u8) opt->val[0]) ? TRUE : FALSE
         ;  break
         ;

            case MY_OPT_STACK
         :  xfstack = mcxIOnew(opt->val, "w")
         ;  break
         ;

            case MY_OPT_STEM
         :  stem = opt->val
         ;  break
         ;

            case MY_OPT_MULTIPLEX
         :  plex = strchr("yY1", (unsigned char) opt->val[0]) ? TRUE : FALSE
         ;  break
         ;

            case MY_OPT_DISPATCH
         :  dispatch_g = TRUE
         ;  break
         ;

            case MY_OPT_INTEGRATE
         :  integrate_g = TRUE
         ;  break
         ;

            case MY_OPT_CONTRACT
         :  break
         ;

            case MY_OPT_SUBCLUSTERX
         :  subclusterx_g = TRUE,  subcluster_g = TRUE
         ;  break
         ;

            case MY_OPT_SUBCLUSTER
         :  subcluster_g = TRUE
         ;  break
         ;

            case MY_OPT_CONTROL
         :  xfctrl = mcxIOnew(opt->val, "r")
         ;  break
         ;

            case MY_OPT_CL
         :  xfcl = mcxIOnew(opt->val, "r")
         ;  have_bootstrap = TRUE
         ;  break
         ;

            case MY_OPT_VERSION
         :  app_report_version(me)
         ;  exit(0)
         ;

            default
         :  mcxExit(1)
         ;
         }
      }

      mcxOptFree(&opts)

   ;  a = 2 + n_arg_read

   ;  if (a < argc)
      {  if (strcmp(argv[a], "--"))
         mcxDie
         (  1
         ,  me
         ,  "trailing %s options require standalone '--' separator (found %s)"
         ,  integrate_g ? "integrate" : "mcl"
         ,  argv[a]
         )
      ;  a++
   ;  }

      if (subcluster_g + dispatch_g + integrate_g > 1)
      mcxDie(1, me, "too many modes!")

   ;  if (N && N < argc-a)
      mcxErr(me, "-n argument leaves spurious option specifications")

   ;  srandom(mcxSeed(89315))
   ;  signal(SIGALRM, mclSigCatch)

   ;  if (dispatch_g)
      plexprefix = "dis"
   ;  else if (!write_modes || (write_modes & OUTPUT_STEPS))
      plexprefix = stem

   ;  {  mcxTing* tg = mcxTingEmpty(NULL, 30)
      ;  if ((write_modes & OUTPUT_COARSE) && !xfcoarse)
            mcxTingPrint(tg, "%s.%s", stem, "coarse")
         ,  xfcoarse = mcxIOnew(tg->str, "w")

      ;  if ((write_modes & OUTPUT_BASE) && !xfbase)
            mcxTingPrint(tg, "%s.%s", stem, "base")
         ,  xfbase = mcxIOnew(tg->str, "w")

      ;  if
         (  (!write_modes || (write_modes & OUTPUT_CONE))
         && !xfcone
         )
         {  mcxTingPrint(tg, "%s.%s", stem, "cone")
         ;  xfcone = mcxIOnew(tg->str, "w")
         ;  mcxIOopen(xfcone, EXIT_ON_FAIL)
         ;  fprintf(xfcone->fp, "# %s %s\n", argv[0], cline->str)
      ;  }

         if ((write_modes & OUTPUT_STACK) && !xfstack)
         {  mcxTingPrint(tg, "%s.%s", stem, "stack")
         ;  xfstack = mcxIOnew(tg->str, "w")
         ;  mcxIOopen(xfstack, EXIT_ON_FAIL)
         ;  fprintf(xfstack->fp, "# %s %s\n", argv[0], cline->str)
      ;  }

         mcxTingFree(&tg)
   ;  }

      if (integrate_g)
      {  for (i=a;i<argc;i++)
         {  mcxIO* xf = mcxIOnew(argv[i], "r")
         ;  mclx* cl = mclxRead(xf, EXIT_ON_FAIL)
         ;  mclxCatPush(&stck_g, cl, NULL, NULL, mclxCBdomStack, NULL, "dummy-integrate", n_cls++)
      ;  }

         integrate_results(&stck_g)

      ;  if (xfstack)
         mclxCatWrite(xfstack, &stck_g, MCLXIO_VALUE_NONE, RETURN_ON_FAIL)

      ;  if (xfcone)
            mclxCatConify(&stck_g)
         ,  mclxCatWrite(xfcone, &stck_g, MCLXIO_VALUE_NONE, RETURN_ON_FAIL)

      ;  return 0
   ;  }

      for (i=a;i<argc;i++)
      {  if (get_interface(NULL, argv[1], shared->str, argv[i], NULL, 0, RETURN_ON_FAIL))
         mcxDie(1, me, "error while testing mcl options viability (%s)", argv[i])
   ;  }


      mcxLog(MCX_LOG_APP, me, "pid %ld", (long) getpid())

                        /* make sure clusters align with this cluster
                         * status: does not seem promising.
                        */
   ;  if (xfctrl)
      clctrl = mclxRead(xfctrl, EXIT_ON_FAIL)
   ;

                        /*
                         * Below: compute cl and mxbase.
                        */
   ;  if (xfcl)
      {  cl = mclxRead(xfcl, EXIT_ON_FAIL)
      ;  write_clustering
         (cl, NULL, xfcone, xfstack, plexprefix, multiplex_idx++, NULL)

      ;  if (subcluster_g || dispatch_g)
         mclxCatPush(&stck_g, cl, NULL, NULL, mclxCBdomStack, NULL, "dummy-mclcm", n_cls++)

      ;  mcxIOfree(&xfcl)
      ;  if (!b1opts && !b2opts)
         b1opts = ""
      ;  mxbase = get_base(argv[1], NULL, b1opts, b2opts)
   ;  }
      else
      {  mcxbits CACHE  =     b1opts || b2opts
                           ?  ALG_CACHE_INPUT       /* cache, transform later */
                           :  ALG_CACHE_START
      ;  get_interface
         (  &mlp
         ,  argv[1]
         ,  shared->str
         ,  a < argc ? argv[a] : NULL
         ,  NULL
         ,  CACHE
         ,  EXIT_ON_FAIL
         )
      ;  if (a < argc)
         a++

      ;  if ((status = mclAlgorithm(mlp)) == STATUS_FAIL)
         {  mcxErr(me, "failed at initial run")
         ;  exit(1)
      ;  }

         cl_coarse =  mclAlgParamRelease(mlp, mlp->cl_result)
      ;  cl_coarse =  control_test(cl_coarse, clctrl)

      ;  write_clustering
         (cl_coarse, NULL, xfcone, xfstack, plexprefix, multiplex_idx++, mlp)

      ;  if (subcluster_g || dispatch_g)
         mclxCatPush(&stck_g, cl_coarse, NULL, NULL, mclxCBdomStack, NULL, "dummy-mclcm", n_cls++)

      ;  cl = cl_coarse
      ;  n_ite++

      ;  if (b1opts || b2opts)
         {  mclx* mx_input =  mclAlgParamRelease(mlp, mlp->mx_input)
         ;  mxbase = get_base(NULL, mx_input, b1opts, b2opts)
                           /* ^ get_base frees mx_input */
      ;  }
         else
         mxbase =  mclAlgParamRelease(mlp, mlp->mx_start)
   ;  }

      clprev = cl

   ;  mclAlgParamFree(&mlp, TRUE)

   ;  if (xfbase)
      {  dim nre = mclxNrofEntries(mxbase)
      ;  mcxLog(MCX_LOG_APP, me, "base has %lu entries", (ulong) nre)
      ;  mclxaWrite(mxbase, xfbase, MCLXIO_VALUE_GETENV, EXIT_ON_FAIL)
      ;  mcxIOclose(xfbase)
   ;  }

      if (subcluster_g || dispatch_g)
      iaf = iaf ? 1/iaf : 1.414

   ;  while
      (  (!dispatch_g && (!N || n_ite < N))
      || (dispatch_g && a < argc)
      )
      {  mclx* mx_coarse   =  NULL, *clnext = NULL

      ;  dim dist_new_prev = 0, dist_prev_new = 0
      ;  mclx* clnew = NULL
      ;  mcxbool faith = FALSE
      ;  double inflation = -1.0

      ;  if (subcluster_g)
         mx_coarse
         =     subclusterx_g
            ?  mclxBlockPartition(mxbase, clprev, 50)
            :  mclxBlockUnion(mxbase, clprev)

                  /* have to copy mxbase as mx_coarse is freed.
                   * Even if it were not freed, it is probably transformed.
                  */
      ;  else if (dispatch_g)
         mx_coarse = mclxCopy(mxbase)

      ;  else
         {  mx_coarse = get_coarse(mxbase, clprev, add_transpose)

         ;  if (n_ite == 1)
            {  mclx* cc = clmUGraphComponents(mx_coarse, NULL)   /* fixme; mx_coarse garantueed UD ? */
            ;  n_components = N_COLS(cc)
            ;  mclxFree(&cc)
         ;  }
         }

         if (xfcoarse)
         write_coarse(xfcoarse, mx_coarse)

      ;  get_interface
         (  &mlp
         ,  NULL
         ,  shared->str
         ,  a < argc ? argv[a] : NULL
         ,  mx_coarse
         ,  ALG_CACHE_START
         ,  EXIT_ON_FAIL
         )

      ;  inflation = mlp->mpp->mainInflation
      ;  BIT_OFF(mlp->modes, ALG_DO_SHOW_PID | ALG_DO_SHOW_JURY)

      ;  if ((status = mclAlgorithm(mlp)) == STATUS_FAIL)
         {  mcxErr(me, "failed")
         ;  mcxExit(1)
      ;  }

         cl_coarse = mclAlgParamRelease(mlp, mlp->cl_result)

      ;  if (xfcoarse)
         mclxaWrite(cl_coarse, xfcoarse, MCLXIO_VALUE_NONE, RETURN_ON_FAIL)

      ;  if (dispatch_g || subcluster_g)
         clnext = cl_coarse
      ;  else
            clnext = mclxCompose(clprev, cl_coarse, 0)
         ,  clnext = control_test(clnext, clctrl)
         ,  mclxFree(&cl_coarse)

      ;  clmSJDistance
         (clprev, clnext, NULL, NULL, &dist_prev_new, &dist_new_prev)

      ;  if (dist_prev_new + dist_new_prev)
         {  write_clustering
            (clnext, clprev, xfcone, xfstack, plexprefix, multiplex_idx++, mlp)
         ;  clnew = clnext

         ;  if (subcluster_g || dispatch_g)
            mclxCatPush(&stck_g, clnext, NULL, NULL, mclxCBdomStack, NULL, "dummy-mclcm", n_cls++)
         ;  else
            mclxFree(&clprev)

         ;  clprev = clnew
      ;  }
         else if
         (  N_COLS(clnext) > n_components
         && inflation * iaf > 1.2
         && inflation * iaf < 10
         )
         {  mclxFree(&clnext)
         ;  inflation *= iaf
         ;  mcxTingPrintAfter(shared, " -I %.2f", inflation)
         ;  mcxLog(MCX_LOG_APP, me, "setting inflation to %.2f", inflation)
         ;  faith = TRUE
      ;  }
                                       /* i.e. vanilla mode, contraction */
         else if (!subcluster_g && !dispatch_g)
         {  mclx* cc
         ;  mclxFree(&clnext)

         ;  mclxAddTranspose(mx_coarse, 1.0)
         ;  cc = clmUGraphComponents(mx_coarse, NULL)  

         ;  if (N_COLS(cc) < N_COLS(clprev))
            {  mclx* ccback = mclxCompose(clprev, cc, 0)
            ;  write_clustering
               (ccback, clprev, xfcone, xfstack, plexprefix, multiplex_idx++, NULL)
            ;  mclxFree(&clprev)
            ;  clprev = ccback
            ;  mcxTell(me, "connected components added as root clustering")
         ;  }

            if (root && N_COLS(cc) > 1)
            {  mclx* root =   mclxCartesian
                              (  mclvCanonical(NULL, 1, 0)
                              ,  mclvCopy(NULL, mxbase->dom_cols)
                              ,  1.0
                              )
            ;  write_clustering
               (root, clprev, xfcone, xfstack, plexprefix, multiplex_idx++, NULL)

            ;  mclxFree(&clprev)

            ;  mcxTell(me, "universe added as root clustering")
            ;  clprev = root
            ;  clnew = NULL
         ;  }

            mclxFree(&cc)
      ;  }
         else if (subcluster_g || dispatch_g)
         mclxFree(&clnext)

      ;  mclAlgParamFree(&mlp, TRUE)                        /* frees mx_coarse */

      ;  if (!clnew && !faith)
         {  same = TRUE
         ;  break
      ;  }

         a++

      ;  if (dispatch_g && a == argc)
         break

      ;  n_ite++
   ;  }

      if (same)
      mcxLog(MCX_LOG_MODULE, me, "no further contraction: halting")

   ;  if (dispatch_g)
      integrate_results(&stck_g)
   ;  else if (subcluster_g)
      mclxCatReverse(&stck_g)

   ;  if (dispatch_g || subcluster_g)
      {  dim j
      ;  if (xfstack)
         mclxCatWrite(xfstack, &stck_g, MCLXIO_VALUE_NONE, RETURN_ON_FAIL)
      ;  if (xfcone && ! mclxCatConify(&stck_g))
         mclxCatWrite(xfcone, &stck_g, MCLXIO_VALUE_NONE, RETURN_ON_FAIL)
      ;  for (j=0;j<stck_g.n_level;j++)
         {  mclxAnnot* an = stck_g.level+j
         ;  mclxFree(&an->mx)
      ;  }
         mcxFree(stck_g.level)
   ;  }

      mcxIOfree(&xfcoarse)
   ;  mcxIOfree(&xfbase)
   ;  mcxIOfree(&xfcone)
   ;  mcxIOfree(&xfstack)

   ;  mcxTingFree(&shared)

   ;  if (!dispatch_g && !subcluster_g)          /* fixme fixme fixme */
      mclxFree(&clprev)

   ;  mclxFree(&mxbase)
   ;  mclvFree(&start_col_sums_g)
   ;  mcxTingFree(&cline)
   ;  helpful_reminder()
   ;  return STATUS_OK
;  }
Ejemplo n.º 17
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
;  }