示例#1
0
文件: lisp235.c 项目: hoelzl/Clicc
void Farray_in_bounds_p(CL_FORM *base, int nargs)
{
	CL_FORM *rest_0;
	CL_FORM *local;
	rest_0 = ARG(1);
	local = ARG(nargs);
	COPY(ARG(0), LOCAL(0));
	Farray_rank(LOCAL(0));
	REST_LENGTH(rest_0, LOCAL(1));
	Fnumeql(LOCAL(0), 2);
	if(CL_TRUEP(LOCAL(0)))
	{
	}
	else
	{
		LOAD_SMSTR((CL_FORM *)&KClisp[188], LOCAL(0));	/* Wrong number of subscripts for array ~a */
		COPY(ARG(0), LOCAL(1));
		Ferror(LOCAL(0), 2);
	}
	{
		LOAD_FIXNUM(LOCAL(0), 0, LOCAL(0));
		{
			CL_FORM *rest_1;
			LOAD_NIL(LOCAL(1));
			rest_1 = rest_0;
			M1_1:;
			if(NOT(REST_NOT_EMPTY(rest_1)))
			{
				LOAD_NIL(LOCAL(1));
				LOAD_SYMBOL(SYMBOL(Slisp, 48), ARG(0));	/* T */
				goto RETURN1;
			}
			{
				CL_FORM *rest_2;
				rest_2 = rest_1;
				REST_CAR(rest_2, LOCAL(1));
			}
			if(CL_FIXNUMP(LOCAL(1)))
			{
				LOAD_FIXNUM(LOCAL(2), 0, LOCAL(2));
				COPY(LOCAL(1), LOCAL(3));
				COPY(ARG(0), LOCAL(4));
				COPY(LOCAL(0), LOCAL(5));
				Farray_dimension(LOCAL(4));
				F1minus(LOCAL(4));
				Fle(LOCAL(2), 3);
			}
			else
			{
				goto ELSE1;
			}
			if(CL_TRUEP(LOCAL(2)))
			{
			}
			else
			{
				ELSE1:;
				LOAD_NIL(ARG(0));
				goto RETURN1;
			}
			F1plus(LOCAL(0));
			{
				CL_FORM *rest_3;
				rest_3 = rest_1;
				rest_1 = REST_CDR(rest_3);
			}
			goto M1_1;
		}
		RETURN1:;
	}
}
示例#2
0
//
//  Make_Where_For_Frame: C
//
// Each call frame maintains the array it is executing in, the current index
// in that array, and the index of where the current expression started.
// This can be deduced into a segment of code to display in the debug views
// to indicate roughly "what's running" at that stack level.
//
// Unfortunately, Rebol doesn't formalize this very well.  There is no lock
// on segments of blocks during their evaluation, and it's possible for
// self-modifying code to scramble the blocks being executed.  The DO
// evaluator is robust in terms of not *crashing*, but the semantics may well
// suprise users.
//
// !!! Should blocks on the stack be locked from modification, at least by
// default unless a special setting for self-modifying code unlocks it?
//
// So long as WHERE information is unreliable, this has to check that
// `expr_index` (where the evaluation started) and `index` (where the
// evaluation thinks it currently is) aren't out of bounds here.  We could
// be giving back positions now unrelated to the call...but it won't crash!
//
REBARR *Make_Where_For_Frame(struct Reb_Frame *frame)
{
    REBCNT start;
    REBCNT end;

    REBARR *where;
    REBOOL pending;

    if (FRM_IS_VALIST(frame)) {
        const REBOOL truncated = TRUE;
        Reify_Va_To_Array_In_Frame(frame, truncated);
    }

    // WARNING: MIN is a C macro and repeats its arguments.
    //
    start = MIN(ARR_LEN(FRM_ARRAY(frame)), cast(REBCNT, frame->expr_index));
    end = MIN(ARR_LEN(FRM_ARRAY(frame)), FRM_INDEX(frame));

    assert(end >= start);
    assert(frame->mode != CALL_MODE_GUARD_ARRAY_ONLY);
    pending = NOT(frame->mode == CALL_MODE_FUNCTION);

    // Do a shallow copy so that the WHERE information only includes
    // the range of the array being executed up to the point of
    // currently relevant evaluation, not all the way to the tail
    // of the block (where future potential evaluation would be)
    {
        REBCNT n = 0;

        REBCNT len =
            1 // fake function word (compensates for prefetch)
            + (end - start) // data from expr_index to the current index
            + (pending ? 1 : 0); // if it's pending we put "..." to show that

        where = Make_Array(len);

        // !!! Due to "prefetch" the expr_index will be *past* the invocation
        // of the function.  So this is a lie, as a placeholder for what a
        // real debug mode would need to actually save the data to show.
        // If the execution were a path or anything other than a word, this
        // will lose it.
        //
        Val_Init_Word(ARR_AT(where, n), REB_WORD, FRM_LABEL(frame));
        ++n;

        for (n = 1; n < len; ++n)
            *ARR_AT(where, n) = *ARR_AT(FRM_ARRAY(frame), start + n - 1);

        SET_ARRAY_LEN(where, len);
        TERM_ARRAY(where);
    }

    // Making a shallow copy offers another advantage, that it's
    // possible to get rid of the newline marker on the first element,
    // that would visually disrupt the backtrace for no reason.
    //
    if (end - start > 0)
        CLEAR_VAL_FLAG(ARR_HEAD(where), VALUE_FLAG_LINE);

    // We add an ellipsis to a pending frame to make it a little bit
    // clearer what is going on.  If someone sees a where that looks
    // like just `* [print]` the asterisk alone doesn't quite send
    // home the message that print is not running and it is
    // argument fulfillment that is why it's not "on the stack"
    // yet, so `* [print ...]` is an attempt to say that better.
    //
    // !!! This is in-band, which can be mixed up with literal usage
    // of ellipsis.  Could there be a better "out-of-band" conveyance?
    // Might the system use colorization in a value option bit.
    //
    if (pending)
        Val_Init_Word(Alloc_Tail_Array(where), REB_WORD, SYM_ELLIPSIS);

    return where;
}
示例#3
0
文件: lisp344.c 项目: hoelzl/Clicc
void Fmake_pathname(CL_FORM *base, int nargs)
{
	BOOL supl_flags[8];
	static CL_FORM * keylist[] =
	{
		SYMBOL(Slisp, 251),	/* HOST */
		SYMBOL(Slisp, 252),	/* DEVICE */
		SYMBOL(Slisp, 253),	/* DIRECTORY */
		SYMBOL(Slisp, 254),	/* NAME */
		SYMBOL(Slisp, 80),	/* TYPE */
		SYMBOL(Slisp, 255),	/* VERSION */
		SYMBOL(Slisp, 275),	/* DEFAULTS */
		SYMBOL(Slisp, 277),	/* CASE */
	};
	keysort(ARG(0), nargs - 0, 8, keylist, supl_flags, FALSE);
	if(NOT(supl_flags[0]))
	{
		LOAD_NIL(ARG(0));
		LOAD_NIL(ARG(8));
	}
	else
	{
		LOAD_T(ARG(8));
	}
	if(NOT(supl_flags[1]))
	{
		LOAD_NIL(ARG(1));
		LOAD_NIL(ARG(9));
	}
	else
	{
		LOAD_T(ARG(9));
	}
	if(NOT(supl_flags[2]))
	{
		LOAD_NIL(ARG(2));
		LOAD_NIL(ARG(10));
	}
	else
	{
		LOAD_T(ARG(10));
	}
	if(NOT(supl_flags[3]))
	{
		LOAD_NIL(ARG(3));
		LOAD_NIL(ARG(11));
	}
	else
	{
		LOAD_T(ARG(11));
	}
	if(NOT(supl_flags[4]))
	{
		LOAD_NIL(ARG(4));
		LOAD_NIL(ARG(12));
	}
	else
	{
		LOAD_T(ARG(12));
	}
	if(NOT(supl_flags[5]))
	{
		LOAD_NIL(ARG(5));
		LOAD_NIL(ARG(13));
	}
	else
	{
		LOAD_T(ARG(13));
	}
	if(NOT(supl_flags[6]))
	{
		LOAD_NIL(ARG(6));
	}
	if(NOT(supl_flags[7]))
	{
		LOAD_SYMBOL(SYMBOL(Slisp, 276), ARG(7));	/* LOCAL */
	}
	make_pathname1(ARG(0));
}
short AQRInfo::setAQREntriesFromInputStr(char * inStr, Lng32 inStrLen)
{
  if ((! inStr) || (inStrLen <= 0))
    return -1;

  char * newStr = new(heap_) char[inStrLen + 1 + 1];
  str_cpy_all(newStr, inStr, inStrLen);
  newStr[inStrLen] = 0;
  Lng32 n = 0;

  Int32 i = 0;
  while (i < inStrLen)
    {
      if ((inStr[i] != '+') &&
	  (inStr[i] != '-') &&
	  (inStr[i] != '.') &&
	  (inStr[i] != ' ') &&
	  (inStr[i] != ',') &&
	  (inStr[i] != '|') &&
	  (NOT ((inStr[i] >= '0') &&
		(inStr[i] <= '9'))))
	return -1;

      if (inStr[i] != ' ')
	{
	  newStr[n] = inStr[i];
	  n++;
	}

      i++;
    }

  if (newStr[n-1] != '|')
    {
      newStr[n] = '|';
      n++;
    }
  newStr[n] = 0;

  i = 0;
  Int32 j = 0;
  Int32 k = 1;
  Lng32 sqlcode = -1;
  Lng32 nskcode = 0;
  Lng32 retries = 1;
  Lng32 delay = 60;
  Lng32 type = 0;
  Lng32 numCQDs = 0;
  char * cqdStr = NULL;
  Lng32 cmpInfo = 0;
  Lng32 intAQR = 0;
  Lng32 task = ComTdbExeUtilAQR::NONE_;
  NABoolean numberSeen = FALSE;
  while (i < n)
    {
      if ((newStr[i] >= '0') &&
	  (newStr[i] <= '9'))
	numberSeen = TRUE;

      if (newStr[i] == '+')
	{
	  if ((numberSeen) ||
	      (task != ComTdbExeUtilAQR::NONE_))
	    return -1;

	  task = ComTdbExeUtilAQR::ADD_;
	  j++;
	}
      else if (newStr[i] == '-')
	{
	  if ((numberSeen) ||
	      (task != ComTdbExeUtilAQR::NONE_))
	    return -1;

	  task = ComTdbExeUtilAQR::DELETE_;
	  j++;
	}
      else if (newStr[i] == '.')
	{
	  if ((numberSeen) ||
	      (task != ComTdbExeUtilAQR::NONE_))
	    return -1;

	  task = ComTdbExeUtilAQR::UPDATE_;
	  j++;
	}

      if ((newStr[i] == ',') ||
	  (newStr[i] == '|'))
	{
	  if (i > j)
	    {
	      Lng32 v = 0;
	      if ((k < 7) || (k == 8) || (k == 9))
		{
		  Int64 bigV = str_atoi(&newStr[j], i-j);
		  if (bigV == -1)
		    return -1;
		  
		  if (bigV > INT_MAX)
		    return -1;

		  v = (Lng32)bigV;
		}

	      switch (k)
		{
		case 1:
		  sqlcode = v;
		  break;
		  
		case 2:
		  nskcode = v;
		  break;
		  
		case 3:
		  retries = v;
		  break;
		  
		case 4:
		  delay = v;
		  break;
		  
		case 5:
		  type = v;
		  break;

		case 6:
		  numCQDs = v;
		  break;

		case 7:
		  cqdStr = new(heap_) char[i-j+1];
		  str_cpy_all(cqdStr, &newStr[j], i-j);
		  cqdStr[i-j] = 0;
		  break;
		  
		case 8:
		  cmpInfo = v;
		  break;

		case 9:
		  intAQR = v;
		  break;

		} // switch
	    }

	  k++;

	  j = i + 1;
	}

      if (newStr[i] == '|')
	{
	  if (task == ComTdbExeUtilAQR::NONE_)
	    task = ComTdbExeUtilAQR::ADD_;

	  if (setAQREntry(task, sqlcode, nskcode, retries, delay, type,
			  numCQDs, cqdStr, cmpInfo, intAQR))
	    return -1;

	  sqlcode = -1;
	  nskcode = 0;
	  retries = 1;
	  delay = 60;
	  type = 0;
	  numCQDs = 0;
	  cqdStr = NULL;
	  cmpInfo = 0;
	  intAQR = 0;

	  numberSeen = FALSE;
	  task = ComTdbExeUtilAQR::NONE_;

	  k = 1;
	  j = i+1;
	}
	
      i++;
    }

  return 0;
}
示例#5
0
文件: FcharG.c 项目: hoelzl/Clicc
void FcharG(CL_FORM *base, int nargs)
{
	CL_FORM *rest_0;
	CL_FORM *local;
	rest_0 = ARG(1);
	local = ARG(nargs);
	{
		CL_FORM *rest_1;
		LOAD_NIL(LOCAL(0));
		rest_1 = rest_0;
		M1_1:;
		if(NOT(REST_NOT_EMPTY(rest_1)))
		{
			LOAD_NIL(LOCAL(0));
			LOAD_SYMBOL(SYMBOL(Slisp, 48), ARG(0));	/* T */
			goto RETURN1;
		}
		{
			CL_FORM *rest_2;
			rest_2 = rest_1;
			REST_CAR(rest_2, LOCAL(0));
		}
		if(CL_CHARP(ARG(0)))
		{
		}
		else
		{
			COPY(SYMVAL(Slisp, 58), LOCAL(1));	/* WRONG_TYPE */
			COPY(ARG(0), LOCAL(2));
			LOAD_SYMBOL(SYMBOL(Slisp, 18), LOCAL(3));	/* CHARACTER */
			Ferror(LOCAL(1), 3);
		}
		COPY(ARG(0), LOCAL(1));
		rt_char_code(LOCAL(1));
		if(CL_CHARP(LOCAL(0)))
		{
		}
		else
		{
			COPY(SYMVAL(Slisp, 58), LOCAL(2));	/* WRONG_TYPE */
			COPY(LOCAL(0), LOCAL(3));
			LOAD_SYMBOL(SYMBOL(Slisp, 18), LOCAL(4));	/* CHARACTER */
			Ferror(LOCAL(2), 3);
		}
		COPY(LOCAL(0), LOCAL(2));
		rt_char_code(LOCAL(2));
		Fle(LOCAL(1), 2);
		if(CL_TRUEP(LOCAL(1)))
		{
			LOAD_NIL(ARG(0));
			goto RETURN1;
		}
		COPY(LOCAL(0), ARG(0));
		{
			CL_FORM *rest_3;
			rest_3 = rest_1;
			rest_1 = REST_CDR(rest_3);
		}
		goto M1_1;
	}
	RETURN1:;
}
示例#6
0
static void do_vread_s(const message * mp, int from_int)
{
  u8_t *buffer;
  u32_t size;
  int r, ix = 0;
  vir_bytes bytes;
  dpeth_t *dep = NULL;
  de_loc_descr_t *descr = NULL;
  iovec_dat_s_t *iovp = NULL;

  dep = &de_state;

  dep->de_client = mp->m_source;

  if (dep->de_mode == DEM_ENABLED) {    

    descr = &dep->descr[DESCR_RECV][dep->cur_descr[DESCR_RECV]];  

    /* check if packet is in the current descr and only there */
    if(  !( !(descr->descr->des[DES0] & DES0_OWN) &&  
	    (descr->descr->des[DES0] & DES0_FS)   &&
	    (descr->descr->des[DES0] & DES0_LS)     ))
      goto suspend;


    /*TODO: multi-descr msgs...*/
    /* We only support packets contained in a single descriptor.
       Setting the descriptor buffer size to less then
       ETH_MAX_PACK_SIZE will result in multi-descriptor
       packets that we won't be able to handle 
    */
    assert(!(descr->descr->des[DES0]&DES0_OWN));
    assert(descr->descr->des[DES0]&DES0_FS);
    assert(descr->descr->des[DES0]&DES0_LS);

    /* Check for abnormal messages. We assert here
       because this driver is for a virtualized 
       envrionment where we will not get bad packets
    */
    assert(!(descr->descr->des[DES0]&DES0_ES));
    assert(!(descr->descr->des[DES0]&DES0_RE));


    /* Setup the iovec entry to allow copying into
       client layer
    */
    dep->de_read_iovec.iod_proc_nr = mp->m_source;
    de_get_userdata_s(mp->m_source, (cp_grant_id_t) mp->DL_GRANT, 0,
		      mp->DL_COUNT, dep->de_read_iovec.iod_iovec);
    dep->de_read_iovec.iod_iovec_s = mp->DL_COUNT;
    dep->de_read_iovec.iod_grant = (cp_grant_id_t) mp->DL_GRANT;
    dep->de_read_iovec.iod_iovec_offset = 0;
    size = de_calc_iov_size(&dep->de_read_iovec);
    if (size < ETH_MAX_PACK_SIZE) 
      panic("%s %d", str_SizeErrMsg, size);

    /* Copy buffer to user area  and clear ownage */
    size = (descr->descr->des[DES0]&DES0_FL)>>DES0_FL_SHIFT;

    /*TODO: Complain to MS */
    /*HACK: VPC2007 returns packet of invalid size. Ethernet standard
      specify 46 bytes as the minimum for valid payload. However, this is 
      artificial in so far as for certain packet types, notably ARP, less
      then 46 bytes are needed to contain the full information. In a non 
      virtualized environment the 46 bytes rule is enforced in order to give
      guarantee in the collison detection scheme. Of course, this being a 
      driver for a VPC2007, we won't have collisions and I can only suppose
      MS decided to cut packet size to true minimum, regardless of the 
      46 bytes payload standard. Note that this seems to not happen in 
      bridged mode. Note also, that the card does not return runt or 
      incomplete frames to us, so this hack is safe
    */    
    if(size<60){
      bzero(&descr->buf1[size], 60-size);
      size=60;
    }
    /* End ugly hack */

    iovp = &dep->de_read_iovec;
    buffer = descr->buf1;
    dep->bytes_rx += size;
    dep->de_stat.ets_packetR++;
    dep->de_read_s = size;

    do {   
      bytes = iovp->iod_iovec[ix].iov_size;	/* Size of buffer */
      if (bytes >= size) 
	bytes = size;

      r= sys_safecopyto(iovp->iod_proc_nr, iovp->iod_iovec[ix].iov_grant, 0,
			(vir_bytes)buffer, bytes);
      if (r != OK)
	panic("%s %d", str_CopyErrMsg, r);
      buffer += bytes;
      
      if (++ix >= IOVEC_NR) {	/* Next buffer of IO vector */
	de_next_iov(iovp);
	ix = 0;
      }
    } while ((size -= bytes) > 0);

    descr->descr->des[DES0]=DES0_OWN;
    dep->cur_descr[DESCR_RECV]++;
    if(dep->cur_descr[DESCR_RECV] >= DE_NB_RECV_DESCR)
      dep->cur_descr[DESCR_RECV] = 0;	  

    DEBUG(printf("Read returned size = %d\n", size));

    /* Reply information */
    dep->de_flags |= DEF_ACK_RECV;
    dep->de_flags &= NOT(DEF_READING);
  }
示例#7
0
文件: null.c 项目: Ascronia/fieldtrip
void null_test2 (void)
{
    cholmod_dense *X, *Xbad = NULL ;
    cholmod_sparse *Sbad = NULL, *A ;
    int ok ;

    /* ---------------------------------------------------------------------- */
    /* Test Core Common */
    /* ---------------------------------------------------------------------- */

    ok = CHOLMOD(allocate_work)(Size_max, 1, 1, cm) ;		NOT (ok) ;
    ok = CHOLMOD(allocate_work)(1, Size_max, 1, cm) ;		NOT (ok) ;
    ok = CHOLMOD(allocate_work)(1, 1, Size_max, cm) ;		NOT (ok) ;

    /* free a NULL pointer */
    CHOLMOD(free)(42, sizeof (char), NULL, cm) ;
    cm->print = 5 ; CHOLMOD(print_common)("cm", cm) ; cm->print = 3 ;

    cm->maxrank = 3 ;
    cm->maxrank = CHOLMOD(maxrank)(5, cm) ; OK (cm->maxrank == 4) ;
    cm->maxrank = 1 ;
    cm->maxrank = CHOLMOD(maxrank)(5, cm) ; OK (cm->maxrank == 2) ;
    cm->maxrank = 8 ;

    /* test the error handler */
    cm->error_handler = my_handler2 ;
    CHOLMOD(drop)(0., NULL, cm) ;
    cm->error_handler = NULL ;

    /* ---------------------------------------------------------------------- */
    /* dense */
    /* ---------------------------------------------------------------------- */

    X = CHOLMOD(allocate_dense)(5, 4, 1, CHOLMOD_REAL, cm) ;	    NOP (X) ;
    X = CHOLMOD(allocate_dense)(1, Int_max, 1, CHOLMOD_REAL, cm) ;  NOP (X) ;
    X = CHOLMOD(allocate_dense)(1, 1, 1, -1, cm) ;		    NOP (X) ;
    CHOLMOD(free_dense)(&X, cm) ;

    /* free a NULL dense matrix */
    ok = CHOLMOD(free_dense)(&X, cm) ;				    OK (ok) ;
    ok = CHOLMOD(free_dense)(NULL, cm) ;			    OK (ok) ;

    /* make an invalid sparse matrix */
    Sbad = CHOLMOD(speye)(2, 3, CHOLMOD_REAL, cm) ;		    OKP (Sbad) ;
    Sbad->stype = 1 ;
    ok = CHOLMOD(check_sparse)(Sbad, cm) ;			    NOT (ok) ;
    X = CHOLMOD(sparse_to_dense)(Sbad, cm) ;			    NOP (X) ;
    ok = CHOLMOD(free_sparse)(&Sbad, cm) ;			    OK (ok) ;

    /* make an invalid dense matrix */
    Xbad = CHOLMOD(eye)(4, 4, CHOLMOD_REAL, cm) ;		    OKP (Xbad) ;
    Xbad->d = 1 ;
    ok = CHOLMOD(check_dense)(Xbad, cm) ;			    NOT (ok) ;
    A = CHOLMOD(dense_to_sparse)(Xbad, TRUE, cm) ;
    ok = CHOLMOD(free_dense)(&Xbad, cm) ;			    OK (ok) ;
    CHOLMOD(print_common)("cm", cm) ;
    cm->print = 5 ; CHOLMOD(print_sparse)(A, "Bad A", cm) ; cm->print = 3 ;
    NOP (A) ;

    /* ---------------------------------------------------------------------- */
    /* sparse */
    /* ---------------------------------------------------------------------- */

    /* free a NULL sparse matrix */
    ok = CHOLMOD(free_sparse)(&A, cm) ;				    OK (ok) ;
    ok = CHOLMOD(free_sparse)(NULL, cm) ;			    OK (ok) ;
    A = CHOLMOD(copy_sparse)(NULL, cm) ;			    NOP (A) ;

    /* ---------------------------------------------------------------------- */
    /* error tests done */
    /* ---------------------------------------------------------------------- */

    printf ("------------------ null tests done\n") ;
}
示例#8
0
int
rtpp_command_ul_handle(struct cfg *cf, struct rtpp_command *cmd,
  struct common_cmd_args *ccap, struct ul_opts *ulop,
  struct rtpp_session *sp, int sidx)
{
    int pidx, lport, i;
    int fds[2];
    char *cp;
    struct rtpp_session *spa, *spb;

    pidx = 1;
    lport = 0;
    spa = spb = NULL;
    fds[0] = fds[1] = -1;
    if (sidx != -1) {
        assert(ccap->op == UPDATE || ccap->op == LOOKUP);
        spa = sp;
        if (spa->fds[sidx] == -1) {
            if (ulop->local_addr != NULL) {
                spa->laddr[sidx] = ulop->local_addr;
            }
            if (rtpp_create_listener(cf, spa->laddr[sidx], &lport, fds) == -1) {
                rtpp_log_write(RTPP_LOG_ERR, spa->log, "can't create listener");
                reply_error(cf, cmd, ECODE_LSTFAIL_1);
                goto err_undo_0;
            }
            assert(spa->fds[sidx] == -1);
            spa->fds[sidx] = fds[0];
            assert(spa->rtcp->fds[sidx] == -1);
            spa->rtcp->fds[sidx] = fds[1];
            spa->ports[sidx] = lport;
            spa->rtcp->ports[sidx] = lport + 1;
            if (spa->complete == 0) {
                cmd->csp->nsess_complete.cnt++;
            }
            spa->complete = spa->rtcp->complete = 1;
            append_session(cf, spa, sidx);
        }
        if (ulop->weak)
            spa->weak[sidx] = 1;
        else if (ccap->op == UPDATE)
            spa->strong = 1;
        lport = spa->ports[sidx];
        ulop->lia[0] = spa->laddr[sidx];
        pidx = (sidx == 0) ? 1 : 0;
        spa->ttl_mode = cf->stable->ttl_mode;
        spa->ttl[0] = cf->stable->max_ttl;
        spa->ttl[1] = cf->stable->max_ttl;
        if (ccap->op == UPDATE) {
            rtpp_log_write(RTPP_LOG_INFO, spa->log,
              "adding %s flag to existing session, new=%d/%d/%d",
              ulop->weak ? ( sidx ? "weak[1]" : "weak[0]" ) : "strong",
              spa->strong, spa->weak[0], spa->weak[1]);
        }
        rtpp_log_write(RTPP_LOG_INFO, spa->log,
          "lookup on ports %d/%d, session timer restarted", spa->ports[0],
          spa->ports[1]);
    } else {
        assert(ccap->op == UPDATE);
        rtpp_log_write(RTPP_LOG_INFO, cf->stable->glog,
          "new session %s, tag %s requested, type %s",
          ccap->call_id, ccap->from_tag, ulop->weak ? "weak" : "strong");
        if (cf->stable->slowshutdown != 0) {
            rtpp_log_write(RTPP_LOG_INFO, cf->stable->glog,
              "proxy is in the deorbiting-burn mode, new session rejected");
            reply_error(cf, cmd, ECODE_SLOWSHTDN);
            goto err_undo_0;
        }
        if (ulop->local_addr != NULL) {
            ulop->lia[0] = ulop->lia[1] = ulop->local_addr;
        }
        if (rtpp_create_listener(cf, ulop->lia[0], &lport, fds) == -1) {
            rtpp_log_write(RTPP_LOG_ERR, cf->stable->glog, "can't create listener");
            reply_error(cf, cmd, ECODE_LSTFAIL_2);
            goto err_undo_0;
        }

        /*
         * Session creation. If creation is requested with weak flag,
         * set weak[0].
         */
        spa = malloc(sizeof(*spa));
        if (spa == NULL) {
            handle_nomem(cf, cmd, ECODE_NOMEM_4, ulop,
              fds, spa, spb);
            return (-1);
        }
        /* spb is RTCP twin session for this one. */
        spb = malloc(sizeof(*spb));
        if (spb == NULL) {
            handle_nomem(cf, cmd, ECODE_NOMEM_5, ulop,
              fds, spa, spb);
            return (-1);
        }
        memset(spa, 0, sizeof(*spa));
        memset(spb, 0, sizeof(*spb));
        spa->init_ts = cmd->dtime;
        spb->init_ts = cmd->dtime;
        for (i = 0; i < 2; i++) {
            spa->fds[i] = spb->fds[i] = -1;
            spa->last_update[i] = 0;
            spb->last_update[i] = 0;
        }
        spa->call_id = strdup(ccap->call_id);
        if (spa->call_id == NULL) {
            handle_nomem(cf, cmd, ECODE_NOMEM_6, ulop,
              fds, spa, spb);
            return (-1);
        }
        spb->call_id = spa->call_id;
        spa->tag = strdup(ccap->from_tag);
        spa->tag_nomedianum = strdup(ccap->from_tag);
        if (spa->tag == NULL) {
            handle_nomem(cf, cmd, ECODE_NOMEM_7, ulop,
              fds, spa, spb);
            return (-1);
        }
        cp = strrchr(spa->tag_nomedianum, ';');
        if (cp != NULL)
            *cp = '\0';
        spb->tag = spa->tag;
        spb->tag_nomedianum = spa->tag_nomedianum;
        for (i = 0; i < 2; i++) {
            spa->rrcs[i] = NULL;
            spb->rrcs[i] = NULL;
            spa->laddr[i] = ulop->lia[i];
            spb->laddr[i] = ulop->lia[i];
        }
        spa->strong = spa->weak[0] = spa->weak[1] = 0;
        if (ulop->weak)
            spa->weak[0] = 1;
        else
            spa->strong = 1;
        assert(spa->fds[0] == -1);
        spa->fds[0] = fds[0];
        assert(spb->fds[0] == -1);
        spb->fds[0] = fds[1];
        spa->ports[0] = lport;
        spb->ports[0] = lport + 1;
        spa->ttl[0] = cf->stable->max_ttl;
        spa->ttl[1] = cf->stable->max_ttl;
        spb->ttl[0] = -1;
        spb->ttl[1] = -1;
        spa->log = rtpp_log_open(cf->stable, "rtpproxy", spa->call_id, 0);
        rtpp_log_setlevel(spa->log, cf->stable->log_level);
        spb->log = spa->log;
        spa->rtcp = spb;
        spb->rtcp = NULL;
        spa->rtp = NULL;
        spb->rtp = spa;
        spa->sridx = spb->sridx = -1;

        append_session(cf, spa, 0);
        append_session(cf, spa, 1);

        spa->hte = CALL_METHOD(cf->stable->sessions_ht, append, spa->call_id, spa);
        if (spa->hte == NULL) {
            remove_session(cf, spa);
            remove_session(cf, spb);
            handle_nomem(cf, cmd, ECODE_NOMEM_8, ulop, fds, spa, spb);
            return (-1);
        }

        cf->sessions_created++;
        cf->sessions_active++;
        cmd->csp->nsess_created.cnt++;

        /*
         * Each session can consume up to 5 open file descriptors (2 RTP,
         * 2 RTCP and 1 logging) so that warn user when he is likely to
         * exceed 80% mark on hard limit.
         */
        if (cf->sessions_active > (rtpp_rlim_max(cf) * 80 / (100 * 5)) &&
          cf->nofile_limit_warned == 0) {
            cf->nofile_limit_warned = 1;
            rtpp_log_write(RTPP_LOG_WARN, cf->stable->glog, "passed 80%% "
              "threshold on the open file descriptors limit (%d), "
              "consider increasing the limit using -L command line "
              "option", (int)rtpp_rlim_max(cf));
        }

        rtpp_log_write(RTPP_LOG_INFO, spa->log, "new session on a port %d created, "
          "tag %s", lport, ccap->from_tag);
        if (cf->stable->record_all != 0) {
            handle_copy(cf, spa, 0, NULL, 0);
            handle_copy(cf, spa, 1, NULL, 0);
        }
    }

    if (ccap->op == UPDATE) {
        if (rtpp_th_get_sn(cf->timeout_handler) == NULL && ulop->socket_name_u != NULL)
            rtpp_log_write(RTPP_LOG_ERR, spa->log, "must permit notification socket with -n");
        if (spa->timeout_data.notify_tag != NULL) {
            free(spa->timeout_data.notify_tag);
            spa->timeout_data.notify_tag = NULL;
        }
        if (rtpp_th_get_sn(cf->timeout_handler) != NULL && ulop->socket_name_u != NULL) {
            if (strcmp(rtpp_th_get_sn(cf->timeout_handler), ulop->socket_name_u) != 0) {
                rtpp_log_write(RTPP_LOG_ERR, spa->log, "invalid socket name %s", ulop->socket_name_u);
                ulop->socket_name_u = NULL;
            } else {
                rtpp_log_write(RTPP_LOG_INFO, spa->log, "setting timeout handler");
                spa->timeout_data.handler = cf->timeout_handler;
                spa->timeout_data.notify_tag = strdup(ulop->notify_tag);
            }
        } else if (ulop->socket_name_u == NULL && spa->timeout_data.handler != NULL) {
            spa->timeout_data.handler = NULL;
            rtpp_log_write(RTPP_LOG_INFO, spa->log, "disabling timeout handler");
        }
    }

    if (ulop->ia[0] != NULL && ulop->ia[1] != NULL) {
        if (spa->addr[pidx] != NULL)
            spa->last_update[pidx] = cmd->dtime;
        if (spa->rtcp->addr[pidx] != NULL)
            spa->rtcp->last_update[pidx] = cmd->dtime;
        /*
         * Unless the address provided by client historically
         * cannot be trusted and address is different from one
         * that we recorded update it.
         */
        if (spa->untrusted_addr[pidx] == 0 && !(spa->addr[pidx] != NULL &&
          SA_LEN(ulop->ia[0]) == SA_LEN(spa->addr[pidx]) &&
          memcmp(ulop->ia[0], spa->addr[pidx], SA_LEN(ulop->ia[0])) == 0)) {
            rtpp_log_write(RTPP_LOG_INFO, spa->log, "pre-filling %s's address "
              "with %s:%s", (pidx == 0) ? "callee" : "caller", ulop->addr, ulop->port);
            if (spa->addr[pidx] != NULL) {
                if (spa->canupdate[pidx] == 0) {
                    if (spa->prev_addr[pidx] != NULL)
                         free(spa->prev_addr[pidx]);
                    spa->prev_addr[pidx] = spa->addr[pidx];
                } else {
                    free(spa->addr[pidx]);
                }
            }
            spa->addr[pidx] = ulop->ia[0];
            ulop->ia[0] = NULL;
        }
        if (spa->rtcp->untrusted_addr[pidx] == 0 && !(spa->rtcp->addr[pidx] != NULL &&
          SA_LEN(ulop->ia[1]) == SA_LEN(spa->rtcp->addr[pidx]) &&
          memcmp(ulop->ia[1], spa->rtcp->addr[pidx], SA_LEN(ulop->ia[1])) == 0)) {
            if (spa->rtcp->addr[pidx] != NULL) {
                if (spa->rtcp->canupdate[pidx] == 0) {
                    if (spa->rtcp->prev_addr[pidx] != NULL)
                        free(spa->rtcp->prev_addr[pidx]);
                    spa->rtcp->prev_addr[pidx] = spa->rtcp->addr[pidx];
                } else {
                    free(spa->rtcp->addr[pidx]);
                }
            }
            spa->rtcp->addr[pidx] = ulop->ia[1];
            ulop->ia[1] = NULL;
        }
    }
    spa->asymmetric[pidx] = spa->rtcp->asymmetric[pidx] = ulop->asymmetric;
    spa->canupdate[pidx] = spa->rtcp->canupdate[pidx] = NOT(ulop->asymmetric);
    if (spa->codecs[pidx] != NULL) {
        free(spa->codecs[pidx]);
        spa->codecs[pidx] = NULL;
    }
    if (ulop->codecs != NULL) {
        spa->codecs[pidx] = ulop->codecs;
        ulop->codecs = NULL;
    }
    if (ulop->requested_nsamples > 0) {
        rtpp_log_write(RTPP_LOG_INFO, spa->log, "RTP packets from %s "
          "will be resized to %d milliseconds",
          (pidx == 0) ? "callee" : "caller", ulop->requested_nsamples / 8);
    } else if (spa->resizers[pidx] != NULL) {
          rtpp_log_write(RTPP_LOG_INFO, spa->log, "Resizing of RTP "
          "packets from %s has been disabled",
          (pidx == 0) ? "callee" : "caller");
    }
    if (ulop->requested_nsamples > 0) {
        if (spa->resizers[pidx] != NULL) {
            rtp_resizer_set_onsamples(spa->resizers[pidx], ulop->requested_nsamples);
        } else {
            spa->resizers[pidx] = rtp_resizer_new(ulop->requested_nsamples);
        }
    } else if (spa->resizers[pidx] != NULL) {
        rtp_resizer_free(spa->resizers[pidx]);
        spa->resizers[pidx] = NULL;
    }

    assert(lport != 0);
    ulop->reply.port = lport;
    ulop->reply.ia = ulop->lia[0];
    if (cf->stable->advaddr[0] != NULL) {
        if (cf->stable->bmode != 0 && cf->stable->advaddr[1] != NULL &&
          ulop->lia[0] == cf->stable->bindaddr[1]) {
            ulop->reply.ia_ov = cf->stable->advaddr[1];
        } else {
            ulop->reply.ia_ov = cf->stable->advaddr[0];
        }
    }
    ul_reply_port(cf, cmd, &ulop->reply);
    rtpp_command_ul_opts_free(ulop);
    return (0);

err_undo_0:
    rtpp_command_ul_opts_free(ulop);
    return (-1);
}
示例#9
0
/*
**  Name:	void el1_send(dpeth_t *dep, int from_int, int pktsize)
**  Function:	Send function.  Called from main to transit a packet or
**  		from interrupt handler when a new packet was queued.
*/
static void el1_send(dpeth_t * dep, int from_int, int pktsize)
{
  buff_t *txbuff;
  clock_t now;

  if (from_int == FALSE) {

	if ((txbuff = alloc_buff(dep, pktsize + sizeof(buff_t))) != NULL) {

		/*  Fill transmit buffer from user area */
		txbuff->next = NULL;
		txbuff->size = pktsize;
		txbuff->client = dep->de_client;
		user2mem(dep, txbuff);
	} else
		panic(dep->de_name, "out of memory for Tx", NO_NUM);

  } else if ((txbuff = dep->de_xmitq_head) != NULL) {

	/* Get first packet in queue */
	lock();
	if (dep->de_xmitq_tail == dep->de_xmitq_head)
		dep->de_xmitq_head = dep->de_xmitq_tail = NULL;
	else
		dep->de_xmitq_head = txbuff->next;
	unlock();
	pktsize = txbuff->size;

  } else
	panic(dep->de_name, "should not be sending ", NO_NUM);

  if ((dep->de_flags & DEF_XMIT_BUSY)) {
	if (from_int) panic(dep->de_name, "should not be sending ", NO_NUM);
	getuptime(&now);
	if ((now - dep->de_xmit_start) > 4) {
		/* Transmitter timed out */
		DEBUG(printf("3c501: transmitter timed out ... \n"));
		dep->de_stat.ets_sendErr += 1;
		dep->de_flags &= NOT(DEF_XMIT_BUSY);
		el1_reset(dep);
	}

	/* Queue packet */
	lock();			/* Queue packet to receive queue */
	if (dep->de_xmitq_head == NULL)
		dep->de_xmitq_head = txbuff;
	else
		dep->de_xmitq_tail->next = txbuff;
	dep->de_xmitq_tail = txbuff;
	unlock();
  } else {
	/* Save for retransmission */
	TxBuff = txbuff;
	dep->de_flags |= (DEF_XMIT_BUSY | DEF_ACK_SEND);

	/* Setup board for packet loading */
	lock();			/* Buffer to processor */
	outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_SYS);
	inb_el1(dep, EL1_RECV);	/* Clears any spurious interrupt */
	inb_el1(dep, EL1_XMIT);
	outw_el1(dep, EL1_RECVPTR, 0);	/* Clears RX packet area */

	/* Loads packet */
	outw_el1(dep, EL1_XMITPTR, (EL1_BFRSIZ - pktsize));
	outsb(dep->de_data_port, SELF, txbuff->buffer, pktsize);
	/* Starts transmitter */
	outw_el1(dep, EL1_XMITPTR, (EL1_BFRSIZ - pktsize));
	outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_XMIT);	/* There it goes... */
	unlock();

	getuptime(&dep->de_xmit_start);
	dep->de_flags &= NOT(DEF_SENDING);
  }
  return;
}
//==================================================================
static void resolveFunctionCalls(
						TokNode *pNode,
						const DVec<Function> &funcs )
{
	for (size_t i=0; i < pNode->mpChilds.size(); ++i)
	{
		resolveFunctionCalls( pNode->mpChilds[i], funcs );
	}

	if ( pNode->mNodeType == TokNode::TYPE_FUNCCALL )
	{
		// do we have any params ?
		if ( pNode->mpChilds.size() )
		{
			const TokNode	*pParamsList = pNode->mpChilds[0];

			// bogus params ?
			for (size_t i=0; i < pParamsList->mpChilds.size(); ++i)
			{
				VarType vtype = pParamsList->mpChilds[i]->GetVarType();
				if ( vtype == VT_UNKNOWN )
				{
					throw Exception( pNode, "Unknown type for parameter %i", i+1 );
					//break;
				}
			}
		}

		const Function	*pFunc = NULL;

		// is asm func ? If so, then no need to process anything else here
		if ( IsAsmFunc( pNode->GetTokStr() ) )
			return;

		// find the function by its name and it's parameters types
		pFunc = MatchFunctionByParams( pNode, funcs );

		if NOT( pFunc )
		{
			// if not, then throw an exception
			throw Exception(
				DUT::SSPrintFS( "Could not find the function: %s", pNode->GetTokStr() ),
				pNode );
		}

		TokNode	*pClonedParamsHooks = cloneBranch( pFunc->mpParamsNode );

		TokNode	*pFollowingStatement = NULL;
		if ( pFunc->mpRetTypeTok->id == T_KW___funcop )
		{
			pFollowingStatement = pNode->GetRight();
		}

		// place the params block where the function call (name) currently is
		pClonedParamsHooks->ReplaceNode( pNode );

		// don't add the return value for "void" functions !
		if ( pFunc->mRetVarType != VT_VOID )
		{
			// add a return node/variable
			AddVariable(
				pClonedParamsHooks->mpParent,
				DNEW TokNode( DNEW Token( *pFunc->mpRetTypeTok ) ),
				DNEW TokNode( "varying", T_DE_varying, T_TYPE_DETAIL, pClonedParamsHooks ),	// %%% forced varying for now !
				NULL,
				pClonedParamsHooks,
				false,
				true );
		}

		const TokNode	*pPassParams = pNode->GetChildTry( 0 );

		assignPassingParams( pClonedParamsHooks, pPassParams );

		// a funcop ?
		if ( pFunc->mpRetTypeTok->id == T_KW___funcop )
		{
			// NOTE: do re really need to do this reparenting ??!

			if NOT( pFollowingStatement )
				throw Exception( "Missing statement !", pNode );

			pClonedParamsHooks->mIsFuncOp = true;

			handleFuncopEndForIfElse( pClonedParamsHooks );
		}
	}
}
示例#11
0
WireSyntax::WireSyntax()
{
    SYNTAX("Wire");

    DEFINE_VOID("Comment",
                CHOICE(
                    GLUE(
                        STRING("//"),
                        CHOICE(
                            FIND(AHEAD(CHAR('\n'))),
                            FIND(EOI())
                        )
                    ),
                    GLUE(
                        STRING("/*"),
                        REPEAT(
                            CHOICE(
                                INLINE("Comment"),
                                GLUE(
                                    NOT(STRING("*/")),
                                    ANY()
                                )
                            )
                        ),
                        STRING("*/")
                    )
                )
               );

    DEFINE_VOID("Whitespace",
                REPEAT(
                    CHOICE(
                        RANGE(" \t\n"),
                        INLINE("Comment")
                    )
                )
               );

    DEFINE("Name",
           REPEAT(1, EXCEPT(" \t\n:;"))
          );

    DEFINE("Value",
           CHOICE(
               REF("Atom"),
               REF("Properties"),
               REF("Items")
           )
          );

    DEFINE("Object",
           GLUE(
               REPEAT(0, 1,
                      GLUE(
                          REF("Name"),
                          INLINE("Whitespace"),
                          CHAR(':'),
                          INLINE("Whitespace")
                      )
                     ),
               INLINE("Value")
           )
          );

    DEFINE("Atom",
           REPEAT(
               GLUE(
                   NOT(
                       CHOICE(
                           GLUE(
                               REPEAT(RANGE(" \t")),
                               INLINE("Name"),
                               REPEAT(RANGE(" \t")),
                               CHAR(':')
                           ),
                           GLUE(
                               REPEAT(RANGE(" \t")),
                               RANGE("};,")
                           ),
                           STRING("\n\n")
                       )
                   ),
                   ANY()
               )
           )
          );

    DEFINE("Properties",
           GLUE(
               CHAR('{'),
               INLINE("Whitespace"),
               REPEAT(
                   GLUE(
                       REF("Object"),
                       INLINE("Whitespace"),
                       RANGE(";,"),
                       INLINE("Whitespace")
                   )
               ),
               CHAR('}')
           )
          );

    DEFINE("Items",
           GLUE(
               CHAR('['),
               INLINE("Whitespace"),
               REPEAT(
                   GLUE(
                       REF("Value"),
                       INLINE("Whitespace"),
                       RANGE(";,"),
                       INLINE("Whitespace")
                   )
               ),
               CHAR(']')
           )
          );

    ENTRY("Object");
}
示例#12
0
文件: lisp100.c 项目: plops/clicc
void Fpathname_host(CL_FORM *base, int nargs)
{
	BOOL supl_flags[1];
	static CL_FORM * keylist[] =
	{
		SYMBOL(Slisp, 208),	/* CASE */
	};
	keysort(STACK(base, 1), nargs - 1, 1, keylist, supl_flags, FALSE);
	if(NOT(supl_flags[0]))
	{
		LOAD_SYMBOL(SYMBOL(Slisp, 207), STACK(base, 1));	/* LOCAL */
	}
	COPY(STACK(base, 0), STACK(base, 2));
	COPY(STACK(base, 0), STACK(base, 3));
	LOAD_SYMBOL(SYMBOL(Slisp, 164), STACK(base, 4));	/* PATHNAME */
	struct_typep(STACK(base, 3));
	if(CL_TRUEP(STACK(base, 3)))
	{
		COPY(STACK(base, 0), STACK(base, 2));
	}
	else
	{
		if(CL_ARRAY_P(STACK(base, 0)))
		{
			COPY(STACK(base, 0), STACK(base, 3));
			LOAD_SYMBOL(SYMBOL(Slisp, 43), STACK(base, 4));	/* STANDARD-CHAR */
			LOAD_SYMBOL(SYMBOL(Slisp, 48), STACK(base, 5));	/* * */
			check_array_internal(STACK(base, 3));
			bool_result = CL_TRUEP(STACK(base, 3));
		}
		else
		{
			bool_result = FALSE;
		}
		if(bool_result)
		{
			COPY(STACK(base, 0), STACK(base, 2));
			Fparse_namestring(STACK(base, 2), 1);
			mv_count = 1;
		}
		else
		{
			COPY(STACK(base, 0), STACK(base, 3));
			LOAD_SYMBOL(SYMBOL(Slisp, 63), STACK(base, 4));	/* STREAM */
			struct_typep(STACK(base, 3));
			if(CL_TRUEP(STACK(base, 3)))
			{
				COPY(STACK(base, 0), STACK(base, 2));
				file_name(STACK(base, 2), 1);
				Fparse_namestring(STACK(base, 2), 1);
				mv_count = 1;
			}
			else
			{
				LOAD_SMSTR((CL_FORM *)&KFpathname_host[0], STACK(base, 2));	/* etypecase: the value ~a is not a legal value */
				COPY(STACK(base, 0), STACK(base, 3));
				Ferror(STACK(base, 2), 2);
			}
		}
	}
	COPY(STACK(base, 2), STACK(base, 0));
	LOAD_FIXNUM(0, STACK(base, 1));
	LOAD_SYMBOL(SYMBOL(Slisp, 164), STACK(base, 2));	/* PATHNAME */
	struct_ref(STACK(base, 0));
}
CmpStatement::ReturnStatus
CmpStatement::process (const CmpMessageCompileStmt& compilestmt)
{
  CmpMain cmpmain;

  CMPASSERT(compilestmt.getCmpCompileInfo());

  char * sqlStr = NULL;
  Int32 sqlStrLen = 0;
  Lng32 inputCS = 0;
  NAString currCatName;
  NAString currSchName;
  char * recompControlInfo = NULL;
  NABoolean isSchNameRecvd;
  NABoolean nametypeNsk;
  NABoolean odbcProcess;
  NABoolean noTextCache;
  NABoolean aqrPrepare;
  NABoolean standaloneQuery;
  if (processRecvdCmpCompileInfo(this,
				 compilestmt,
  				 compilestmt.getCmpCompileInfo(),
				 context_,
				 sqlStr,
				 sqlStrLen, // out - long &
				 inputCS,
				 isSchNameRecvd, 
				 currCatName, currSchName,
				 recompControlInfo,
				 nametypeNsk,
				 odbcProcess,
				 noTextCache,
				 aqrPrepare,
				 standaloneQuery))
    return CmpStatement_ERROR;

  reply_ =
    new(outHeap_) CmpMessageReplyCode( outHeap_, compilestmt.id(), 
				       0, 0, outHeap_);
   
  // A pointer to user SQL query is stored in CmpStatement; if an exception is
  // thrown the user query is copied from here. It is reset upon return from
  // sqlcompStatic() method.

  sqlTextStr_ = sqlStr;
  sqlTextLen_ = sqlStrLen;

  // process recompControlInfo, if received
  if (recompControlInfo)
    setupRecompControlInfo(recompControlInfo, &cmpmain, inputCS);


  // set ODBC_PROCESS default.
  NABoolean odbcProcessChanged = FALSE;
  if (odbcProcess)
    {
      if (CmpCommon::getDefault(ODBC_PROCESS) != DF_ON)
	{
	  odbcProcessChanged = TRUE;
	  NAString op("ON");
	  context_->schemaDB_->getDefaults().validateAndInsert("ODBC_PROCESS", op, FALSE);
	}
      if (CmpCommon::getDefault(JDBC_PROCESS) != DF_ON)
	{
	  odbcProcessChanged = TRUE;
	  NAString op("ON");
	  context_->schemaDB_->getDefaults().validateAndInsert("JDBC_PROCESS", op, FALSE);
	}
      
    }
  
  QueryText qText(sqlStr, inputCS);
  cmpmain.setSqlParserFlags(compilestmt.getFlags());

  if (compilestmt.getCmpCompileInfo()->isSystemModuleStmt())
  {
  CMPASSERT(FALSE);
 }

  ULng32 flags = 0;

  NABoolean qtcChanged = FALSE;
  if ((CmpCommon::getDefault(QUERY_TEXT_CACHE) == DF_SYSTEM) &&
      (aqrPrepare || noTextCache))
    {
      CMPASSERT(NOT (aqrPrepare && noTextCache));

      qtcChanged = TRUE;
      NAString op(((aqrPrepare && standaloneQuery) ? "SKIP" : "OFF"));
      context_->schemaDB_->getDefaults().validateAndInsert("QUERY_TEXT_CACHE", op, FALSE);
    }

  CmpMain::ReturnStatus rs = 
    cmpmain.sqlcompStatic(qText, 0, 
			  &(reply_->data()), &(reply_->size()),
			  reply_->outHeap(), CmpMain::END, 
			  compilestmt.getType());
  sqlTextStr_ = NULL;

  
  // restore the original cat & schema names before returning.
  if (isSchNameRecvd)
    {
      context_->schemaDB_->getDefaults().setCatalogTrustedFast(currCatName);
      context_->schemaDB_->getDefaults().setSchemaTrustedFast(currSchName);
    }

  if (recompControlInfo)
    restoreRecompControlInfo(recompControlInfo);


  if (odbcProcessChanged)
    {
      // restore the original odbc process setting
      NAString op("OFF");
      context_->schemaDB_->getDefaults().validateAndInsert("ODBC_PROCESS", op, FALSE);
      context_->schemaDB_->getDefaults().validateAndInsert("JDBC_PROCESS", op, FALSE);
    }

  if (qtcChanged)
    {
      // restore the original query text cache setting
      NAString op("SYSTEM");
      context_->schemaDB_->getDefaults().validateAndInsert("QUERY_TEXT_CACHE", op, FALSE);
    }

  if (rs)
    {
      error(arkcmpErrorNoDiags,sqlStr);
      return CmpStatement_ERROR;
    }

  return CmpStatement_SUCCESS;
}
CmpStatement::ReturnStatus
CmpStatement::process (const CmpMessageSQLText& sqltext)
{
  CmpMain cmpmain;

  CMPASSERT(sqltext.getCmpCompileInfo());
  
  char * sqlStr = NULL;
  Int32 sqlStrLen = 0;
  Lng32 inputCS = 0;
  NAString currCatName;
  NAString currSchName;
  char * recompControlInfo = NULL;
  NABoolean isSchNameRecvd;
  NABoolean nametypeNsk;
  NABoolean odbcProcess;
  NABoolean noTextCache;
  NABoolean aqrPrepare;
  NABoolean standaloneQuery;
  if (processRecvdCmpCompileInfo(this,
				 sqltext,
  				 sqltext.getCmpCompileInfo(),
				 context_,
				 sqlStr, 
				 sqlStrLen, // out - long &
				 inputCS,
				 isSchNameRecvd, 
				 currCatName, currSchName, 
				 recompControlInfo,
				 nametypeNsk,
				 odbcProcess,
				 noTextCache,
				 aqrPrepare,
				 standaloneQuery))
    return CmpStatement_ERROR;

  reply_ = new(outHeap_) CmpMessageReplyCode( outHeap_, sqltext.id(), 0, 0, outHeap_);
  
  if ((sqlStr) && inputCS == SQLCHARSETCODE_ISO88591 &&
      (strncmp(sqlStr, "select $ZZDEBUG", strlen("select $ZZDEBUG")) == 0))
    {
      NADebug();
    }


 // If this is an ODBC query transmit inputArrayMaxsize and rowsetAtomicity information 
 // (used for binding rowsets as input parameters) from CLI into cmpmain
 // so that it can be used during binding.
  if ((CmpCommon::getDefault(ODBC_PROCESS) == DF_ON) ||
      (CmpCommon::getDefault(JDBC_PROCESS) == DF_ON))
  {
    cmpmain.setInputArrayMaxsize(sqltext.getCmpCompileInfo()->getInputArrayMaxsize());
    cmpmain.setRowsetAtomicity(sqltext.getCmpCompileInfo()->getRowsetAtomicity());
  }
  cmpmain.setHoldableAttr(sqltext.getCmpCompileInfo()->getHoldableAttr());
 
  FragmentDir * fragmentDir = NULL;
  IpcMessageObjType typ = sqltext.getType();

  //
  //if this is a recompilation
  if (typ == CmpMessageObj::SQLTEXT_RECOMPILE) {
    recompiling_ = TRUE;
  }
 
  // A pointer to user SQL query is stored in CmpStatement; if an exception is
  // thrown the user query is copied from here. It is reset upon return from
  // sqlcomp() method.
  sqlTextStr_ = sqlStr;
  sqlTextLen_ = sqlStrLen;
  sqlTextCharSet_ = inputCS;

  QueryText qText(sqlStr, inputCS);
  cmpmain.setSqlParserFlags(sqltext.getFlags());

  NABoolean qtcChanged = FALSE;
  if ((CmpCommon::getDefault(QUERY_TEXT_CACHE) == DF_SYSTEM) &&
      (aqrPrepare || noTextCache))
    {
      CMPASSERT(NOT (aqrPrepare && noTextCache));

      qtcChanged = TRUE;
      NAString op(((aqrPrepare && standaloneQuery) ? "SKIP" : "OFF"));
      context_->schemaDB_->getDefaults().validateAndInsert("QUERY_TEXT_CACHE", op, FALSE);
    }

  CmpMain::ReturnStatus rs = CmpMain::SUCCESS;
  try
  {
    rs =
    cmpmain.sqlcomp(qText, 0, 
		    &(reply_->data()), &(reply_->size()),
		    reply_->outHeap(), CmpMain::END, 
		    &fragmentDir, typ);
  }
  catch (...)
  {
    error(arkcmpErrorNoDiags,sqlStr);
    return CmpStatement_ERROR;
  }

  sqlTextStr_ = NULL;
  
  ((CmpMessageReplyCode *)reply_)->setFragmentDir(fragmentDir);

  // restore the original cat & schema names before returning.
  if (isSchNameRecvd)
    {
      context_->schemaDB_->getDefaults().setCatalogTrustedFast(currCatName);
      context_->schemaDB_->getDefaults().setSchemaTrustedFast(currSchName);
    }

  if (qtcChanged)
    {
      // restore the original query text cache setting
      NAString op("SYSTEM");
      context_->schemaDB_->getDefaults().validateAndInsert("QUERY_TEXT_CACHE", op, FALSE);
    }

  if (rs)
    {
      error(arkcmpErrorNoDiags,sqlStr);
      return CmpStatement_ERROR;
    }

  return CmpStatement_SUCCESS;
}
int    GLUI_EditText::key_handler( unsigned char key,int modifiers )
{
  int i, regular_key;
  /* int has_selection;              */

  if ( NOT glui )
    return false;

  if ( debug )
    dump( stdout, "-> KEY HANDLER" );

  regular_key = false;
  /*  has_selection = (sel_start != sel_end);              */

  if ( key == 21 AND (modifiers & GLUT_ACTIVE_CTRL )!=0) { /* DEL all text */
    /** This one (key==21) may not port!! */
    
    insertion_pt = -1;  
    text[0] = '\0';
    sel_start = sel_end = -1;
  }
  else if ( key == 13 ) {           /* RETURN */
    /*    glui->disactivate_current_control();              */
    disactivate();  /** Force callbacks, etc **/
    activate(GLUI_ACTIVATE_TAB);     /** Reselect all text **/
    translate_and_draw_front();
    return true;
  }
  else if ( key  == 27 ) {         /* ESCAPE */
    glui->disactivate_current_control();
    return true;
  }
  else if ( key == 8 ) {       /* BACKSPACE */
    if ( sel_start == sel_end ) {   /* no selection */
      if ( insertion_pt > 0 ) {
	/*** See if we're deleting a period in a float data-type box ***/
	if ( data_type == GLUI_EDITTEXT_FLOAT AND text[insertion_pt-1]=='.' )
	  num_periods--;
	
	/*** Shift over string first ***/
	insertion_pt--;
	for( i=insertion_pt; i< (int)strlen( text ); i++ )
	  text[i] = text[i+1];    
      }
    }
    else {                         /* There is a selection */
      clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end ));
      insertion_pt = MIN(sel_start,sel_end);
      sel_start = sel_end = insertion_pt;
    }
  }
  else {                      /* Regular key */    
    regular_key = true;
    
    /** Check if we only accept numbers **/
    if (data_type == GLUI_EDITTEXT_FLOAT ) {
      if ( (key < '0' OR key > '9') AND key != '.' AND key != '-' )
	return true;

      if ( key == '-' ) { /* User typed a '-' */

	/* If user has first character selected, then '-' is allowed */
	if ( NOT ( MIN(sel_start,sel_end) == 0 AND
		   MAX(sel_start,sel_end) > 0 ) ) {

	  /* User does not have 1st char selected */
	  if (insertion_pt != 0 OR text[0] == '-' ) {
	    return true; /* Can only place negative at beginning of text,
			    and only one of them */
	  }
	}
      }

      if ( key == '.' ) {
	/*printf( "PERIOD: %d\n", num_periods );              */

	if ( num_periods > 0 ) {
	  /** We're trying to type a period, but the text already contains
	    a period.  Check whether the period is contained within
	    is current selection (thus it will be safely replaced) **/

	  int period_found = false; 
	  if ( sel_start != sel_end ) {
	    for( i=MIN(sel_end,sel_start); i<MAX(sel_start,sel_end); i++ ) {
	      /*  printf( "%c ", text[i] );              */
	      if ( text[i] == '.' ) {
		period_found = true;
		break;
	      }
	    }
	  }

	  /* printf( "found: %d    num: %d\n", period_found, num_periods );              */
	  
	  if ( NOT period_found )
	    return true;
	}
      }
    } 
    else if (data_type == GLUI_EDITTEXT_INT)	
    {
      if ( (key < '0' OR key > '9') AND key != '-' )
	return true;

      if ( key == '-' ) { /* User typed a '-' */

	/* If user has first character selected, then '-' is allowed */
	if ( NOT ( MIN(sel_start,sel_end) == 0 AND
		   MAX(sel_start,sel_end) > 0 ) ) {

	  /* User does not have 1st char selected */
	  if (insertion_pt != 0 OR text[0] == '-' ) {
	    return true; /* Can only place negative at beginning of text,
			    and only one of them */
	  }
	}
      }
    }

    /** This is just to get rid of warnings - the flag regular_key is 
      set if the key was not a backspace, return, whatever.  But I
      believe if we're here, we know it was a regular key anyway */
    if ( regular_key ) {
    }

    /**** If there's a current selection, erase it ******/
    if ( sel_start != sel_end ) {
      clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end ));
      insertion_pt = MIN(sel_start,sel_end);
      sel_start = sel_end = insertion_pt;
    }

    /******** check whether we have space ******/
    if ( (int)strlen( text ) + 2 >= sizeof( GLUI_String ))
      return false;

    /******** We insert the character into the string ***/
     
    /*** Shift over string first ***/
    for( i=(int)strlen( text ); i >= insertion_pt; i-- )
      text[i+1] = text[i];
    
    /******** Now insert the character ********/
    text[insertion_pt] = key;    

    /******** Move the insertion point and substring_end one over ******/
    insertion_pt++;
    substring_end++;

    sel_start = sel_end = insertion_pt;
  }
  
  /******** Now redraw text ***********/
  /* Hack to prevent text box from being cleared first **/  
  /**  int substring_change =  update_substring_bounds();
    draw_text_only = 
    (NOT substring_change AND NOT has_selection AND regular_key ); 
    */

  draw_text_only = false;  /** Well, hack is not yet working **/
  update_and_draw_text();
  draw_text_only = false;


  if ( debug )
    dump( stdout, "<- KEY HANDLER" );

  /*** Now look to see if this string has a period ***/
  num_periods = 0;
  for( i=0; i<(int)strlen(text); i++ )
    if ( text[i] == '.' )
      num_periods++;

  return true;
}
示例#16
0
/*
**  Name:	void el1_interrupt(dpeth_t *dep)
**  Function:	Interrupt handler.  Acknwledges transmit interrupts
**  		or unloads receive buffer to memory queue.
*/
static void el1_interrupt(dpeth_t * dep)
{
  u16_t csr, isr;
  int pktsize;
  buff_t *rxptr;

  csr = inb_el1(dep, EL1_CSR);
  if ((csr & ECSR_XMIT) && (dep->de_flags & DEF_XMIT_BUSY)) {

	/* Got a transmit interrupt */
	isr = inb_el1(dep, EL1_XMIT);
	if ((isr & (EXSR_16JAM | EXSR_UNDER | EXSR_JAM)) || !(isr & EXSR_IDLE)) {
	DEBUG(printf("3c501: got xmit interrupt (ASR=0x%02X XSR=0x%02X)\n", csr, isr));
		if (isr & EXSR_JAM) {
			/* Sending, packet got a collision */
			dep->de_stat.ets_collision += 1;
			/* Put pointer back to beginning of packet */
			outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_SYS);
			outw_el1(dep, EL1_XMITPTR, (EL1_BFRSIZ - TxBuff->size));
			/* And retrigger transmission */
			outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_XMIT);
			return;

		} else if ((isr & EXSR_16JAM) || !(isr & EXSR_IDLE)) {
			dep->de_stat.ets_sendErr += 1;

		} else if (isr & EXSR_UNDER) {
			dep->de_stat.ets_fifoUnder += 1;
		}
		DEBUG(printf("3c501: got xmit interrupt (0x%02X)\n", isr));
		el1_reset(dep);

	} else {
		/** if (inw_el1(dep, EL1_XMITPTR) == EL1_BFRSIZ) **/
		/* Packet transmitted successfully */
		dep->de_stat.ets_packetT += 1;
		dep->bytes_Tx += (long) (TxBuff->size);
		free_buff(dep, TxBuff);
		dep->de_flags &= NOT(DEF_XMIT_BUSY);
		if ((dep->de_flags & DEF_SENDING) && dep->de_xmitq_head) {
			/* Pending transmit request available in queue */
			el1_send(dep, TRUE, 0);
			if (dep->de_flags & (DEF_XMIT_BUSY | DEF_ACK_SEND))
				return;
		}
	}

  } else if ((csr & (ECSR_RECV | ECSR_XMTBSY)) == (ECSR_RECV | ECSR_XMTBSY)) {

	/* Got a receive interrupt */
	isr = inb_el1(dep, EL1_RECV);
	pktsize = inw_el1(dep, EL1_RECVPTR);
	if ((isr & ERSR_RERROR) || (isr & ERSR_STALE)) {
	DEBUG(printf("Rx0 (ASR=0x%02X RSR=0x%02X size=%d)\n", csr, isr, pktsize));
		dep->de_stat.ets_recvErr += 1;

	} else if (pktsize < ETH_MIN_PACK_SIZE || pktsize > ETH_MAX_PACK_SIZE) {
	DEBUG(printf("Rx1 (ASR=0x%02X RSR=0x%02X size=%d)\n", csr, isr, pktsize));
		dep->de_stat.ets_recvErr += 1;

	} else if ((rxptr = alloc_buff(dep, pktsize + sizeof(buff_t))) == NULL) {
		/* Memory not available. Drop packet */
		dep->de_stat.ets_fifoOver += 1;

	} else if (isr & (ERSR_GOOD | ERSR_ANY)) {
		/* Got a good packet. Read it from buffer */
		outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_SYS);
		outw_el1(dep, EL1_XMITPTR, 0);
		insb(dep->de_data_port, SELF, rxptr->buffer, pktsize);
		rxptr->next = NULL;
		rxptr->size = pktsize;
		dep->de_stat.ets_packetR += 1;
		dep->bytes_Rx += (long) pktsize;
		lock();		/* Queue packet to receive queue */
		if (dep->de_recvq_head == NULL)
			dep->de_recvq_head = rxptr;
		else
			dep->de_recvq_tail->next = rxptr;
		dep->de_recvq_tail = rxptr;
		unlock();

		/* Reply to pending Receive requests, if any */
		el1_recv(dep, TRUE, 0);
	}
  } else {			/* Nasty condition, should never happen */
	DEBUG(
	      printf("3c501: got interrupt with status 0x%02X\n"
		     "       de_flags=0x%04X  XSR=0x%02X RSR=0x%02X \n"
		     "       xmit buffer = 0x%4X recv buffer = 0x%4X\n",
			csr, dep->de_flags,
			inb_el1(dep, EL1_RECV),
			inb_el1(dep, EL1_XMIT),
			inw_el1(dep, EL1_XMITPTR),
			inw_el1(dep, EL1_RECVPTR))
		);
	el1_reset(dep);
  }

  /* Move into receive mode */
  outb_el1(dep, EL1_CSR, ECSR_RIDE | ECSR_RECV);
  outw_el1(dep, EL1_RECVPTR, 0);
  /* Be sure that interrupts are cleared */
  inb_el1(dep, EL1_RECV);
  inb_el1(dep, EL1_XMIT);
  return;
}
示例#17
0
static void do_conf(const message * mp)
{
  int r;
  dpeth_t *dep;
  message reply_mess;

  dep = &de_state;

  strncpy(dep->de_name, str_DevName, strlen(str_DevName));
  dep->de_name[strlen(dep->de_name)-1] = '0' + de_instance;

  if (dep->de_mode == DEM_DISABLED) {
    de_update_conf(dep); 
    pci_init();
    if (dep->de_mode == DEM_ENABLED && !de_probe(dep, de_instance)) {
	printf("%s: warning no ethernet card found at 0x%04X\n",
	       dep->de_name, dep->de_base_port);
	dep->de_mode = DEM_DISABLED;
    }
  }

  r = OK;

  /* 'de_mode' may change if probe routines fail, test again */
  switch (dep->de_mode) {

  case DEM_DISABLED:
    r = ENXIO;       /* Device is OFF or hardware probe failed */
    break;

  case DEM_ENABLED:
    if (dep->de_flags == DEF_EMPTY) {
	de_first_init(dep);
	dep->de_flags |= DEF_ENABLED;
	de_reset(dep);
	de_hw_conf(dep);
	de_setup_frame(dep);
	de_start(dep);
    }

    /* TODO CHECK PROMISC AND MULTI */
    dep->de_flags &= NOT(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
    if (mp->DL_MODE & DL_PROMISC_REQ)
	dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
    if (mp->DL_MODE & DL_MULTI_REQ) dep->de_flags |= DEF_MULTI;
    if (mp->DL_MODE & DL_BROAD_REQ) dep->de_flags |= DEF_BROAD;
    break;

  case DEM_SINK:
    DEBUG(printf("%s running in sink mode\n", str_DevName));
    memset(dep->de_address.ea_addr, 0, sizeof(ether_addr_t));
    de_conf_addr(dep);
    break;

  default:	break;
  }

  reply_mess.m_type = DL_CONF_REPLY;
  reply_mess.DL_STAT = r;
  if(r == OK){
    *(ether_addr_t *) reply_mess.DL_HWADDR = dep->de_address;
  }
  
  if (send(mp->m_source, &reply_mess) != OK)
    panic("%s %d", str_SendErrMsg, mp->m_source);

  return;
}
示例#18
0
void LoadMOBList()
{
    const int8* Query =
        "SELECT zoneid, name, mobid, pos_rot, pos_x, pos_y, pos_z, \
			respawntime, spawntype, dropid, mob_groups.HP, mob_groups.MP, minLevel, maxLevel, \
			modelid, mJob, sJob, cmbSkill, cmbDmgMult, cmbDelay, behavior, links, mobType, immunity, \
			systemid, mobsize, speed, \
			STR, DEX, VIT, AGI, `INT`, MND, CHR, EVA, DEF, \
			Slash, Pierce, H2H, Impact, \
			Fire, Ice, Wind, Earth, Lightning, Water, Light, Dark, Element, \
			mob_pools.familyid, name_prefix, unknown, animationsub, \
			(mob_family_system.HP / 100), (mob_family_system.MP / 100), hasSpellScript, spellList, ATT, ACC, mob_groups.poolid \
			FROM mob_groups INNER JOIN mob_pools ON mob_groups.poolid = mob_pools.poolid \
			INNER JOIN mob_spawn_points ON mob_groups.groupid = mob_spawn_points.groupid \
			INNER JOIN mob_family_system ON mob_pools.familyid = mob_family_system.familyid \
			WHERE NOT (pos_x = 0 AND pos_y = 0 AND pos_z = 0);";

    int32 ret = Sql_Query(SqlHandle, Query);

	if( ret != SQL_ERROR && Sql_NumRows(SqlHandle) != 0)
	{
		while(Sql_NextRow(SqlHandle) == SQL_SUCCESS)
		{
        	uint16 ZoneID = (uint16)Sql_GetUIntData(SqlHandle, 0);
			CMobEntity* PMob = new CMobEntity;

			PMob->name.insert(0,Sql_GetData(SqlHandle,1));
			PMob->id = (uint32)Sql_GetUIntData(SqlHandle,2);
			PMob->targid = (uint16)PMob->id & 0x0FFF;

			PMob->m_SpawnPoint.rotation = (uint8)Sql_GetIntData(SqlHandle,3);
			PMob->m_SpawnPoint.x = Sql_GetFloatData(SqlHandle,4);
			PMob->m_SpawnPoint.y = Sql_GetFloatData(SqlHandle,5);
			PMob->m_SpawnPoint.z = Sql_GetFloatData(SqlHandle,6);

			PMob->m_RespawnTime = Sql_GetUIntData(SqlHandle,7) * 1000;
			PMob->m_SpawnType   = (SPAWNTYPE)Sql_GetUIntData(SqlHandle,8);
			PMob->m_DropID		= Sql_GetUIntData(SqlHandle,9);

			PMob->HPmodifier = (uint32)Sql_GetIntData(SqlHandle,10);
			PMob->MPmodifier = (uint32)Sql_GetIntData(SqlHandle,11);

			PMob->m_minLevel = (uint8)Sql_GetIntData(SqlHandle,12);
			PMob->m_maxLevel = (uint8)Sql_GetIntData(SqlHandle,13);

			memcpy(&PMob->look,Sql_GetData(SqlHandle,14),23);

			PMob->SetMJob(Sql_GetIntData(SqlHandle,15));
			PMob->SetSJob(Sql_GetIntData(SqlHandle,16));

			PMob->m_Weapons[SLOT_MAIN]->setMaxHit(1);
			PMob->m_Weapons[SLOT_MAIN]->setSkillType(Sql_GetIntData(SqlHandle,17));
			PMob->m_dmgMult = Sql_GetUIntData(SqlHandle, 18);
			PMob->m_Weapons[SLOT_MAIN]->setDelay((Sql_GetIntData(SqlHandle,19) * 1000)/60);
			PMob->m_Weapons[SLOT_MAIN]->setBaseDelay((Sql_GetIntData(SqlHandle,19) * 1000)/60);

			PMob->m_Behaviour  = (uint16)Sql_GetIntData(SqlHandle,20);
			PMob->m_Link       = (uint8)Sql_GetIntData(SqlHandle,21);
			PMob->m_Type       = (uint8)Sql_GetIntData(SqlHandle,22);
			PMob->m_Immunity   = (IMMUNITY)Sql_GetIntData(SqlHandle,23);
			PMob->m_EcoSystem  = (ECOSYSTEM)Sql_GetIntData(SqlHandle,24);
			PMob->m_ModelSize += (uint8)Sql_GetIntData(SqlHandle,25);

			PMob->speed    = (uint8)Sql_GetIntData(SqlHandle,26);
			PMob->speedsub = (uint8)Sql_GetIntData(SqlHandle,26);

			/*if(PMob->speed != 0)
			{
				PMob->speed += map_config.speed_mod;
                // whats this for?
				PMob->speedsub += map_config.speed_mod;
			}*/

            PMob->strRank = (uint8)Sql_GetIntData(SqlHandle,27);
            PMob->dexRank = (uint8)Sql_GetIntData(SqlHandle,28);
            PMob->vitRank = (uint8)Sql_GetIntData(SqlHandle,29);
            PMob->agiRank = (uint8)Sql_GetIntData(SqlHandle,30);
            PMob->intRank = (uint8)Sql_GetIntData(SqlHandle,31);
            PMob->mndRank = (uint8)Sql_GetIntData(SqlHandle,32);
            PMob->chrRank = (uint8)Sql_GetIntData(SqlHandle,33);
            PMob->evaRank = (uint8)Sql_GetIntData(SqlHandle,34);
            PMob->defRank = (uint8)Sql_GetIntData(SqlHandle,35);
            PMob->attRank = (uint8)Sql_GetIntData(SqlHandle,57);
            PMob->accRank = (uint8)Sql_GetIntData(SqlHandle,58);

			PMob->setModifier(MOD_SLASHRES, (uint16)(Sql_GetFloatData(SqlHandle,36) * 1000));
			PMob->setModifier(MOD_PIERCERES,(uint16)(Sql_GetFloatData(SqlHandle,37) * 1000));
			PMob->setModifier(MOD_HTHRES,   (uint16)(Sql_GetFloatData(SqlHandle,38) * 1000));
			PMob->setModifier(MOD_IMPACTRES,(uint16)(Sql_GetFloatData(SqlHandle,39) * 1000));

            PMob->setModifier(MOD_FIREDEF,    (int16)((Sql_GetFloatData(SqlHandle, 40) - 1) * -1000)); // These are stored as floating percentages
            PMob->setModifier(MOD_ICEDEF,     (int16)((Sql_GetFloatData(SqlHandle, 41) - 1) * -1000)); // and need to be adjusted into modifier units.
            PMob->setModifier(MOD_WINDDEF,    (int16)((Sql_GetFloatData(SqlHandle, 42) - 1) * -1000)); // Higher DEF = lower damage.
            PMob->setModifier(MOD_EARTHDEF,   (int16)((Sql_GetFloatData(SqlHandle, 43) - 1) * -1000)); // Negatives signify increased damage.
            PMob->setModifier(MOD_THUNDERDEF, (int16)((Sql_GetFloatData(SqlHandle, 44) - 1) * -1000)); // Positives signify reduced damage.
            PMob->setModifier(MOD_WATERDEF,   (int16)((Sql_GetFloatData(SqlHandle, 45) - 1) * -1000)); // Ex: 125% damage would be 1.25, 50% damage would be 0.50
            PMob->setModifier(MOD_LIGHTDEF,   (int16)((Sql_GetFloatData(SqlHandle, 46) - 1) * -1000)); // (1.25 - 1) * -1000 = -250 DEF
            PMob->setModifier(MOD_DARKDEF,    (int16)((Sql_GetFloatData(SqlHandle, 47) - 1) * -1000)); // (0.50 - 1) * -1000 = 500 DEF

            PMob->setModifier(MOD_FIRERES,    (int16)((Sql_GetFloatData(SqlHandle, 40) - 1) * -100)); // These are stored as floating percentages
            PMob->setModifier(MOD_ICERES,     (int16)((Sql_GetFloatData(SqlHandle, 41) - 1) * -100)); // and need to be adjusted into modifier units.
            PMob->setModifier(MOD_WINDRES,    (int16)((Sql_GetFloatData(SqlHandle, 42) - 1) * -100)); // Higher RES = lower damage.
            PMob->setModifier(MOD_EARTHRES,   (int16)((Sql_GetFloatData(SqlHandle, 43) - 1) * -100)); // Negatives signify lower resist chance.
            PMob->setModifier(MOD_THUNDERRES, (int16)((Sql_GetFloatData(SqlHandle, 44) - 1) * -100)); // Positives signify increased resist chance.
            PMob->setModifier(MOD_WATERRES,   (int16)((Sql_GetFloatData(SqlHandle, 45) - 1) * -100));
            PMob->setModifier(MOD_LIGHTRES,   (int16)((Sql_GetFloatData(SqlHandle, 46) - 1) * -100));
            PMob->setModifier(MOD_DARKRES,    (int16)((Sql_GetFloatData(SqlHandle, 47) - 1) * -100));

			PMob->m_Element = (uint8)Sql_GetIntData(SqlHandle,48);
			PMob->m_Family = (uint16)Sql_GetIntData(SqlHandle,49);
			PMob->m_name_prefix = (uint8)Sql_GetIntData(SqlHandle,50);
			PMob->m_unknown = (uint32)Sql_GetIntData(SqlHandle,51);

			//Special sub animation for Mob (yovra, jailer of love, phuabo)
			// yovra 1: en hauteur, 2: en bas, 3: en haut
			// phuabo 1: sous l'eau, 2: sort de l'eau, 3: rentre dans l'eau
			PMob->animationsub = (uint32)Sql_GetIntData(SqlHandle,52);

			// Setup HP / MP Stat Percentage Boost
			PMob->HPscale = Sql_GetFloatData(SqlHandle,53);
			PMob->MPscale = Sql_GetFloatData(SqlHandle,54);

			PMob->PBattleAI = new CAIMobDummy(PMob);

			if (PMob->m_AllowRespawn = PMob->m_SpawnType == SPAWNTYPE_NORMAL)
			{
				PMob->PBattleAI->SetCurrentAction(ACTION_SPAWN);
			}

			// Check if we should be looking up scripts for this mob
			PMob->m_HasSpellScript = (uint8)Sql_GetIntData(SqlHandle,55);

			PMob->m_SpellListContainer = mobSpellList::GetMobSpellList(Sql_GetIntData(SqlHandle,56));

			PMob->m_Pool = Sql_GetUIntData(SqlHandle,59);

            // must be here first to define mobmods
			mobutils::InitializeMob(PMob, GetZone(ZoneID));

            GetZone(ZoneID)->InsertMOB(PMob);

            luautils::OnMobInitialize(PMob);

            PMob->saveModifiers();
            PMob->saveMobModifiers();
		}
	}

	// attach pets to mobs
	const int8* PetQuery =
		"SELECT zoneid, mob_mobid, pet_offset \
		FROM mob_pets \
		LEFT JOIN mob_spawn_points ON mob_pets.mob_mobid = mob_spawn_points.mobid \
		LEFT JOIN mob_groups ON mob_spawn_points.groupid = mob_groups.groupid;";

	ret = Sql_Query(SqlHandle, PetQuery);

	if( ret != SQL_ERROR && Sql_NumRows(SqlHandle) != 0)
	{
		while(Sql_NextRow(SqlHandle) == SQL_SUCCESS)
		{
        	uint16 ZoneID = (uint16)Sql_GetUIntData(SqlHandle, 0);
			uint32 masterid = (uint32)Sql_GetUIntData(SqlHandle,1);
			uint32 petid = masterid + (uint32)Sql_GetUIntData(SqlHandle,2);

			CMobEntity* PMaster = (CMobEntity*)GetZone(ZoneID)->GetEntity(masterid & 0x0FFF, TYPE_MOB);
			CMobEntity* PPet = (CMobEntity*)GetZone(ZoneID)->GetEntity(petid & 0x0FFF, TYPE_MOB);

			if(PMaster == NULL)
			{
				ShowError("zoneutils::loadMOBList PMaster is null. masterid: %d. Make sure x,y,z are not zeros, and that all entities are entered in the database!\n", masterid);
			}
			else if(PPet == NULL)
			{
				ShowError("zoneutils::loadMOBList PPet is null. petid: %d. Make sure x,y,z are not zeros!\n", petid);
			}
			else if(masterid == petid)
			{
				ShowError("zoneutils::loadMOBList Master and Pet are the same entity: %d\n", masterid);
			}
			else
			{
				// pet is always spawned by master
				PPet->m_AllowRespawn = false;
				PPet->m_SpawnType = SPAWNTYPE_SCRIPTED;
				PPet->PBattleAI->SetCurrentAction(ACTION_NONE);
				PPet->SetDespawnTimer(0);

				PMaster->PPet = PPet;
				PPet->PMaster = PMaster;
			}
		}
	}
}
示例#19
0
/*
**  Name:	void do_init(message *mp)
**  Function:	Checks for hardware presence.
**  		Provides initialization of hardware and data structures
*/
static void do_init(message * mp)
{
  int port;
  dpeth_t *dep;
  dp_conf_t *dcp;
  message reply_mess;

  port = mp->DL_PORT;
  if (port >= 0 && port < DE_PORT_NR) {

	dep = &de_table[port];
	dcp = &dp_conf[port];
	strcpy(dep->de_name, DevName);
	dep->de_name[4] = '0' + port;

	if (dep->de_mode == DEM_DISABLED) {

		update_conf(dep, dcp);	/* First time thru */
		if (dep->de_mode == DEM_ENABLED &&
		    !el1_probe(dep) &&	/* Probe for 3c501  */
		    !wdeth_probe(dep) &&	/* Probe for WD80x3 */
		    !ne_probe(dep) &&	/* Probe for NEx000 */
		    !el2_probe(dep) &&	/* Probe for 3c503  */
		    !el3_probe(dep)) {	/* Probe for 3c509  */
			printf("%s: warning no ethernet card found at 0x%04X\n",
			       dep->de_name, dep->de_base_port);
			dep->de_mode = DEM_DISABLED;
		}
	}

	/* 'de_mode' may change if probe routines fail, test again */
	switch (dep->de_mode) {

	    case DEM_DISABLED:
		/* Device is configured OFF or hardware probe failed */
		port = ENXIO;
		break;

	    case DEM_ENABLED:
		/* Device is present and probed */
		if (dep->de_flags == DEF_EMPTY) {
			/* These actions only the first time */
			do_first_init(dep, dcp);
			dep->de_flags |= DEF_ENABLED;
		}
		dep->de_flags &= NOT(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
		if (mp->DL_MODE & DL_PROMISC_REQ)
			dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
		if (mp->DL_MODE & DL_MULTI_REQ) dep->de_flags |= DEF_MULTI;
		if (mp->DL_MODE & DL_BROAD_REQ) dep->de_flags |= DEF_BROAD;
		(*dep->de_flagsf) (dep);
		dep->de_client = mp->m_source;
		break;

	    case DEM_SINK:
		/* Device not present (sink mode) */
		memset(dep->de_address.ea_addr, 0, sizeof(ether_addr_t));
		dp_confaddr(dep);	/* Station address from env. */
		break;

	    default:	break;
	}
	*(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;

  } else			/* Port number is out of range */
	port = ENXIO;

  reply_mess.m_type = DL_INIT_REPLY;
  reply_mess.m3_i1 = port;
  reply_mess.m3_i2 = DE_PORT_NR;
  DEBUG(printf("\t reply %d\n", reply_mess.m_type));
  if (send(mp->m_source, &reply_mess) != OK)	/* Can't send */
	panic(dep->de_name, SendErrMsg, mp->m_source);

  return;
}
示例#20
0
文件: xupl.c 项目: xupl/xupl
xupl* xupl_parse(xupl *xup) {

	xupl_*_ = (xupl_*) xup;
	FILE* in = _->in;
	off_t buffsize = _->buffsize;

	unsigned short bit = 0x0001;
	unsigned short WHITESPACE = bit;

	unsigned short DOUBLE_STRING = (bit <<= 1);
	unsigned short SINGLE_STRING = (bit <<= 1);
	unsigned short STRING = DOUBLE_STRING | SINGLE_STRING;

	unsigned short LINE_COMMENT = (bit <<= 1);
	unsigned short MULTI_COMMENT = (bit <<= 1);
	unsigned short COMMENT = LINE_COMMENT | MULTI_COMMENT;

	unsigned short _state = 0;

	const int default_tksize = 12;
	int tksize = default_tksize + 1;

	unsigned char *tk = NULL;
	int tkndx = 0;

	int chars_read;
	char* buf = malloc(buffsize + 1);

	xmlNodePtr xroot = NULL;
	xmlNodePtr xc = NULL;
	xmlAttrPtr xprop = NULL;

	const xmlChar* xuplAttr = (const xmlChar*) "data-xupl";
	const xmlChar* xuplClosed = (const xmlChar*) "closed";

	xmlDocPtr xdoc = xmlNewDoc((const unsigned char*) "1.1");
	//xmlNsPtr xuplNs = xmlNewGlobalNs(xdoc,"http://ns.xupl.org/1.1","xupl");

	while ((chars_read = fread(buf, 1, buffsize, in)) > 0) {

		for (int i = 0; i < chars_read; i++) {
			const char c = buf[i];

			switch (c) {

				case '\'':
				case '"':
					IF(COMMENT) break;

					IF(STR(c)) {
						DISABLE(STR(c));
					} else if (NOT(STRING)) {
						ALLOW(STR(c));
						break;
					}

				case '{':
				case '}':
				case ' ':
				case '\n':
				case '\r':
				case '\t':
				case '\f':
				case '\v':
				case ',':
				case '=':
				// Comment characters
				case '*':
				case '/':
				case '#':
				case '!':
					IF(STRING) break;

					switch (c) {
						case ',':
						case '{':
							xprop = NULL;
					}

					if (tk) {
						tk[tkndx] = 0;

						char p = 0;
						if (tkndx >= 1) p = tk[tkndx - 1];
						unsigned char* m = NULL;

						unsigned int tklen = tkndx + 1;
						unsigned char* t = tk;

						IF(COMMENT) {
							if ('\n' == c && IS(LINE_COMMENT)) {
								if (tkndx + 1 < tksize) {
									tk[tkndx++] = ' ';
									tk[tkndx] = 0;
								}
							} else if ('*' == p && '/' == c && IS(MULTI_COMMENT)) {
								tk[tkndx - 1] = 0;
							} else break;
							DISABLE(COMMENT);
							m = tk + 2;
						} else if ('/' == p && '*' == c) {
							ALLOW(MULTI_COMMENT);
							break;
						// Single-line comments can be #! #* #/ ##
						} else if ('#' == p && ('!' == c || '*' == c || '/' == c || '#' == c)) {
							ALLOW(LINE_COMMENT);
							break;
						// If these characters were in the token and not part of a comment,
						// then continue as if they are normal characters of a token.
						} else if ('!' == c || '/' == c || '*' == c || '#' == c) break;

						if (!xc) {
							if (m) {
								xroot = xmlNewDocComment(xdoc, m);
								xmlDocSetRootElement(xdoc, xroot);
							} else {
								xc = xmlNewNode(NULL, tk);
								xmlDocSetRootElement(xdoc, xc);
								if (!xroot) xroot = xc;
							}
						} else if (m) {
							xmlAddChild(xc, xmlNewComment(m));
						} else {
							char *attr = NULL;
							xmlAttrPtr closed = xmlHasProp(xc, xuplAttr);

							switch (tk[0]) {
								case '\'':
								case '"':
									t += 1;
									xmlAddChild(xc, xmlNewText(t));
									break;
									// TODO make this parameterized, characters and names.
								case '.': attr = "class";    break;
								case '#': attr = "id";       break;
								case '@': attr = "project";  break;
								case '/': attr = "href";     break;
								case '[': attr = "data";     break;
								case '~': attr = "duration"; break;
								case '=': attr = "location"; break;
								case '^': attr = "at";       break;
								case ':': attr = "type";     break;
								case '!': attr = "priority"; break;
								default:
								{
									regmatch_t pmatch[1];
									unsigned int isword = 0 == regexec(&re_word, (char*) tk, 1, pmatch, 0);
									if (closed) {
										if (isword) {
											xc = xmlNewChild(xc, NULL, tk, NULL);
										} else {
											xmlAddChild(xc, xmlNewText(tk));
										}
									} else {
										if (xprop) {
											xmlNewProp(xc, xprop->name, tk);
											xmlRemoveProp(xprop);
											xprop = NULL;
										} else if (isword) {
											xprop = xmlNewProp(xc, tk, (unsigned char*) "True");
										} else {
											xprop = xmlNewProp(xc, (unsigned char*) ".fake", tk);
										}
										switch (c) {
											case ',':
											case '{':
												xprop = NULL;
										}
									}
								}
									break;
							}

							if (attr) {
								if (closed) {
									xmlAddChild(xc, xmlNewText(t));
								} else {
									xmlNewProp(xc, (xmlChar*) attr, t);
								}
							}
						}

						free(tk);
						tk = NULL;
						if (tksize > default_tksize && tkndx < default_tksize) {
							tksize /= 2;
						}
						tkndx = 0;

						if (m) continue;
					}

				default:
					break;
			}

			switch (c) {
				case '{':
					xmlNewProp(xc, xuplAttr, xuplClosed);
					continue;
				case '}':
					if (xc) {
						xmlAttrPtr data = xmlHasProp(xc, xuplAttr);
						if (data) xmlRemoveProp(data);
						xc = xc->parent;
					}
					continue;
				default:
					break;
			}

			// Accumulate the tk.
			if (!tk || tkndx >= tksize) {
				// If the tk buffer is too small, double it.
				tk = realloc(tk, tksize *= 2);
			}
			tk[tkndx++] = c;
		}
示例#21
0
文件: null.c 项目: Ascronia/fieldtrip
void null_test (cholmod_common *cn)
{
    cholmod_sparse *A = NULL, *F = NULL, *C = NULL, *R = NULL, *B = NULL ;
    cholmod_factor *L = NULL ;
    cholmod_triplet *T = NULL ;
    cholmod_dense *X = NULL, *DeltaB = NULL, *S = NULL, *Y = NULL, *E = NULL ;
    void *p = NULL, *ii = NULL, *jj = NULL, *xx = NULL, *zz = NULL ;
    Int *Perm = NULL, *fset = NULL, *Parent = NULL, *Post = NULL,
	*RowCount = NULL, *ColCount = NULL, *First = NULL, *Level = NULL,
	*UserPerm = NULL, *colmark = NULL, *Constraints = NULL,
	*r = NULL, *c = NULL, *Set = NULL ;
    char *name = NULL ;
    double alpha [2], beta [2], bk [2], yk [2], rcond ;
    double dj = 1, nm = 0, tol = 0 ;
    int ok, stype = 0, xtype = 0, sorted = 0, packed = 0, nint = 0, update = 0,
	postorder = 0, pack = 0, values = 0, mode = 0, sys = 0, norm = 0,
	to_xtype = 0, to_ll = 0, to_super = 0, to_packed = 0, to_monotonic = 0,
	scale = 0, transpose = 0, option = 0, ordering = 0, prefer = 0,
	mtype = 0, asym = 0 ;
    UF_long lr = 0, k1 = 0, k2 = 0 ;
    size_t j = 0, need = 0, n = 0, mr = 0, nrow = 0, ncol = 0, iworksize = 0,
	newsize = 0, fsize = 0, d = 0, nzmax = 0, nnew = 0, size = 0,
	nold = 0, xwork = 0, kstart = 0, kend = 0, nr = 0, nc = 0, len = 0,
	krow = 0, k = 0 ;

#ifndef NPARTITION
    Int *Anw = NULL, *Aew = NULL, *Partition = NULL,
	*CParent = NULL, *Cmember = NULL ;
    Int compress = 0 ;
#endif

    /* ---------------------------------------------------------------------- */
    /* Core */
    /* ---------------------------------------------------------------------- */

    if (cn == NULL)
    {
	ok = CHOLMOD(start)(cn) ;				NOT (ok) ;
    }
    ok = CHOLMOD(finish)(cn) ;					NOT (ok) ;
    ok = CHOLMOD(defaults)(cn) ;				NOT (ok) ;
    mr = CHOLMOD(maxrank)(n, cn) ;				NOT (mr>0) ;
    ok = CHOLMOD(allocate_work)(nrow, iworksize, xwork, cn) ;	NOT (ok) ;
    ok = CHOLMOD(free_work)(cn) ;				NOT (ok) ;
    lr = CHOLMOD(clear_flag)(cn) ;				NOT (lr>=0) ;

    dj = CHOLMOD(dbound)(dj, cn) ;				OK (dj==0) ;				
    ok = CHOLMOD(error)(CHOLMOD_INVALID, __FILE__, __LINE__, "oops", cn) ;
								NOT (ok) ;
    A = CHOLMOD(allocate_sparse)(nrow, ncol, nzmax, sorted,
	packed, stype, xtype, cn) ;				NOP (A) ;
    ok = CHOLMOD(free_sparse)(&A, cn) ;				NOT (ok) ;
    ok = CHOLMOD(reallocate_sparse)(newsize, A, cn) ;		NOT (ok) ;
    lr = CHOLMOD(nnz)(A, cn) ;					NOT (lr>=0) ;
    A  = CHOLMOD(speye)(nrow, ncol, xtype, cn) ;		NOP (A) ;
    A  = CHOLMOD(spzeros)(nrow, ncol, 0, xtype, cn) ;		NOP (A) ;
    A  = CHOLMOD(ptranspose)(A, values, Perm, fset, fsize, cn);	NOP (A) ;
    A  = CHOLMOD(transpose)(A, values, cn) ;			NOP (A) ;
    ok = CHOLMOD(transpose_unsym)(A, values, Perm, fset, fsize, F, cn) ;
    NOT (ok) ;
    ok = CHOLMOD(transpose_sym)(A, values, Perm, F, cn) ;	NOT (ok) ;
    ok = CHOLMOD(sort)(A, cn) ;					NOT (ok) ;
    A  = CHOLMOD(copy_sparse)(A, cn) ;				NOP (A) ;
    C  = CHOLMOD(aat)(A, fset, fsize, mode, cn) ;		NOP (C) ;

    L  = CHOLMOD(allocate_factor)(n, cn) ;			NOP (L) ;
    ok = CHOLMOD(free_factor)(&L, cn) ;				NOT (ok) ;
    ok = CHOLMOD(reallocate_factor)(newsize, L, cn) ;		NOT (ok) ;
    ok = CHOLMOD(change_factor)(0, 0, 0, 0, 0, L, cn) ;		NOT (ok) ;
    ok = CHOLMOD(pack_factor)(L, cn) ;				NOT (ok) ;
    ok = CHOLMOD(change_factor)(to_xtype, to_ll, to_super,
	to_packed, to_monotonic, L, cn) ;			NOT (ok) ;
    ok = CHOLMOD(reallocate_column)(j, need, L, cn) ;		NOT (ok) ;
    A  = CHOLMOD(factor_to_sparse)(L, cn) ;			NOP (A) ;
    L  = CHOLMOD(copy_factor)(L, cn) ;				NOP (L) ;

    X  = CHOLMOD(allocate_dense)(nrow, ncol, d, xtype, cn) ;	NOP (X) ;
    X  = CHOLMOD(zeros)(nrow, ncol, xtype, cn) ;		NOP (X) ;
    X  = CHOLMOD(ones)(nrow, ncol, xtype, cn) ;			NOP (X) ;
    X  = CHOLMOD(eye)(nrow, ncol, xtype, cn) ;			NOP (X) ;
    ok = CHOLMOD(free_dense)(&X, cn) ;				NOT (ok) ;
    X  = CHOLMOD(sparse_to_dense)(A, cn) ;			NOP (X) ;
    A  = CHOLMOD(dense_to_sparse)(X, values, cn) ;		NOP (A) ;
    Y  = CHOLMOD(copy_dense)(X, cn) ;				NOP (X) ;
    ok = CHOLMOD(copy_dense2)(X, Y, cn) ;			NOT (ok) ;

    T  = CHOLMOD(allocate_triplet)(nrow, ncol, nzmax,
	    stype, xtype, cn) ;					NOP (T) ;
    ok = CHOLMOD(free_triplet)(&T, cn) ;			NOT (ok) ;
    T  = CHOLMOD(sparse_to_triplet)(A, cn) ;			NOP (T) ;
    A  = CHOLMOD(triplet_to_sparse)(T, 0, cn) ;			NOP (A) ;
    T  = CHOLMOD(copy_triplet)(T, cn) ;				NOP (T) ;
    ok = CHOLMOD(reallocate_triplet)(nzmax, T, cn) ;		NOT (ok) ;

    lr = CHOLMOD(postorder)(Parent, nrow, NULL, Post, cn) ;	NOT (lr>=0) ;
    p  = CHOLMOD(malloc)(n, size, cn) ;				NOP (p) ;
    p  = CHOLMOD(calloc)(n, size, cn) ;				NOP (p) ;
    p  = CHOLMOD(free)(n, size, p, cn) ;			NOP (p) ;
    p  = CHOLMOD(realloc)(nnew, size, p, &n, cn) ;		NOP (p) ;
    ok = CHOLMOD(realloc_multiple)(nnew, nint, xtype,
	    &ii, &jj, &xx, &zz, &nold, cn) ;			NOT (ok) ;

    C = CHOLMOD(band)(A, k1, k2, mode, cn) ;			NOP (C) ;
    ok = CHOLMOD(band_inplace)(k1, k2, mode, A, cn) ;		NOT (ok) ;

    ok = CHOLMOD(factor_xtype)(CHOLMOD_REAL, L, cn) ;		NOT (ok) ;
    ok = CHOLMOD(sparse_xtype)(CHOLMOD_REAL, A, cn) ;		NOT (ok) ;
    ok = CHOLMOD(dense_xtype)(CHOLMOD_REAL, X, cn) ;		NOT (ok) ;
    ok = CHOLMOD(triplet_xtype)(CHOLMOD_REAL, T, cn) ;		NOT (ok) ;

    /* ---------------------------------------------------------------------- */
    /* Cholesky */
    /* ---------------------------------------------------------------------- */

    L  = CHOLMOD(analyze)(A, cn) ;				NOP (L) ;    
    L  = CHOLMOD(analyze_p)(A, UserPerm, fset, fsize, cn) ;	NOP (L) ;    
    ok = CHOLMOD(factorize)(A, L, cn) ;				NOT (ok) ;
    ok = CHOLMOD(factorize_p)(A, beta, fset, fsize, L, cn) ;	NOT (ok) ;
    rcond = CHOLMOD(rcond)(L, cn) ;				NOT (rcond>=0) ;
    X = CHOLMOD(solve)(sys, L, Y, cn) ;				NOP (X) ;
    C = CHOLMOD(spsolve)(sys, L, B, cn) ;			NOP (C) ;
    ok = CHOLMOD(etree)(A, Parent, cn) ;			NOT (ok) ;
    ok = CHOLMOD(rowcolcounts)(A, fset, fsize, Parent, Post,
	RowCount, ColCount, First, Level, cn) ;			NOT (ok) ;
    ok = CHOLMOD(amd)(A, fset, fsize, Perm, cn) ;		NOT (ok) ;
    ok = CHOLMOD(camd)(A, fset, fsize, Constraints, Perm, cn) ;	NOT (ok) ;
    ok = CHOLMOD(colamd)(A, fset, fsize, postorder, Perm, cn) ;	NOT (ok) ;
    ok = CHOLMOD(rowfac)(A, F, beta, kstart, kend, L, cn) ;	NOT (ok) ;
    ok = CHOLMOD(row_subtree)(A, F, krow, Parent, R, cn) ;	NOT (ok) ;
    ok = CHOLMOD(row_lsubtree)(A, c, 0, krow, L, R, cn) ;	NOT (ok) ;
    ok = CHOLMOD(resymbol)(A, fset, fsize, pack, L, cn) ;	NOT (ok) ;
    ok = CHOLMOD(resymbol_noperm)(A, fset, fsize, pack, L, cn) ;NOT (ok) ;
    ok = CHOLMOD(analyze_ordering)(A, ordering, Perm, fset,
	fsize, Parent, Post, ColCount, First, Level, cn) ;	NOT (ok) ;

    /* ---------------------------------------------------------------------- */
    /* Modify */
    /* ---------------------------------------------------------------------- */

    ok = CHOLMOD(updown)(update, C, L, cn) ;			NOT (ok) ;
    ok = CHOLMOD(updown_solve)(update, C, L, X, DeltaB, cn) ;	NOT (ok) ;
    ok = CHOLMOD(updown_mark)(update, C, colmark, L, X, DeltaB,
	    cn) ;					NOT (ok) ;
    ok = CHOLMOD(rowadd)(k, R, L, cn) ;				NOT (ok) ;
    ok = CHOLMOD(rowadd_solve)(k, R, bk, L, X, DeltaB, cn) ;	NOT (ok) ;
    ok = CHOLMOD(rowadd_mark)(k, R, bk, colmark, L, X, DeltaB,
	    cn) ;					NOT (ok) ;
    ok = CHOLMOD(rowdel)(k, R, L, cn) ;				NOT (ok) ;
    ok = CHOLMOD(rowdel_solve)(k, R, yk, L, X, DeltaB, cn) ;	NOT (ok) ;
    ok = CHOLMOD(rowdel_mark)(k, R, yk, colmark, L, X, DeltaB,
	    cn) ;					NOT (ok) ;

    /* ---------------------------------------------------------------------- */
    /* MatrixOps */
    /* ---------------------------------------------------------------------- */

    C = CHOLMOD(add)(A, B, alpha, beta, values, sorted, cn) ;	NOP (C) ;

    C = CHOLMOD(copy)(A, stype, mode, cn) ;			NOP (C) ;
    ok = CHOLMOD(drop)(tol, A, cn) ;				NOT (ok) ;
    nm = CHOLMOD(norm_dense)(X, norm, cn) ;			NOT (nm>=0) ;
    nm = CHOLMOD(norm_sparse)(A, norm, cn) ;			NOT (nm>=0) ;
    C = CHOLMOD(horzcat)(A, B, values, cn) ;			NOP (C) ;
    ok = CHOLMOD(scale)(S, scale, A, cn) ;			NOT (ok) ;
    ok = CHOLMOD(sdmult)(A, transpose, alpha, beta, X, Y, cn) ;	NOT (ok) ;
    C = CHOLMOD(ssmult)(A, B, stype, values, sorted, cn) ;	NOP (C) ;
    C = CHOLMOD(submatrix)(A, r, nr, c, nc, values, sorted,
	    cn) ;						NOP (C) ;
    C = CHOLMOD(vertcat)(A, B, values, cn) ;			NOP (C) ;
    asym = CHOLMOD(symmetry)(A, option, NULL, NULL, NULL, NULL,
	    cn) ;						NOT(asym>=0) ;

    /* ---------------------------------------------------------------------- */
    /* Supernodal */
    /* ---------------------------------------------------------------------- */

    ok = CHOLMOD(super_symbolic)(A, F, Parent, L, cn) ;	NOT (ok) ;
    ok = CHOLMOD(super_numeric)(A, F, beta, L, cn) ;		NOT (ok) ;
    ok = CHOLMOD(super_lsolve)(L, X, E, cn) ;			NOT (ok) ;
    ok = CHOLMOD(super_ltsolve)(L, X, E, cn) ;			NOT (ok) ;

    /* ---------------------------------------------------------------------- */
    /* Check */
    /* ---------------------------------------------------------------------- */

    ok = CHOLMOD(check_common)(cn) ;				NOT (ok) ;
    ok = CHOLMOD(print_common)(name, cn) ;			NOT (ok) ;

    ok = CHOLMOD(check_sparse)(A, cn) ;				NOT (ok) ;
    ok = CHOLMOD(print_sparse)(A, name, cn) ;			NOT (ok) ;
    ok = CHOLMOD(check_dense)(X, cn) ;				NOT (ok) ;
    ok = CHOLMOD(print_dense)(X, name, cn) ;			NOT (ok) ;
    ok = CHOLMOD(check_factor)(L, cn) ;				NOT (ok) ;
    ok = CHOLMOD(print_factor)(L, name, cn) ;			NOT (ok) ;
    ok = CHOLMOD(check_triplet)(T, cn) ;			NOT (ok) ;
    ok = CHOLMOD(print_triplet)(T, name, cn) ;			NOT (ok) ;
    ok = CHOLMOD(check_subset)(Set, len, n, cn) ;		NOT (ok) ;
    ok = CHOLMOD(print_subset)(Set, len, n, name, cn) ;		NOT (ok) ;
    ok = CHOLMOD(check_perm)(Perm, n, n, cn) ;			NOT (ok) ;
    ok = CHOLMOD(print_perm)(Perm, n, n, name, cn) ;		NOT (ok) ;
    ok = CHOLMOD(check_parent)(Parent, n, cn) ;			NOT (ok) ;
    ok = CHOLMOD(print_parent)(Parent, n, name, cn) ;		NOT (ok) ;

    A = CHOLMOD(read_sparse)(NULL, cn) ;			NOP (A) ;
    p = CHOLMOD(read_matrix)(NULL, prefer, &mtype, cn) ;	NOP (p) ;
    X = CHOLMOD(read_dense)(NULL, cn) ;				NOP (X) ;
    T = CHOLMOD(read_triplet)(NULL, cn) ;			NOP (T) ;

    asym = CHOLMOD(write_dense) (NULL, NULL, NULL, cn) ;	NOT (asym>=0) ;
    asym = CHOLMOD(write_dense) ((FILE *) 1, NULL, NULL, cn) ;	NOT (asym>=0) ;

    asym = CHOLMOD(write_sparse)(NULL, NULL, NULL, NULL, cn) ;	NOT (asym>=0) ;
    asym = CHOLMOD(write_sparse)((FILE *) 1, NULL, NULL, NULL,
	    cn) ;						NOT (asym>=0) ;

    /* ---------------------------------------------------------------------- */
    /* Partition */
    /* ---------------------------------------------------------------------- */

#ifndef NPARTITION
    lr = CHOLMOD(nested_dissection)(A, fset, fsize, Perm,
	    CParent, Cmember, cn) ;				NOT (lr >= 0) ;
    lr = CHOLMOD(collapse_septree) (n, n, 1., 4,
	    CParent, Cmember, cn) ;				NOT (lr >= 0) ;
    ok = CHOLMOD(metis)(A, fset, fsize, postorder, Perm, cn) ;	NOT (ok) ;
    ok = CHOLMOD(ccolamd)(A, fset, fsize, Cmember, Perm, cn) ;	NOT (ok) ;
    ok = CHOLMOD(csymamd)(A, Cmember, Perm, cn) ;		NOT (ok) ;
    lr = CHOLMOD(bisect)(A, fset, fsize, compress,
	    Partition, cn) ;					NOT (lr >= 0) ;
    lr = CHOLMOD(metis_bisector)(A, Anw, Aew, Partition, cn) ;	NOT (lr >= 0) ;
#endif

}
示例#22
0
文件: cctest.c 项目: Al-th/matlab
void cctest (cholmod_sparse *A)
{

    double knobs [CCOLAMD_KNOBS], knobs2 [CCOLAMD_KNOBS] ;
    Int *P, *Cmember, *Cp, *Ci, *Front_npivcol, *Front_nrows, *Front_ncols,
	*Front_parent, *Front_cols, *InFront, *Si, *Sp ;
    cholmod_sparse *C, *A2, *B, *S ;
    Int nrow, ncol, alen, ok, stats [CCOLAMD_STATS], csets, i, nfr, c, p ;
    size_t s ;

    /* ---------------------------------------------------------------------- */
    /* get inputs */
    /* ---------------------------------------------------------------------- */

    my_srand (42) ;						/* RAND reset */

    printf ("\nCCOLAMD test\n") ;

    if (A == NULL)
    {
	return ;
    }

    if (A->stype)
    {
	A2 = CHOLMOD(copy) (A, 0, 0, cm) ;
	B = A2 ;
    }
    else
    {
	A2 = NULL ;
	B = A ;
    }
    S = CHOLMOD(copy_sparse) (A, cm) ;

    nrow = B->nrow ;
    ncol = B->ncol ;
    Si = S->i ;
    Sp = S->p ;

    /* ---------------------------------------------------------------------- */
    /* allocate workspace and Cmember for ccolamd */
    /* ---------------------------------------------------------------------- */

    P = CHOLMOD(malloc) (nrow+1, sizeof (Int), cm) ;
    Cmember = CHOLMOD(malloc) (nrow, sizeof (Int), cm) ;
    Front_npivcol = CHOLMOD(malloc) (nrow+1, sizeof (Int), cm) ;
    Front_nrows   = CHOLMOD(malloc) (nrow+1, sizeof (Int), cm) ;
    Front_ncols   = CHOLMOD(malloc) (nrow+1, sizeof (Int), cm) ;
    Front_parent  = CHOLMOD(malloc) (nrow+1, sizeof (Int), cm) ;
    Front_cols    = CHOLMOD(malloc) (nrow+1, sizeof (Int), cm) ;
    InFront       = CHOLMOD(malloc) (ncol, sizeof (Int), cm) ;

    csets = MIN (6, nrow) ;
    for (i = 0 ; i < nrow ; i++)
    {
	Cmember [i] = nrand (csets) ;
    }

    CCOLAMD_set_defaults (knobs) ;
    CCOLAMD_set_defaults (knobs2) ;
    CCOLAMD_set_defaults (NULL) ;
    CCOLAMD_report (NULL) ;
    CSYMAMD_report (NULL) ;

    alen = CCOLAMD_recommended (B->nzmax, ncol, nrow) ;
    C = CHOLMOD(allocate_sparse) (ncol, nrow, alen, TRUE, TRUE, 0,
	    CHOLMOD_PATTERN, cm) ;
    Cp = C->p ;
    Ci = C->i ;

    /* ---------------------------------------------------------------------- */
    /* order with ccolamd */
    /* ---------------------------------------------------------------------- */

    ok = CHOLMOD(transpose_unsym) (B, 0, NULL, NULL, 0, C, cm) ; OK (ok) ;
    CHOLMOD(print_sparse) (C, "C for ccolamd", cm) ;
    ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, NULL, stats, Cmember) ;
    CCOLAMD_report (stats) ;
    OK (ok) ;
    ok = stats [CCOLAMD_STATUS] ;
    ok = (ok == CCOLAMD_OK || ok == CCOLAMD_OK_BUT_JUMBLED) ;
    OK (ok) ;

    /* permutation returned in C->p, if the ordering succeeded */
    /* make sure P obeys the constraints */
    OK (check_constraints (Cp, Cmember, nrow)) ;

    /* ---------------------------------------------------------------------- */
    /* order with ccolamd2 */
    /* ---------------------------------------------------------------------- */

    ok = CHOLMOD(transpose_unsym) (B, 0, NULL, NULL, 0, C, cm) ; OK (ok) ;
    ok = CCOLAMD_2 (ncol, nrow, alen, Ci, Cp, NULL, stats,
	    Front_npivcol, Front_nrows, Front_ncols, Front_parent,
	    Front_cols, &nfr, InFront, Cmember) ;
    CCOLAMD_report (stats) ;
    OK (check_constraints (Cp, Cmember, nrow)) ;

    /* ---------------------------------------------------------------------- */
    /* with a small dense-row threshold */
    /* ---------------------------------------------------------------------- */

    knobs2 [CCOLAMD_DENSE_ROW] = 0 ;
    ok = CHOLMOD(transpose_unsym) (B, 0, NULL, NULL, 0, C, cm) ; OK (ok) ;
    ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, knobs2, stats, Cmember) ;
    CCOLAMD_report (stats) ;

    knobs2 [CCOLAMD_DENSE_ROW] = 0.625 ;
    knobs2 [CCOLAMD_DENSE_COL] = 0 ;
    ok = CHOLMOD(transpose_unsym) (B, 0, NULL, NULL, 0, C, cm) ; OK (ok) ;
    ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, knobs2, stats, Cmember) ;
    CCOLAMD_report (stats) ;

    knobs2 [CCOLAMD_DENSE_ROW] = 0.625 ;
    knobs2 [CCOLAMD_DENSE_COL] = -1 ;
    ok = CHOLMOD(transpose_unsym) (B, 0, NULL, NULL, 0, C, cm) ; OK (ok) ;
    ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, knobs2, stats, Cmember) ;
    CCOLAMD_report (stats) ;

    knobs2 [CCOLAMD_DENSE_COL] = 0 ;

    /* ---------------------------------------------------------------------- */
    /* duplicate entries */
    /* ---------------------------------------------------------------------- */

    if (ncol > 2 && nrow > 2)
    {
	ok = CHOLMOD(transpose_unsym) (B, 0, NULL, NULL, 0, C, cm) ;
	OK (ok) ;
	if (Cp [1] - Cp [0] > 2)
	{
	    Ci [0] = Ci [1] ;
	}
	ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, knobs2, stats, Cmember) ;
	CCOLAMD_report (stats) ;
	OK (CHOLMOD(print_perm) (Cp, nrow, nrow, "ccolamd perm", cm)) ;
    }

    /* ---------------------------------------------------------------------- */
    /* csymamd */
    /* ---------------------------------------------------------------------- */

    if (nrow == ncol)
    {
	Int n = nrow ;

	ok = CSYMAMD_MAIN (n, Si, Sp, P, NULL, stats,
		cm->calloc_memory, cm->free_memory, Cmember, A->stype) ;
	OK (ok) ;
	OK (check_constraints (P, Cmember, n)) ;
	CSYMAMD_report (stats) ;

	/* ------------------------------------------------------------------ */
	/* csymamd errors */
	/* ------------------------------------------------------------------ */

	ok = CSYMAMD_MAIN (n, Si, Sp, P, NULL, NULL, cm->calloc_memory,
		cm->free_memory, Cmember, A->stype) ;		       NOT (ok);

	ok = CSYMAMD_MAIN (n, NULL, Sp, P, NULL, stats, cm->calloc_memory,
		cm->free_memory, Cmember, A->stype) ;		       NOT (ok);
	CSYMAMD_report (stats) ;

	ok = CSYMAMD_MAIN (n, Si, NULL, P, NULL, stats, cm->calloc_memory,
		cm->free_memory, Cmember, A->stype) ;		       NOT (ok);
	CSYMAMD_report (stats) ;

	ok = CSYMAMD_MAIN (-1, Si, Sp, P, NULL, stats, cm->calloc_memory,
		cm->free_memory, Cmember, A->stype) ;		       NOT (ok);
	CSYMAMD_report (stats) ;

	p = Sp [n] ;
	Sp [n] = -1 ;
	ok = CSYMAMD_MAIN (n, Si, Sp, P, NULL, stats, cm->calloc_memory,
		cm->free_memory, Cmember, A->stype) ;		       NOT (ok);
	CSYMAMD_report (stats) ;
	Sp [n] = p ;

	Sp [0] = -1 ;
	ok = CSYMAMD_MAIN (n, Si, Sp, P, NULL, stats, cm->calloc_memory,
		cm->free_memory, Cmember, A->stype) ;		       NOT (ok);
	CSYMAMD_report (stats) ;
	Sp [0] = 0 ;

	if (n > 2 && Sp [n] > 3)
	{
	    p = Sp [1] ;
	    Sp [1] = -1 ;
	    ok = CSYMAMD_MAIN (n, Si, Sp, P, NULL, stats, cm->calloc_memory,
		    cm->free_memory, Cmember, A->stype) ;	       NOT (ok);
	    CSYMAMD_report (stats) ;
	    Sp [1] = p ;

	    i = Si [0] ;
	    Si [0] = -1 ;
	    ok = CSYMAMD_MAIN (n, Si, Sp, P, NULL, stats, cm->calloc_memory,
		    cm->free_memory, Cmember, A->stype) ;	       NOT (ok);
	    CSYMAMD_report (stats) ;
	    Si [0] = i ;

	    /* ok, but jumbled */
	    i = Si [0] ;
	    Si [0] = Si [1] ;
	    Si [1] = i ;
	    ok = CSYMAMD_MAIN (n, Si, Sp, P, NULL, stats, cm->calloc_memory,
		    cm->free_memory, Cmember, A->stype) ;	       OK (ok);
	    CSYMAMD_report (stats) ;
	    i = Si [0] ;
	    Si [0] = Si [1] ;
	    Si [1] = i ;

	    test_memory_handler ( ) ;
	    ok = CSYMAMD_MAIN (n, Si, Sp, P, NULL, stats, cm->calloc_memory,
		    cm->free_memory, Cmember, A->stype) ;	       NOT(ok);
	    CSYMAMD_report (stats) ;
	    normal_memory_handler ( ) ;
	}
    }

    /* ---------------------------------------------------------------------- */
    /* error tests */
    /* ---------------------------------------------------------------------- */

    ok = CHOLMOD(transpose_unsym) (B, 0, NULL, NULL, 0, C, cm) ;   OK (ok) ;
    ok = CCOLAMD_MAIN (ncol, nrow, 0, Ci, Cp, knobs, stats, Cmember) ;     NOT (ok) ;
    CCOLAMD_report (stats) ;

    ok = CCOLAMD_MAIN (ncol, nrow, alen, NULL, Cp, knobs, stats, Cmember); NOT (ok) ;
    CCOLAMD_report (stats) ;

    ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, NULL, knobs, stats, Cmember); NOT (ok) ;
    CCOLAMD_report (stats) ;

    ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, knobs, NULL, Cmember) ;   NOT (ok) ;
    CCOLAMD_report (stats) ;

    ok = CCOLAMD_MAIN (-1, nrow, alen, Ci, Cp, knobs, stats, Cmember) ;    NOT (ok) ;
    CCOLAMD_report (stats) ;

    ok = CCOLAMD_MAIN (ncol, -1, alen, Ci, Cp, knobs, stats, Cmember) ;    NOT (ok) ;
    CCOLAMD_report (stats) ;

    ok = CHOLMOD(transpose_unsym) (B, 0, NULL, NULL, 0, C, cm) ; OK (ok) ;
    Cp [nrow] = -1 ;
    ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, knobs, stats, Cmember) ;  NOT (ok) ;
    CCOLAMD_report (stats) ;

    Cp [0] = 1 ;
    ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, knobs, stats, Cmember) ;  NOT (ok) ;
    CCOLAMD_report (stats) ;

    ok = CHOLMOD(transpose_unsym) (B, 0, NULL, NULL, 0, C, cm) ;   OK (ok) ;

    if (nrow > 0 && alen > 0 && Cp [1] > 0)
    {
	c = Cmember [0] ;
	Cmember [0] = -1 ;
	ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, knobs, stats, Cmember) ;NOT(ok);
	CCOLAMD_report (stats) ;
	Cmember [0] = c ;

	p = Cp [1] ;
	Cp [1] = -1 ;
	ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, knobs, stats, Cmember) ;NOT(ok);
	CCOLAMD_report (stats) ;
	Cp [1] = p ;

	i = Ci [0] ;
	Ci [0] = -1 ;
	ok = CCOLAMD_MAIN (ncol, nrow, alen, Ci, Cp, knobs, stats, Cmember) ;NOT(ok);
	CCOLAMD_report (stats) ;
	Ci [0] = i ;
    }

    s = CCOLAMD_recommended (-1, 0, 0) ;
    OK (s == 0) ;

    /* ---------------------------------------------------------------------- */
    /* free workspace */
    /* ---------------------------------------------------------------------- */

    CHOLMOD(free) (nrow+1, sizeof (Int), Front_npivcol, cm) ;
    CHOLMOD(free) (nrow+1, sizeof (Int), Front_nrows, cm) ;
    CHOLMOD(free) (nrow+1, sizeof (Int), Front_ncols, cm) ;
    CHOLMOD(free) (nrow+1, sizeof (Int), Front_parent, cm) ;
    CHOLMOD(free) (nrow+1, sizeof (Int), Front_cols, cm) ;
    CHOLMOD(free) (nrow+1, sizeof (Int), P, cm) ;
    CHOLMOD(free) (nrow, sizeof (Int), Cmember, cm) ;
    CHOLMOD(free) (ncol, sizeof (Int), InFront, cm) ;

    CHOLMOD(free_sparse) (&S, cm) ;
    CHOLMOD(free_sparse) (&A2, cm) ;
    CHOLMOD(free_sparse) (&C, cm) ;
    cm->print = 1 ;
}
示例#23
0
int    GLUI_EditText::key_handler( unsigned char key,int modifiers )
{
  int i, regular_key;
  /* int has_selection;              */

  if ( NOT glui )
    return false;

  if ( debug )
    dump( stdout, "-> KEY HANDLER" );

  regular_key = false;
  bool ctrl_down = (modifiers & GLUT_ACTIVE_CTRL)!=0;
  /*  has_selection = (sel_start != sel_end);              */

  if ( key == CTRL('m') ) {           /* RETURN */
    /*    glui->deactivate_current_control();              */
    deactivate();  /** Force callbacks, etc **/
    activate(GLUI_ACTIVATE_TAB);     /** Reselect all text **/
    redraw();
    return true;
  }
  else if ( key  == CTRL('[')) {         /* ESCAPE */
    glui->deactivate_current_control();
    return true;
  }
  else if ( (key == 127 AND !ctrl_down) OR  /* FORWARD DELETE */
            ( key == CTRL('d') AND modifiers == GLUT_ACTIVE_CTRL) ) 
  {
    if ( sel_start == sel_end ) {   /* no selection */
      if ( insertion_pt < (int)text.length() ) {
        /*** See if we're deleting a period in a float data-type box ***/
        if ( ((data_type == GLUI_EDITTEXT_FLOAT) OR (data_type == GLUI_EDITTEXT_DOUBLE)) AND text[insertion_pt]=='.' )
          num_periods--;

        /*** Shift over string first ***/
        text.erase(insertion_pt,1);
      }
    }
    else {                         /* There is a selection */
      clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end ));
      insertion_pt = MIN(sel_start,sel_end);
      sel_start = sel_end = insertion_pt;
    }
  }
  else if ( ((key == 127) AND ctrl_down) OR   // Delete word forward
            ((key == 'd') AND (modifiers == GLUT_ACTIVE_ALT)) )
  {
    if ( sel_start == sel_end ) {   /* no selection */
      sel_start = insertion_pt;
      sel_end = find_word_break( insertion_pt, +1 );
    }

    clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end ));
    insertion_pt = MIN(sel_start,sel_end);
    sel_start = sel_end = insertion_pt;
  }
  else if ( key == CTRL('h') ) {       /* BACKSPACE */
    if ( sel_start == sel_end ) {   /* no selection */
      if ( insertion_pt > 0 ) {
        /*** See if we're deleting a period in a float data-type box ***/
        if ( ((data_type == GLUI_EDITTEXT_FLOAT) OR (data_type == GLUI_EDITTEXT_DOUBLE)) AND text[insertion_pt-1]=='.' )
          num_periods--;

        /*** Shift over string first ***/
        insertion_pt--;
        text.erase(insertion_pt,1);
      }
    }
    else {                         /* There is a selection */
      clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end ));
      insertion_pt = MIN(sel_start,sel_end);
      sel_start = sel_end = insertion_pt;
    }
  }
  else if ( modifiers == GLUT_ACTIVE_CTRL )  /* CTRL ONLY */ 
  {
    /* Ctrl-key bindings */
    if ( key == CTRL('a') ) {
      return special_handler( GLUT_KEY_HOME, 0 );
    }
    else if ( key == CTRL('e') ) {
      return special_handler( GLUT_KEY_END, 0 );
    }
    else if ( key == CTRL('b') ) {
      return special_handler( GLUT_KEY_LEFT, 0 );
    }
    else if ( key == CTRL('f') ) {
      return special_handler( GLUT_KEY_RIGHT, 0 );
    }
    else if ( key == CTRL('p') ) {
      return special_handler( GLUT_KEY_UP, 0 );
    }
    else if ( key == CTRL('n') ) {
      return special_handler( GLUT_KEY_DOWN, 0 );
    }
    else if ( key == CTRL('u') ) { /* ERASE LINE */
      insertion_pt = 0;  
      text.erase(0,text.length());
      sel_start = sel_end = 0;
    }
    else if ( key == CTRL('k') ) { /* KILL TO END OF LINE */
      sel_start = sel_end = insertion_pt;
      text.erase(insertion_pt,GLUI_String::npos);
    }
  }
  else if ( modifiers == GLUT_ACTIVE_ALT ) /* ALT ONLY */
  {
    if ( key == 'b' ) { // Backward word
      return special_handler ( GLUT_KEY_LEFT, GLUT_ACTIVE_CTRL );
    }
    if ( key == 'f' ) { // Forward word
      return special_handler ( GLUT_KEY_RIGHT, GLUT_ACTIVE_CTRL );
    }
  }
  else if ( (modifiers & GLUT_ACTIVE_CTRL) OR
            (modifiers & GLUT_ACTIVE_ALT) ) 
  {
    /** ignore other keys with modifiers */
    return true;
  }
  else { /* Regular key */    
    regular_key = true;

    /** Check if we only accept numbers **/
    if ((data_type == GLUI_EDITTEXT_FLOAT ) OR (data_type == GLUI_EDITTEXT_DOUBLE)) {
      if ( (key < '0' OR key > '9') AND key != '.' AND key != '-' )
        return true;

      if ( key == '-' ) { /* User typed a '-' */

        /* If user has first character selected, then '-' is allowed */
        if ( NOT ( MIN(sel_start,sel_end) == 0 AND
                   MAX(sel_start,sel_end) > 0 ) ) {

          /* User does not have 1st char selected */
          if (insertion_pt != 0 OR text[0] == '-' ) {
            return true; /* Can only place negative at beginning of text,
                            and only one of them */
          }
        }
      }

      if ( key == '.' ) {
        /*printf( "PERIOD: %d\n", num_periods );              */

        if ( num_periods > 0 ) {
          /** We're trying to type a period, but the text already contains
          a period.  Check whether the period is contained within
          is current selection (thus it will be safely replaced) **/

          int period_found = false; 
          if ( sel_start != sel_end ) {
            for( i=MIN(sel_end,sel_start); i<MAX(sel_start,sel_end); i++ ) {
              /*  printf( "%c ", text[i] );              */
              if ( text[i] == '.' ) {
                period_found = true;
                break;
              }
            }
          }

          /* printf( "found: %d    num: %d\n", period_found, num_periods );              */

          if ( NOT period_found )
            return true;
        }
      }
    } 
    else if (data_type == GLUI_EDITTEXT_INT)	
    {
      if ( (key < '0' OR key > '9') AND key != '-' )
        return true;

      if ( key == '-' ) { /* User typed a '-' */

        /* If user has first character selected, then '-' is allowed */
        if ( NOT ( MIN(sel_start,sel_end) == 0 AND
          MAX(sel_start,sel_end) > 0 ) ) {

            /* User does not have 1st char selected */
            if (insertion_pt != 0 OR text[0] == '-' ) {
              return true; /* Can only place negative at beginning of text,
                           and only one of them */
            }
          }
      }
    }

    /** This is just to get rid of warnings - the flag regular_key is 
      set if the key was not a backspace, return, whatever.  But I
      believe if we're here, we know it was a regular key anyway */
    if ( regular_key ) {
    }

    /**** If there's a current selection, erase it ******/
    if ( sel_start != sel_end ) {
      clear_substring( MIN(sel_start,sel_end), MAX(sel_start,sel_end ));
      insertion_pt = MIN(sel_start,sel_end);
      sel_start = sel_end = insertion_pt;
    }

    /******** We insert the character into the string ***/

    text.insert(insertion_pt,1,key);

    /******** Move the insertion point and substring_end one over ******/
    insertion_pt++;
    substring_end++;

    sel_start = sel_end = insertion_pt;
  }

  /******** Now redraw text ***********/
  /* Hack to prevent text box from being cleared first **/  
  /**  int substring_change =  update_substring_bounds();
  draw_text_only = 
  (NOT substring_change AND NOT has_selection AND regular_key ); 
  */

  draw_text_only = false;  /** Well, hack is not yet working **/
  update_and_draw_text();
  draw_text_only = false;


  if ( debug )
    dump( stdout, "<- KEY HANDLER" );

  /*** Now look to see if this string has a period ***/
  num_periods = 0;
  for( i=0; i<(int)text.length(); i++ )
    if ( text[i] == '.' )
      num_periods++;

  return true;
}
示例#24
0
int agisundirected(Agraph_t * g)
{
    return NOT(agisdirected(g));
}
示例#25
0
short MergeUnion::codeGen(Generator * generator)
{
  ExpGenerator * exp_gen = generator->getExpGenerator();
  Space * space = generator->getSpace();
  
  MapTable * my_map_table = generator->appendAtEnd();

  ////////////////////////////////////////////////////////////////////////////
  //
  // Layout at this node:
  //
  // |------------------------------------------------------------------------|
  // | input data  |  Unioned data | left child's data | right child's data   |
  // | ( I tupps ) |  ( 1 tupp )   | ( L tupps )       |  ( R tupp )          |
  // |------------------------------------------------------------------------|
  // <-- returned row to parent --->
  // <------------ returned row from left child ------->
  // <-------------------- returned row from right child --------------------->
  //
  // input data:        the atp input to this node by its parent. 
  // unioned data:      tupp where the unioned result is moved
  // left child data:   tupps appended by the left child
  // right child data:  tupps appended by right child
  //
  // Input to left child:    I + 1 tupps
  // Input to right child:   I + 1 + L tupps
  //
  // Tupps returned from left and right child are only used to create the
  // unioned data. They are not returned to parent.
  //
  ////////////////////////////////////////////////////////////////////////////

  ex_cri_desc * given_desc
    = generator->getCriDesc(Generator::DOWN);

  ex_cri_desc * returned_desc = NULL;
  if(child(0) || child(1))
    returned_desc = new(space) ex_cri_desc(given_desc->noTuples() + 1, space);
  else
    returned_desc = given_desc;

  // expressions to move the left and right child's output to the
  // unioned row.
  ex_expr * left_expr = 0;
  ex_expr * right_expr = 0;

  // expression to compare left and right child's output to
  // evaluate merge union.
  ex_expr * merge_expr = 0;

  // Expression to conditionally execute the left or right child.
  ex_expr *cond_expr = NULL;

  // Expression to handle triggered action excpetion 
  ex_expr *trig_expr = NULL;

  // It is OK for neither child to exist when generating a merge union TDB
  // for index maintenenace. The children are filled in at build time.
  //
  GenAssert((child(0) AND child(1)) OR (NOT child(0) AND NOT (child(1))),
	    "MergeUnion -- missing one child");
  ComTdb * left_child_tdb = NULL;
  ComTdb * right_child_tdb = NULL;
  ExplainTuple *leftExplainTuple = NULL;
  ExplainTuple *rightExplainTuple = NULL;
  NABoolean afterUpdate = FALSE;
  NABoolean rowsFromLeft = TRUE;
  NABoolean rowsFromRight = TRUE;

  if(child(0) && child(1)) {
 
    // if an update operation is found  before the execution of the
  // IF statement, set afterUpdate to 1 indicating that an update operation
  // was performed before the execution of the IF statement.  Which 
  // is used at runtime to decide whether to set rollbackTransaction in the 
  // diagsArea

 
  if (generator->updateWithinCS() && getUnionForIF()) {
    afterUpdate = TRUE;
  }

    // generate the left child
    generator->setCriDesc(returned_desc, Generator::DOWN);
    child(0)->codeGen(generator);
    left_child_tdb = (ComTdb *)(generator->getGenObj());
    leftExplainTuple = generator->getExplainTuple();

  // MVs --
  // If the left child does not have any outputs, don't expect any rows.
  if (child(0)->getGroupAttr()->getCharacteristicOutputs().isEmpty())
    rowsFromLeft = FALSE;

  // if an update operation is found in the left subtree of this Union then
  // set rowsFromLeft to 0 which is passed on to execution tree indicating
  // that this Union node is not  expecting rows from the left child, then
  // foundAnUpdate_ is reset so it can be reused while doing codGen() on 
  // the right sub tree

    if (getUnionForIF()) {
      if (! getCondEmptyIfThen()) {
        if (generator->foundAnUpdate())   {
          rowsFromLeft = FALSE;
          generator->setFoundAnUpdate(FALSE);
        } 
      } 
      else {
        rowsFromLeft = FALSE;  
      }
    }
    
    // descriptor returned by left child is given to right child as input.
    generator->setCriDesc(generator->getCriDesc(Generator::UP), 
			  Generator::DOWN);
    child(1)->codeGen(generator);
    right_child_tdb = (ComTdb *)(generator->getGenObj());
    rightExplainTuple = generator->getExplainTuple();

  // MVs
  // If the right child does not have any outputs, don't expect any rows.
  if (child(1)->getGroupAttr()->getCharacteristicOutputs().isEmpty())
    rowsFromRight = FALSE;

  // if an update operation is found in the right subtree of this CS then
  // set rowsFromRight to 0 which is passed on to execution tree indicating
  // that this CS node is not  expecting rows from the right child, then
  // foundAnUpdate_ is reset so it can be reused while doing codGen() on
  // the left or right child of another CS node


  if (getUnionForIF()) {
    if (! getCondEmptyIfElse()) {
      if (generator->foundAnUpdate())  {
        rowsFromRight = FALSE;
      } 
    } 
    else {
      rowsFromRight = FALSE;  
    }


    // we cannot always expect a row from a conditional operator. If it is an
    // IF statement without an ELSE and the condition fails then we do not get
    // any rows back. So we allow a conditional union operator to handle all
    // errors below it and for the purposes of 8015 error / 8014 warning
    // treat it as an update node. In this way the nodes above it do not expect
    // any row from this child and do not raise an error if no row is returned.
    // 8014/8015 type errors within this IF statement are handled as in any
    // regular CS.

    generator->setFoundAnUpdate(TRUE);
  }

  }

  // Create the unioned row. 
  // colMapTable() is a list of ValueIdUnion nodes where each node points to
  // the corresponding left and the right output entries.
  // Generate expressions to move the left and right child's output to
  // the unioned row. 
  ValueIdList left_val_id_list;
  ValueIdList right_val_id_list;
  CollIndex   i;                                      

  for (i = 0; i < colMapTable().entries(); i++)       
    {
      ValueIdUnion * vidu_node = (ValueIdUnion *)(((colMapTable()[i]).getValueDesc())->getItemExpr());

      Cast * cnode;
      if (vidu_node->getResult().getType().getTypeQualifier() != NA_ROWSET_TYPE) {
        // move left child's output to result. The 'type' of Cast result is same
        // as that of the vidu_node.
        cnode = new(generator->wHeap())
	           Cast(((vidu_node->getLeftSource()).getValueDesc())->getItemExpr(),
	                &(vidu_node->getResult().getType()));
      }
      else {
	// We indicate that the whole array is to be copied
	SQLRowset *rowsetInfo = (SQLRowset *) &(vidu_node->getResult().getType());
        SQLRowset *newRowset =  new (generator->wHeap()) 
	                         SQLRowset(generator->wHeap(), rowsetInfo->getElementType(),
	                                   rowsetInfo->getMaxNumElements(),
                                           rowsetInfo->getNumElements());
	newRowset->useTotalSize() = TRUE;
        cnode = new(generator->wHeap())
	           Cast(((vidu_node->getLeftSource()).getValueDesc())->getItemExpr(),
	                newRowset);
      }

      cnode->bindNode(generator->getBindWA());
      
      left_val_id_list.insert(cnode->getValueId());

      if (vidu_node->getResult().getType().getTypeQualifier() != NA_ROWSET_TYPE) {
        // move left child's output to result. The 'type' of Cast result is same
        // as that of the vidu_node.
        cnode = new(generator->wHeap())
	           Cast(((vidu_node->getRightSource()).getValueDesc())->getItemExpr(),
	                &(vidu_node->getResult().getType()));
      }
      else {
	// We indicate that the whole array is to be copied
	SQLRowset *rowsetInfo = (SQLRowset *) &(vidu_node->getResult().getType());
        SQLRowset *newRowset =  new (generator->wHeap()) 
	                         SQLRowset(generator->wHeap(), rowsetInfo->getElementType(),
	                                   rowsetInfo->getMaxNumElements(),
                                           rowsetInfo->getNumElements());
	newRowset->useTotalSize() = TRUE;
        cnode = new(generator->wHeap())
	           Cast(((vidu_node->getRightSource()).getValueDesc())->getItemExpr(),
	                newRowset);
      }

      cnode->bindNode(generator->getBindWA());
      right_val_id_list.insert(cnode->getValueId());
    }
  
  ExpTupleDesc * tuple_desc = 0;
  ULng32 tuple_length = 0;
  if(child(0) && child(1)) {
    exp_gen->generateContiguousMoveExpr(left_val_id_list,
					0, // don't add convert nodes
					1, returned_desc->noTuples() - 1,
					ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
					tuple_length,
					&left_expr,
					&tuple_desc,
					ExpTupleDesc::SHORT_FORMAT);
  

    exp_gen->generateContiguousMoveExpr(right_val_id_list,
					0, // don't add convert nodes
					1, returned_desc->noTuples() - 1,
					ExpTupleDesc::SQLARK_EXPLODED_FORMAT,
					tuple_length,
					&right_expr);
  }
  
  // add value ids for all vidu_nodes to my map table. This is the
  // the map table that will be returned. The attributes of the value ids
  // are same as that of left(or right) expression outputs.
  for (i = 0; i < colMapTable().entries(); i++)
    {
      ValueIdUnion * vidu_node = (ValueIdUnion *)(((colMapTable()[i]).getValueDesc())->getItemExpr());
      
      Attributes * attr =
	generator->addMapInfoToThis(my_map_table, vidu_node->getValueId(), 
				    generator->getMapInfo(left_val_id_list[i])->getAttr())->getAttr();
      attr->setAtp(0);
    }
  
  // describe the returned unioned row
  returned_desc->setTupleDescriptor(returned_desc->noTuples() - 1, tuple_desc);
  
  // if sort-merge union is being done, generate expression to
  // compare the left and the right values.
  // This predicate should return TRUE if the left value is
  // less than the right value.
  merge_expr = 0;
  if (getMergeExpr()) {
    // generate the merge predicate. 
    ItemExpr * mergeExpr = new(generator->wHeap()) BoolResult(getMergeExpr());
    mergeExpr->bindNode(generator->getBindWA());    
      
    exp_gen->generateExpr(mergeExpr->getValueId(),
			  ex_expr::exp_SCAN_PRED,
			  &merge_expr);   
  }

  // If conditional union, generate conditional expression, and ignore
  // right child if it was just being used as a no-op.
  cond_expr = 0;
  if (NOT condExpr().isEmpty()) {
    ItemExpr *condExp = condExpr().rebuildExprTree(ITM_AND, TRUE, TRUE);

    exp_gen->generateExpr(condExp->getValueId(), 
                          ex_expr::exp_SCAN_PRED, 
		          &cond_expr);
  }

  // If conditional union, generate triggered action exception error 
  if (NOT trigExceptExpr().isEmpty()) {
    ItemExpr *trigExp = trigExceptExpr().rebuildExprTree(ITM_AND, TRUE, TRUE);

    exp_gen->generateExpr(trigExp->getValueId(), 
                          ex_expr::exp_SCAN_PRED, 
		          &trig_expr);
  }

  // remove both children's map table. Nothing from child's context
  // should be visible from here on upwards.
  generator->removeAll(my_map_table);

  // Ensure the default buffer size is at least as large as the unioned output
  // row.
  UInt32 outputBuffSize = MAXOF( getDefault(GEN_UN_BUFFER_SIZE),
                                 tuple_length );
  outputBuffSize = SqlBufferNeededSize( 1,                 // # of tuples
                                        outputBuffSize,
                                        SqlBuffer::NORMAL_
                                        );

  ComTdbUnion * union_tdb 
    = new(space) ComTdbUnion(
			     left_child_tdb,
			     right_child_tdb,
			     left_expr,
			     right_expr,
			     merge_expr,
			     cond_expr,
			     trig_expr,
                             tuple_length, // unioned rowlen
			     returned_desc->noTuples()-1, // tupp index for
			                                  // unioned buffer
			     given_desc,
			     returned_desc, 
			     (queue_index)getDefault(GEN_UN_SIZE_DOWN),
			     (queue_index)getDefault(GEN_UN_SIZE_UP),
			     (Cardinality) (getInputCardinality() * getEstRowsUsed()).getValue(),
			     getDefault(GEN_UN_NUM_BUFFERS),
			     outputBuffSize,
			     getOrderedUnion(),
                             getBlockedUnion(),  //++ Triggers -
                             hasNoOutputs(),     //++ Triggers -
                             rowsFromLeft,
                             rowsFromRight,
                             afterUpdate,
			     getInNotAtomicStatement());

  generator->initTdbFields(union_tdb);

  // If it does not have two children, this is index maintenance code and
  // should not be Explained  
  if (!generator->explainDisabled()) {
    generator->setExplainTuple(addExplainInfo(union_tdb,
					    leftExplainTuple,
					    rightExplainTuple,
					    generator));
  }

  // restore the original down cri desc since this node changed it.
  generator->setCriDesc(given_desc, Generator::DOWN);

  // set the new up cri desc.
  generator->setCriDesc(returned_desc, Generator::UP);

  generator->setGenObj(this, union_tdb);

  return 0;  
}
示例#26
0
static void
rxmit_packets(struct cfg *cf, struct rtpp_session *sp, int ridx,
  double dtime)
{
    int ndrain, i, port;
    struct rtp_packet *packet = NULL;

    /* Repeat since we may have several packets queued on the same socket */
    for (ndrain = 0; ndrain < 5; ndrain++) {
	if (packet != NULL)
	    rtp_packet_free(packet);

	packet = rtp_recv(sp->fds[ridx]);
	if (packet == NULL)
	    break;
	packet->laddr = sp->laddr[ridx];
	packet->rport = sp->ports[ridx];
	packet->rtime = dtime;

	i = 0;
	if (sp->addr[ridx] != NULL) {
	    /* Check that the packet is authentic, drop if it isn't */
	    if (sp->asymmetric[ridx] == 0) {
		if (memcmp(sp->addr[ridx], &packet->raddr, packet->rlen) != 0) {
		    if (sp->canupdate[ridx] == 0) {
			/*
			 * Continue, since there could be good packets in
			 * queue.
			 */
			continue;
		    }
		    /* Signal that an address has to be updated */
		    i = 1;
		} else if (sp->canupdate[ridx] != 0 &&
		  sp->last_update[ridx] != 0 &&
		  dtime - sp->last_update[ridx] > UPDATE_WINDOW) {
		    sp->canupdate[ridx] = 0;
		}
	    } else {
		/*
		 * For asymmetric clients don't check
		 * source port since it may be different.
		 */
		if (!ishostseq(sp->addr[ridx], sstosa(&packet->raddr)))
		    /*
		     * Continue, since there could be good packets in
		     * queue.
		     */
		    continue;
	    }
	    sp->pcount[ridx]++;
	} else {
	    sp->pcount[ridx]++;
	    sp->addr[ridx] = malloc(packet->rlen);
	    if (sp->addr[ridx] == NULL) {
		sp->pcount[3]++;
		rtpp_log_write(RTPP_LOG_ERR, sp->log,
		  "can't allocate memory for remote address - "
		  "removing session");
		remove_session(cf, GET_RTP(sp));
		/* Break, sp is invalid now */
		break;
	    }
	    /* Signal that an address have to be updated. */
	    i = 1;
	}

	/*
	 * Update recorded address if it's necessary. Set "untrusted address"
	 * flag in the session state, so that possible future address updates
	 * from that client won't get address changed immediately to some
	 * bogus one.
	 */
	if (i != 0) {
	    sp->untrusted_addr[ridx] = 1;
	    memcpy(sp->addr[ridx], &packet->raddr, packet->rlen);
	    if (sp->prev_addr[ridx] == NULL || memcmp(sp->prev_addr[ridx],
	      &packet->raddr, packet->rlen) != 0) {
	        sp->canupdate[ridx] = 0;
	    }

	    port = ntohs(satosin(&packet->raddr)->sin_port);

	    rtpp_log_write(RTPP_LOG_INFO, sp->log,
	      "%s's address filled in: %s:%d (%s)",
	      (ridx == 0) ? "callee" : "caller",
	      addr2char(sstosa(&packet->raddr)), port,
	      (sp->rtp == NULL) ? "RTP" : "RTCP");

	    /*
	     * Check if we have updated RTP while RTCP is still
	     * empty or contains address that differs from one we
	     * used when updating RTP. Try to guess RTCP if so,
	     * should be handy for non-NAT'ed clients, and some
	     * NATed as well.
	     */
	    if (sp->rtcp != NULL && (sp->rtcp->addr[ridx] == NULL ||
	      !ishostseq(sp->rtcp->addr[ridx], sstosa(&packet->raddr)))) {
		if (sp->rtcp->addr[ridx] == NULL) {
		    sp->rtcp->addr[ridx] = malloc(packet->rlen);
		    if (sp->rtcp->addr[ridx] == NULL) {
			sp->pcount[3]++;
			rtpp_log_write(RTPP_LOG_ERR, sp->log,
			  "can't allocate memory for remote address - "
			  "removing session");
			remove_session(cf, sp);
			/* Break, sp is invalid now */
			break;
		    }
		}
		memcpy(sp->rtcp->addr[ridx], &packet->raddr, packet->rlen);
		satosin(sp->rtcp->addr[ridx])->sin_port = htons(port + 1);
		/* Use guessed value as the only true one for asymmetric clients */
		sp->rtcp->canupdate[ridx] = NOT(sp->rtcp->asymmetric[ridx]);
		rtpp_log_write(RTPP_LOG_INFO, sp->log, "guessing RTCP port "
		  "for %s to be %d",
		  (ridx == 0) ? "callee" : "caller", port + 1);
	    }
	}

	if (sp->resizers[ridx].output_nsamples > 0)
	    rtp_resizer_enqueue(&sp->resizers[ridx], &packet);
	if (packet != NULL)
	    send_packet(cf, sp, ridx, packet);
    }

    if (packet != NULL)
	rtp_packet_free(packet);
}
示例#27
0
//
//  Do_Breakpoint_Throws: C
//
// A call to Do_Breakpoint_Throws does delegation to a hook in the host, which
// (if registered) will generally start an interactive session for probing the
// environment at the break.  The `resume` native cooperates by being able to
// give back a value (or give back code to run to produce a value) that the
// call to breakpoint returns.
//
// RESUME has another feature, which is to be able to actually unwind and
// simulate a return /AT a function *further up the stack*.  (This may be
// switched to a feature of a "STEP OUT" command at some point.)
//
REBOOL Do_Breakpoint_Throws(
    REBVAL *out,
    REBOOL interrupted, // Ctrl-C (as opposed to a BREAKPOINT)
    const REBVAL *default_value,
    REBOOL do_default
) {
    REBVAL *target = NONE_VALUE;

    REBVAL temp;
    VAL_INIT_WRITABLE_DEBUG(&temp);

    if (!PG_Breakpoint_Quitting_Hook) {
        //
        // Host did not register any breakpoint handler, so raise an error
        // about this as early as possible.
        //
        fail (Error(RE_HOST_NO_BREAKPOINT));
    }

    // We call the breakpoint hook in a loop, in order to keep running if any
    // inadvertent FAILs or THROWs occur during the interactive session.
    // Only a conscious call of RESUME speaks the protocol to break the loop.
    //
    while (TRUE) {
        struct Reb_State state;
        REBCTX *error;

    push_trap:
        PUSH_TRAP(&error, &state);

        // The host may return a block of code to execute, but cannot
        // while evaluating do a THROW or a FAIL that causes an effective
        // "resumption".  Halt is the exception, hence we PUSH_TRAP and
        // not PUSH_UNHALTABLE_TRAP.  QUIT is also an exception, but a
        // desire to quit is indicated by the return value of the breakpoint
        // hook (which may or may not decide to request a quit based on the
        // QUIT command being run).
        //
        // The core doesn't want to get involved in presenting UI, so if
        // an error makes it here and wasn't trapped by the host first that
        // is a bug in the host.  It should have done its own PUSH_TRAP.
        //
        if (error) {
        #if !defined(NDEBUG)
            REBVAL error_value;
            VAL_INIT_WRITABLE_DEBUG(&error_value);

            Val_Init_Error(&error_value, error);
            PROBE_MSG(&error_value, "Error not trapped during breakpoint:");
            Panic_Array(CTX_VARLIST(error));
        #endif

            // In release builds, if an error managed to leak out of the
            // host's breakpoint hook somehow...just re-push the trap state
            // and try it again.
            //
            goto push_trap;
        }

        // Call the host's breakpoint hook.
        //
        if (PG_Breakpoint_Quitting_Hook(&temp, interrupted)) {
            //
            // If a breakpoint hook returns TRUE that means it wants to quit.
            // The value should be the /WITH value (as in QUIT/WITH)
            //
            assert(!THROWN(&temp));
            *out = *ROOT_QUIT_NATIVE;
            CONVERT_NAME_TO_THROWN(out, &temp, FALSE);
            return TRUE; // TRUE = threw
        }

        // If a breakpoint handler returns FALSE, then it should have passed
        // back a "resume instruction" triggered by a call like:
        //
        //     resume/do [fail "This is how to fail from a breakpoint"]
        //
        // So now that the handler is done, we will allow any code handed back
        // to do whatever FAIL it likes vs. trapping that here in a loop.
        //
        DROP_TRAP_SAME_STACKLEVEL_AS_PUSH(&state);

        // Decode and process the "resume instruction"
        {
            struct Reb_Frame *frame;
            REBVAL *mode;
            REBVAL *payload;

            assert(IS_GROUP(&temp));
            assert(VAL_LEN_HEAD(&temp) == RESUME_INST_MAX);

            mode = VAL_ARRAY_AT_HEAD(&temp, RESUME_INST_MODE);
            payload = VAL_ARRAY_AT_HEAD(&temp, RESUME_INST_PAYLOAD);
            target = VAL_ARRAY_AT_HEAD(&temp, RESUME_INST_TARGET);

            // The first thing we need to do is determine if the target we
            // want to return to has another breakpoint sandbox blocking
            // us.  If so, what we need to do is actually retransmit the
            // resume instruction so it can break that wall, vs. transform
            // it into an EXIT/FROM that would just get intercepted.
            //
            if (!IS_NONE(target)) {
            #if !defined(NDEBUG)
                REBOOL found = FALSE;
            #endif

                for (frame = FS_TOP; frame != NULL; frame = frame->prior) {
                    if (frame->mode != CALL_MODE_FUNCTION)
                        continue;

                    if (
                        frame != FS_TOP
                        && FUNC_CLASS(frame->func) == FUNC_CLASS_NATIVE
                        && (
                            FUNC_CODE(frame->func) == &N_pause
                            || FUNC_CODE(frame->func) == &N_breakpoint
                        )
                    ) {
                        // We hit a breakpoint (that wasn't this call to
                        // breakpoint, at the current FS_TOP) before finding
                        // the sought after target.  Retransmit the resume
                        // instruction so that level will get it instead.
                        //
                        *out = *ROOT_RESUME_NATIVE;
                        CONVERT_NAME_TO_THROWN(out, &temp, FALSE);
                        return TRUE; // TRUE = thrown
                    }

                    if (IS_FRAME(target)) {
                        if (NOT(frame->flags & DO_FLAG_FRAME_CONTEXT))
                            continue;
                        if (
                            VAL_CONTEXT(target)
                            == AS_CONTEXT(frame->data.context)
                        ) {
                            // Found a closure matching the target before we
                            // reached a breakpoint, no need to retransmit.
                            //
                        #if !defined(NDEBUG)
                            found = TRUE;
                        #endif
                            break;
                        }
                    }
                    else {
                        assert(IS_FUNCTION(target));
                        if (frame->flags & DO_FLAG_FRAME_CONTEXT)
                            continue;
                        if (VAL_FUNC(target) == frame->func) {
                            //
                            // Found a function matching the target before we
                            // reached a breakpoint, no need to retransmit.
                            //
                        #if !defined(NDEBUG)
                            found = TRUE;
                        #endif
                            break;
                        }
                    }
                }

                // RESUME should not have been willing to use a target that
                // is not on the stack.
                //
            #if !defined(NDEBUG)
                assert(found);
            #endif
            }

            if (IS_NONE(mode)) {
                //
                // If the resume instruction had no /DO or /WITH of its own,
                // then it doesn't override whatever the breakpoint provided
                // as a default.  (If neither the breakpoint nor the resume
                // provided a /DO or a /WITH, result will be UNSET.)
                //
                goto return_default; // heeds `target`
            }

            assert(IS_LOGIC(mode));

            if (VAL_LOGIC(mode)) {
                if (DO_VAL_ARRAY_AT_THROWS(&temp, payload)) {
                    //
                    // Throwing is not compatible with /AT currently.
                    //
                    if (!IS_NONE(target))
                        fail (Error_No_Catch_For_Throw(&temp));

                    // Just act as if the BREAKPOINT call itself threw
                    //
                    *out = temp;
                    return TRUE; // TRUE = thrown
                }

                // Ordinary evaluation result...
            }
            else
                temp = *payload;
        }

        // The resume instruction will be GC'd.
        //
        goto return_temp;
    }

    DEAD_END;

return_default:

    if (do_default) {
        if (DO_VAL_ARRAY_AT_THROWS(&temp, default_value)) {
            //
            // If the code throws, we're no longer in the sandbox...so we
            // bubble it up.  Note that breakpoint runs this code at its
            // level... so even if you request a higher target, any throws
            // will be processed as if they originated at the BREAKPOINT
            // frame.  To do otherwise would require the EXIT/FROM protocol
            // to add support for DO-ing at the receiving point.
            //
            *out = temp;
            return TRUE; // TRUE = thrown
        }
    }
    else
        temp = *default_value; // generally UNSET! if no /WITH

return_temp:

    // The easy case is that we just want to return from breakpoint
    // directly, signaled by the target being NONE!.
    //
    if (IS_NONE(target)) {
        *out = temp;
        return FALSE; // FALSE = not thrown
    }

    // If the target is a function, then we're looking to simulate a return
    // from something up the stack.  This uses the same mechanic as
    // definitional returns--a throw named by the function or closure frame.
    //
    // !!! There is a weak spot in definitional returns for FUNCTION! that
    // they can only return to the most recent invocation; which is a weak
    // spot of FUNCTION! in general with stack relative variables.  Also,
    // natives do not currently respond to definitional returns...though
    // they can do so just as well as FUNCTION! can.
    //
    *out = *target;
    CONVERT_NAME_TO_THROWN(out, &temp, TRUE);

    return TRUE; // TRUE = thrown
}
示例#28
0
int
handle_command(struct cfg *cf, int controlfd, double dtime)
{
    int len, argc, i, pidx, asymmetric;
    int external, pf, lidx, playcount, weak, tpf;
    int fds[2], lport, n;
    socklen_t rlen;
    char buf[1024 * 8];
    char *cp, *call_id, *from_tag, *to_tag, *addr, *port, *cookie;
    char *pname, *codecs, *recording_name, *t;
    struct rtpp_session *spa, *spb;
    char **ap, *argv[10];
    const char *rname, *errmsg;
    struct sockaddr *ia[2], *lia[2];
    struct sockaddr_storage raddr;
    int requested_nsamples;
    enum {DELETE, RECORD, PLAY, NOPLAY, COPY, UPDATE, LOOKUP, QUERY} op;
    int max_argc;
    char *socket_name_u, *notify_tag;
    struct sockaddr *local_addr;
    char c;

    requested_nsamples = -1;
    ia[0] = ia[1] = NULL;
    spa = spb = NULL;
    lia[0] = lia[1] = cf->bindaddr[0];
    lidx = 1;
    fds[0] = fds[1] = -1;
    recording_name = NULL;
    socket_name_u = notify_tag = NULL;
    local_addr = NULL;
    codecs = NULL;

    if (cf->umode == 0) {
	for (;;) {
	    len = read(controlfd, buf, sizeof(buf) - 1);
	    if (len != -1 || (errno != EAGAIN && errno != EINTR))
		break;
	    sched_yield();
	}
    } else {
	rlen = sizeof(raddr);
	len = recvfrom(controlfd, buf, sizeof(buf) - 1, 0,
	  sstosa(&raddr), &rlen);
    }
    if (len == -1) {
	if (errno != EAGAIN && errno != EINTR)
	    rtpp_log_ewrite(RTPP_LOG_ERR, cf->glog, "can't read from control socket");
	return -1;
    }
    buf[len] = '\0';

    rtpp_log_write(RTPP_LOG_DBUG, cf->glog, "received command \"%s\"", buf);

    cp = buf;
    argc = 0;
    memset(argv, 0, sizeof(argv));
    for (ap = argv; (*ap = rtpp_strsep(&cp, "\r\n\t ")) != NULL;)
	if (**ap != '\0') {
	    argc++;
	    if (++ap >= &argv[10])
		break;
	}
    cookie = NULL;
    if (argc < 1 || (cf->umode != 0 && argc < 2)) {
	rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
	reply_error(cf, controlfd, &raddr, rlen, cookie, 0);
	return 0;
    }

    /* Stream communication mode doesn't use cookie */
    if (cf->umode != 0) {
	cookie = argv[0];
	for (i = 1; i < argc; i++)
	    argv[i - 1] = argv[i];
	argc--;
	argv[argc] = NULL;
    } else {
	cookie = NULL;
    }

    addr = port = NULL;
    switch (argv[0][0]) {
    case 'u':
    case 'U':
	/* U[opts] callid remote_ip remote_port from_tag [to_tag] */
	op = UPDATE;
	rname = "update/create";
	break;

    case 'l':
    case 'L':
	op = LOOKUP;
	rname = "lookup";
	break;

    case 'd':
    case 'D':
	op = DELETE;
	rname = "delete";
	break;

    case 'p':
    case 'P':
	/*
	 * P callid pname codecs from_tag to_tag
	 *
	 *   <codecs> could be either comma-separated list of supported
	 *   payload types or word "session" (without quotes), in which
	 *   case list saved on last session update will be used instead.
	 */
	op = PLAY;
	rname = "play";
	playcount = 1;
	pname = argv[2];
	codecs = argv[3];
	break;

    case 'r':
    case 'R':
	op = RECORD;
	rname = "record";
	break;

    case 'c':
    case 'C':
	op = COPY;
	rname = "copy";
	break;

    case 's':
    case 'S':
	op = NOPLAY;
	rname = "noplay";
	break;

    case 'v':
    case 'V':
	if (argv[0][1] == 'F' || argv[0][1] == 'f') {
	    int i, known;
	    /*
	     * Wait for protocol version datestamp and check whether we
	     * know it.
	     */
	    if (argc != 2 && argc != 3) {
		rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
		reply_error(cf, controlfd, &raddr, rlen, cookie, 2);
		return 0;
	    }
	    /*
	     * Only list 20081224 protocol mod as supported if
	     * user actually enabled notification with -n
	     */
	    if (strcmp(argv[1], "20081224") == 0 &&
	      cf->timeout_handler.socket_name == NULL) {
		reply_number(cf, controlfd, &raddr, rlen, cookie, 0);
		return 0;
	    }
	    for (known = i = 0; proto_caps[i].pc_id != NULL; ++i) {
		if (!strcmp(argv[1], proto_caps[i].pc_id)) {
		    known = 1;
		    break;
		}
	    }
	    reply_number(cf, controlfd, &raddr, rlen, cookie, known);
	    return 0;
	}
	if (argc != 1 && argc != 2) {
	    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
	    reply_error(cf, controlfd, &raddr, rlen, cookie, 2);
	    return 0;
	}
	/* This returns base version. */
	reply_number(cf, controlfd, &raddr, rlen, cookie, CPROTOVER);
	return 0;

    case 'i':
    case 'I':
	if (cookie == NULL)
	    len = sprintf(buf, "sessions created: %llu\nactive sessions: %d\n"
	      "active streams: %d\n", cf->sessions_created,
	      cf->sessions_active, cf->nsessions / 2);
	else
	    len = sprintf(buf, "%s sessions created: %llu\nactive sessions: %d\n"
	      "active streams: %d\n", cookie, cf->sessions_created,
	      cf->sessions_active, cf->nsessions / 2);
	for (i = 1; i < cf->nsessions; i++) {
	    char addrs[4][256];

	    spa = cf->sessions[i];
	    if (spa == NULL || spa->sidx[0] != i)
		continue;
	    /* RTCP twin session */
	    if (spa->rtcp == NULL) {
		spb = spa->rtp;
		buf[len++] = '\t';
	    } else {
		spb = spa->rtcp;
		buf[len++] = '\t';
		buf[len++] = 'C';
		buf[len++] = ' ';
	    }

	    addr2char_r(spb->laddr[1], addrs[0], sizeof(addrs[0]));
	    if (spb->addr[1] == NULL) {
		strcpy(addrs[1], "NONE");
	    } else {
		sprintf(addrs[1], "%s:%d", addr2char(spb->addr[1]),
		  addr2port(spb->addr[1]));
	    }
	    addr2char_r(spb->laddr[0], addrs[2], sizeof(addrs[2]));
	    if (spb->addr[0] == NULL) {
		strcpy(addrs[3], "NONE");
	    } else {
		sprintf(addrs[3], "%s:%d", addr2char(spb->addr[0]),
		  addr2port(spb->addr[0]));
	    }

	    len += sprintf(buf + len,
	      "%s/%s: caller = %s:%d/%s, callee = %s:%d/%s, "
	      "stats = %lu/%lu/%lu/%lu, ttl = %d/%d\n",
	      spb->call_id, spb->tag, addrs[0], spb->ports[1], addrs[1],
	      addrs[2], spb->ports[0], addrs[3], spa->pcount[0], spa->pcount[1],
	      spa->pcount[2], spa->pcount[3], spb->ttl[0], spb->ttl[1]);
	    if (len + 512 > sizeof(buf)) {
		doreply(cf, controlfd, buf, len, &raddr, rlen);
		len = 0;
	    }
	}
	if (len > 0)
	    doreply(cf, controlfd, buf, len, &raddr, rlen);;
	return 0;
	break;

    case 'q':
    case 'Q':
	op = QUERY;
	rname = "query";
	break;

    case 'x':
    case 'X':
        /* Delete all active sessions */
        rtpp_log_write(RTPP_LOG_INFO, cf->glog, "deleting all active sessions");
        for (i = 1; i < cf->nsessions; i++) {
	    spa = cf->sessions[i];
	    if (spa == NULL || spa->sidx[0] != i)
		continue;
	    /* Skip RTCP twin session */
	    if (spa->rtcp != NULL) {
		remove_session(cf, spa);
	    }
        }
        reply_ok(cf, controlfd, &raddr, rlen, cookie);
        return 0;
        break;

    default:
	rtpp_log_write(RTPP_LOG_ERR, cf->glog, "unknown command");
	reply_error(cf, controlfd, &raddr, rlen, cookie, 3);
	return 0;
    }
    call_id = argv[1];
    if (op == UPDATE || op == LOOKUP || op == PLAY) {
	max_argc = (op == UPDATE ? 8 : 6);
	if (argc < 5 || argc > max_argc) {
	    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
	    reply_error(cf, controlfd, &raddr, rlen, cookie, 4);
	    return 0;
	}
	from_tag = argv[4];
	to_tag = argv[5];
	if (op == PLAY && argv[0][1] != '\0')
	    playcount = atoi(argv[0] + 1);
	if (op == UPDATE && argc > 6) {
	    socket_name_u = argv[6];
	    if (strncmp("unix:", socket_name_u, 5) == 0)
		socket_name_u += 5;
	    if (argc == 8) {
		notify_tag = argv[7];
		len = url_unquote((uint8_t *)notify_tag, strlen(notify_tag));
		if (len == -1) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog,
		      "command syntax error - invalid URL encoding");
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 4);
		    return 0;
		}
		notify_tag[len] = '\0';
	    }
	}
    }
    if (op == COPY) {
	if (argc < 4 || argc > 5) {
	    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
	    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
	    return 0;
	}
	recording_name = argv[2];
	from_tag = argv[3];
	to_tag = argv[4];
    }
    if (op == DELETE || op == RECORD || op == NOPLAY || op == QUERY) {
	if (argc < 3 || argc > 4) {
	    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
	    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
	    return 0;
	}
	from_tag = argv[2];
	to_tag = argv[3];
    }
    if (op == DELETE || op == RECORD || op == COPY || op == NOPLAY) {
	/* D, R and S commands don't take any modifiers */
	if (argv[0][1] != '\0') {
	    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
	    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
	    return 0;
	}
    }
    if (op == UPDATE || op == LOOKUP || op == DELETE) {
	addr = argv[2];
	port = argv[3];
	/* Process additional command modifiers */
	external = 1;
	/* In bridge mode all clients are assumed to be asymmetric */
	asymmetric = (cf->bmode != 0) ? 1 : 0;
	pf = AF_INET;
	weak = 0;
	for (cp = argv[0] + 1; *cp != '\0'; cp++) {
	    switch (*cp) {
	    case 'a':
	    case 'A':
		asymmetric = 1;
		break;

	    case 'e':
	    case 'E':
		if (lidx < 0) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
		    return 0;
		}
		lia[lidx] = cf->bindaddr[1];
		lidx--;
		break;

	    case 'i':
	    case 'I':
		if (lidx < 0) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
		    return 0;
		}
		lia[lidx] = cf->bindaddr[0];
		lidx--;
		break;

	    case '6':
		pf = AF_INET6;
		break;

	    case 's':
	    case 'S':
		asymmetric = 0;
		break;

	    case 'w':
	    case 'W':
		weak = 1;
		break;

	    case 'z':
	    case 'Z':
		requested_nsamples = (strtol(cp + 1, &cp, 10) / 10) * 80;
		if (requested_nsamples <= 0) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
		    return 0;
		}
		cp--;
		break;

	    case 'c':
	    case 'C':
		cp += 1;
		for (t = cp; *cp != '\0'; cp++) {
		    if (!isdigit(*cp) && *cp != ',')
			break;
		}
		if (t == cp) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
		    return 0;
		}
		codecs = alloca(cp - t + 1);
		memcpy(codecs, t, cp - t);
		codecs[cp - t] = '\0';
		cp--;
		break;

	    case 'l':
	    case 'L':
		len = extractaddr(cp + 1, &t, &cp, &tpf);
		if (len == -1) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
		    return 0;
		}
		c = t[len];
		t[len] = '\0';
		local_addr = host2bindaddr(cf, t, tpf, &errmsg);
		if (local_addr == NULL) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog,
		      "invalid local address: %s: %s", t, errmsg);
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
		    return 0;
		}
		t[len] = c;
		cp--;
		break;

	    case 'r':
	    case 'R':
		len = extractaddr(cp + 1, &t, &cp, &tpf);
		if (len == -1) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
		    return 0;
		}
		c = t[len];
		t[len] = '\0';
		local_addr = alloca(sizeof(struct sockaddr_storage));
		n = resolve(local_addr, tpf, t, SERVICE, AI_PASSIVE);
		if (n != 0) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog,
		      "invalid remote address: %s: %s", t, gai_strerror(n));
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
		    return 0;
		}
		if (local4remote(cf, local_addr, satoss(local_addr)) == -1) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog,
		      "can't find local address for remote address: %s", t);
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
		    return 0;
		}
		local_addr = addr2bindaddr(cf, local_addr, &errmsg);
		if (local_addr == NULL) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog,
		      "invalid local address: %s", errmsg);
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
		    return 0;
		}
		t[len] = c;
		cp--;
		break;

	    default:
		rtpp_log_write(RTPP_LOG_ERR, cf->glog, "unknown command modifier `%c'",
		  *cp);
		break;
	    }
	}
	if (op != DELETE && addr != NULL && port != NULL && strlen(addr) >= 7) {
	    struct sockaddr_storage tia;

	    if ((n = resolve(sstosa(&tia), pf, addr, port,
	      AI_NUMERICHOST)) == 0) {
		if (!ishostnull(sstosa(&tia))) {
		    for (i = 0; i < 2; i++) {
			ia[i] = malloc(SS_LEN(&tia));
			if (ia[i] == NULL) {
			    handle_nomem(cf, controlfd, &raddr, rlen, cookie,
			      5, ia, fds, spa, spb);
			    return 0;
			}
			memcpy(ia[i], &tia, SS_LEN(&tia));
		    }
		    /* Set port for RTCP, will work both for IPv4 and IPv6 */
		    n = ntohs(satosin(ia[1])->sin_port);
		    satosin(ia[1])->sin_port = htons(n + 1);
		}
	    } else {
		rtpp_log_write(RTPP_LOG_ERR, cf->glog, "getaddrinfo: %s",
		  gai_strerror(n));
	    }
	}
    }

    /*
     * Record and delete need special handling since they apply to all
     * streams in the session.
     */
    switch (op) {
    case DELETE:
	i = handle_delete(cf, call_id, from_tag, to_tag, weak);
	break;

    case RECORD:
	i = handle_record(cf, call_id, from_tag, to_tag);
	break;

    default:
	i = find_stream(cf, call_id, from_tag, to_tag, &spa);
	if (i != -1 && op != UPDATE)
	    i = NOT(i);
	break;
    }

    if (i == -1 && op != UPDATE) {
	rtpp_log_write(RTPP_LOG_INFO, cf->glog,
	  "%s request failed: session %s, tags %s/%s not found", rname,
	  call_id, from_tag, to_tag != NULL ? to_tag : "NONE");
	if (op == LOOKUP) {
	    for (i = 0; i < 2; i++)
		if (ia[i] != NULL)
		    free(ia[i]);
	    reply_port(cf, controlfd, &raddr, rlen, cookie, 0, lia);
	    return 0;
	}
	reply_error(cf, controlfd, &raddr, rlen, cookie, 8);
	return 0;
    }

    switch (op) {
    case DELETE:
    case RECORD:
	reply_ok(cf, controlfd, &raddr, rlen, cookie);
	return 0;

    case NOPLAY:
	handle_noplay(cf, spa, i);
	reply_ok(cf, controlfd, &raddr, rlen, cookie);
	return 0;

    case PLAY:
	handle_noplay(cf, spa, i);
	if (strcmp(codecs, "session") == 0) {
	    if (spa->codecs[i] == NULL) {
		reply_error(cf, controlfd, &raddr, rlen, cookie, 6);
		return 0;
	    }
	    codecs = spa->codecs[i];
	}
	if (playcount != 0 && handle_play(cf, spa, i, codecs, pname, playcount) != 0) {
	    reply_error(cf, controlfd, &raddr, rlen, cookie, 6);
	    return 0;
	}
	reply_ok(cf, controlfd, &raddr, rlen, cookie);
	return 0;

    case COPY:
	handle_copy(cf, spa, i, recording_name);
	reply_ok(cf, controlfd, &raddr, rlen, cookie);
	return 0;

    case QUERY:
	handle_query(cf, controlfd, &raddr, rlen, cookie, spa, i);
	return 0;

    case LOOKUP:
    case UPDATE:
	/* those are handled below */
	break;

    default:
	/* Programmatic error, should not happen */
	abort();
    }

    pidx = 1;
    lport = 0;
    if (i != -1) {
	assert(op == UPDATE || op == LOOKUP);
	if (spa->fds[i] == -1) {
	    if (local_addr != NULL) {
		spa->laddr[i] = local_addr;
	    }
	    if (create_listener(cf, spa->laddr[i], &lport, fds) == -1) {
		rtpp_log_write(RTPP_LOG_ERR, spa->log, "can't create listener");
		reply_error(cf, controlfd, &raddr, rlen, cookie, 7);
		return 0;
	    }
	    assert(spa->fds[i] == -1);
	    spa->fds[i] = fds[0];
	    assert(spa->rtcp->fds[i] == -1);
	    spa->rtcp->fds[i] = fds[1];
	    spa->ports[i] = lport;
	    spa->rtcp->ports[i] = lport + 1;
	    spa->complete = spa->rtcp->complete = 1;
	    append_session(cf, spa, i);
	    append_session(cf, spa->rtcp, i);
	}
	if (weak)
	    spa->weak[i] = 1;
	else if (op == UPDATE)
	    spa->strong = 1;
	lport = spa->ports[i];
	lia[0] = spa->laddr[i];
	pidx = (i == 0) ? 1 : 0;
	spa->ttl_mode = cf->ttl_mode;
	spa->ttl[0] = cf->max_ttl;
	spa->ttl[1] = cf->max_ttl;
	if (op == UPDATE) {
	    rtpp_log_write(RTPP_LOG_INFO, spa->log,
	      "adding %s flag to existing session, new=%d/%d/%d",
	      weak ? ( i ? "weak[1]" : "weak[0]" ) : "strong",
	      spa->strong, spa->weak[0], spa->weak[1]);
	}
	rtpp_log_write(RTPP_LOG_INFO, spa->log,
	  "lookup on ports %d/%d, session timer restarted", spa->ports[0],
	  spa->ports[1]);
    } else {
	assert(op == UPDATE);
	rtpp_log_write(RTPP_LOG_INFO, cf->glog,
	  "new session %s, tag %s requested, type %s",
	  call_id, from_tag, weak ? "weak" : "strong");

	if (local_addr != NULL) {
	    lia[0] = lia[1] = local_addr;
	    if (lia[0] == NULL) {
		rtpp_log_write(RTPP_LOG_ERR, spa->log,
		  "can't create listener: %s", t);
		reply_error(cf, controlfd, &raddr, rlen, cookie, 10);
		return 0;
	    }
	}
	if (create_listener(cf, lia[0], &lport, fds) == -1) {
	    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "can't create listener");
	    reply_error(cf, controlfd, &raddr, rlen, cookie, 10);
	    return 0;
	}

	/*
	 * Session creation. If creation is requested with weak flag,
	 * set weak[0].
	 */
	spa = malloc(sizeof(*spa));
	if (spa == NULL) {
	    handle_nomem(cf, controlfd, &raddr, rlen, cookie, 11, ia,
	      fds, spa, spb);
	    return 0;
	}
	/* spb is RTCP twin session for this one. */
	spb = malloc(sizeof(*spb));
	if (spb == NULL) {
	    handle_nomem(cf, controlfd, &raddr, rlen, cookie, 12, ia,
	      fds, spa, spb);
	    return 0;
	}
	memset(spa, 0, sizeof(*spa));
	memset(spb, 0, sizeof(*spb));
	for (i = 0; i < 2; i++) {
	    spa->fds[i] = spb->fds[i] = -1;
	    spa->last_update[i] = 0;
	    spb->last_update[i] = 0;
	}
	spa->call_id = strdup(call_id);
	if (spa->call_id == NULL) {
	    handle_nomem(cf, controlfd, &raddr, rlen, cookie, 13, ia,
	      fds, spa, spb);
	    return 0;
	}
	spb->call_id = spa->call_id;
	spa->tag = strdup(from_tag);
	if (spa->tag == NULL) {
	    handle_nomem(cf, controlfd, &raddr, rlen, cookie, 14, ia,
	      fds, spa, spb);
	    return 0;
	}
	spb->tag = spa->tag;
	for (i = 0; i < 2; i++) {
	    spa->rrcs[i] = NULL;
	    spb->rrcs[i] = NULL;
	    spa->laddr[i] = lia[i];
	    spb->laddr[i] = lia[i];
	}
	spa->strong = spa->weak[0] = spa->weak[1] = 0;
	if (weak)
	    spa->weak[0] = 1;
	else
	    spa->strong = 1;
	assert(spa->fds[0] == -1);
	spa->fds[0] = fds[0];
	assert(spb->fds[0] == -1);
	spb->fds[0] = fds[1];
	spa->ports[0] = lport;
	spb->ports[0] = lport + 1;
	spa->ttl[0] = cf->max_ttl;
	spa->ttl[1] = cf->max_ttl;
	spb->ttl[0] = -1;
	spb->ttl[1] = -1;
	spa->log = rtpp_log_open(cf, "rtpproxy", spa->call_id, 0);
	spb->log = spa->log;
	spa->rtcp = spb;
	spb->rtcp = NULL;
	spa->rtp = NULL;
	spb->rtp = spa;
	spa->sridx = spb->sridx = -1;

	append_session(cf, spa, 0);
	append_session(cf, spa, 1);
	append_session(cf, spb, 0);
	append_session(cf, spb, 1);

	hash_table_append(cf, spa);

	cf->sessions_created++;
	cf->sessions_active++;
	/*
	 * Each session can consume up to 5 open file descriptors (2 RTP,
	 * 2 RTCP and 1 logging) so that warn user when he is likely to
	 * exceed 80% mark on hard limit.
	 */
	if (cf->sessions_active > (cf->nofile_limit.rlim_max * 80 / (100 * 5)) &&
	  cf->nofile_limit_warned == 0) {
	    cf->nofile_limit_warned = 1;
	    rtpp_log_write(RTPP_LOG_WARN, cf->glog, "passed 80%% "
	      "threshold on the open file descriptors limit (%d), "
	      "consider increasing the limit using -L command line "
	      "option", (int)cf->nofile_limit.rlim_max);
	}

	rtpp_log_write(RTPP_LOG_INFO, spa->log, "new session on a port %d created, "
	  "tag %s", lport, from_tag);
	if (cf->record_all != 0) {
	    handle_copy(cf, spa, 0, NULL);
	    handle_copy(cf, spa, 1, NULL);
	}
    }

    if (op == UPDATE) {
	if (cf->timeout_handler.socket_name == NULL && socket_name_u != NULL)
	    rtpp_log_write(RTPP_LOG_ERR, spa->log, "must permit notification socket with -n");
	if (spa->timeout_data.notify_tag != NULL) {
	    free(spa->timeout_data.notify_tag);
	    spa->timeout_data.notify_tag = NULL;
	}
	if (cf->timeout_handler.socket_name != NULL && socket_name_u != NULL) {
	    if (strcmp(cf->timeout_handler.socket_name, socket_name_u) != 0) {
		rtpp_log_write(RTPP_LOG_ERR, spa->log, "invalid socket name %s", socket_name_u);
		socket_name_u = NULL;
	    } else {
		rtpp_log_write(RTPP_LOG_INFO, spa->log, "setting timeout handler");
		spa->timeout_data.handler = &cf->timeout_handler;
		spa->timeout_data.notify_tag = strdup(notify_tag);
	    }
	} else if (socket_name_u == NULL && spa->timeout_data.handler != NULL) {
	    spa->timeout_data.handler = NULL;
	    rtpp_log_write(RTPP_LOG_INFO, spa->log, "disabling timeout handler");
	}
    }

    if (ia[0] != NULL && ia[1] != NULL) {
        if (spa->addr[pidx] != NULL)
            spa->last_update[pidx] = dtime;
        if (spa->rtcp->addr[pidx] != NULL)
            spa->rtcp->last_update[pidx] = dtime;
	/*
	 * Unless the address provided by client historically
	 * cannot be trusted and address is different from one
	 * that we recorded update it.
	 */
	if (spa->untrusted_addr[pidx] == 0 && !(spa->addr[pidx] != NULL &&
	  SA_LEN(ia[0]) == SA_LEN(spa->addr[pidx]) &&
	  memcmp(ia[0], spa->addr[pidx], SA_LEN(ia[0])) == 0)) {
	    rtpp_log_write(RTPP_LOG_INFO, spa->log, "pre-filling %s's address "
	      "with %s:%s", (pidx == 0) ? "callee" : "caller", addr, port);
	    if (spa->addr[pidx] != NULL) {
	        if (spa->canupdate[pidx] == 0) {
	            if (spa->prev_addr[pidx] != NULL)
	                 free(spa->prev_addr[pidx]);
	            spa->prev_addr[pidx] = spa->addr[pidx];
	        } else {
		    free(spa->addr[pidx]);
		}
	    }
	    spa->addr[pidx] = ia[0];
	    ia[0] = NULL;
	}
	if (spa->rtcp->untrusted_addr[pidx] == 0 && !(spa->rtcp->addr[pidx] != NULL &&
	  SA_LEN(ia[1]) == SA_LEN(spa->rtcp->addr[pidx]) &&
	  memcmp(ia[1], spa->rtcp->addr[pidx], SA_LEN(ia[1])) == 0)) {
	    if (spa->rtcp->addr[pidx] != NULL) {
	        if (spa->rtcp->canupdate[pidx] == 0) {
	            if (spa->rtcp->prev_addr[pidx] != NULL)
	                free(spa->rtcp->prev_addr[pidx]);
	            spa->rtcp->prev_addr[pidx] = spa->rtcp->addr[pidx];
	        } else {
		    free(spa->rtcp->addr[pidx]);
		}
	    }
	    spa->rtcp->addr[pidx] = ia[1];
	    ia[1] = NULL;
	}
    }
    spa->asymmetric[pidx] = spa->rtcp->asymmetric[pidx] = asymmetric;
    spa->canupdate[pidx] = spa->rtcp->canupdate[pidx] = NOT(asymmetric);
    if (spa->codecs[pidx] != NULL) {
	free(spa->codecs[pidx]);
	spa->codecs[pidx] = NULL;
    }
    if (codecs != NULL)
	spa->codecs[pidx] = strdup(codecs);
    if (requested_nsamples > 0) {
	rtpp_log_write(RTPP_LOG_INFO, spa->log, "RTP packets from %s "
	  "will be resized to %d milliseconds",
	  (pidx == 0) ? "callee" : "caller", requested_nsamples / 8);
    } else if (spa->resizers[pidx].output_nsamples > 0) {
	  rtpp_log_write(RTPP_LOG_INFO, spa->log, "Resizing of RTP "
	  "packets from %s has been disabled",
	  (pidx == 0) ? "callee" : "caller");
    }
    spa->resizers[pidx].output_nsamples = requested_nsamples;

    for (i = 0; i < 2; i++)
	if (ia[i] != NULL)
	    free(ia[i]);

    assert(lport != 0);
    reply_port(cf, controlfd, &raddr, rlen, cookie, lport, lia);
    return 0;
}
示例#29
0
int
rtpp_command_ul_handle(struct cfg *cf, struct rtpp_command *cmd,
  struct ul_opts *ulop, int sidx)
{
    int pidx, lport, sessions_active;
    struct rtpp_socket *fds[2];
    const char *actor;
    struct rtpp_session *spa, *spb;

    pidx = 1;
    lport = 0;
    spa = spb = NULL;
    fds[0] = fds[1] = NULL;
    if (sidx != -1) {
        RTPP_DBG_ASSERT(cmd->cca.op == UPDATE || cmd->cca.op == LOOKUP);
        spa = cmd->sp;
        if (spa->rtp->stream[sidx]->fd == NULL || ulop->new_port != 0) {
            if (ulop->local_addr != NULL) {
                spa->rtp->stream[sidx]->laddr = ulop->local_addr;
            }
            if (rtpp_create_listener(cf, spa->rtp->stream[sidx]->laddr, &lport, fds) == -1) {
                RTPP_LOG(spa->log, RTPP_LOG_ERR, "can't create listener");
                reply_error(cmd, ECODE_LSTFAIL_1);
                goto err_undo_0;
            }
            if (spa->rtp->stream[sidx]->fd != NULL && ulop->new_port != 0) {
                RTPP_LOG(spa->log, RTPP_LOG_INFO,
                  "new port requested, releasing %d/%d, replacing with %d/%d",
                  spa->rtp->stream[sidx]->port, spa->rtcp->stream[sidx]->port, lport, lport + 1);
                CALL_METHOD(cf->stable->sessinfo, update, spa, sidx, fds);
            } else {
                RTPP_DBG_ASSERT(spa->rtp->stream[sidx]->fd == NULL);
                spa->rtp->stream[sidx]->fd = fds[0];
                RTPP_DBG_ASSERT(spa->rtcp->stream[sidx]->fd == NULL);
                spa->rtcp->stream[sidx]->fd = fds[1];
                CALL_METHOD(cf->stable->sessinfo, append, spa, sidx);
            }
            spa->rtp->stream[sidx]->port = lport;
            spa->rtcp->stream[sidx]->port = lport + 1;
            if (spa->complete == 0) {
                cmd->csp->nsess_complete.cnt++;
            }
            spa->complete = 1;
        }
        if (ulop->weak)
            spa->rtp->stream[sidx]->weak = 1;
        else if (cmd->cca.op == UPDATE)
            spa->strong = 1;
        lport = spa->rtp->stream[sidx]->port;
        ulop->lia[0] = spa->rtp->stream[sidx]->laddr;
        pidx = (sidx == 0) ? 1 : 0;
        if (cmd->cca.op == UPDATE) {
            CALL_METHOD(spa->rtp->stream[0]->ttl, reset_with,
              cf->stable->max_setup_ttl);
            CALL_METHOD(spa->rtp->stream[1]->ttl, reset_with,
              cf->stable->max_setup_ttl);
            RTPP_LOG(spa->log, RTPP_LOG_INFO,
              "adding %s flag to existing session, new=%d/%d/%d",
              ulop->weak ? ( sidx ? "weak[1]" : "weak[0]" ) : "strong",
              spa->strong, spa->rtp->stream[0]->weak, spa->rtp->stream[1]->weak);
        } else {
            CALL_METHOD(spa->rtp->stream[0]->ttl, reset_with, cf->stable->max_ttl);
            CALL_METHOD(spa->rtp->stream[1]->ttl, reset_with, cf->stable->max_ttl);
        }
        RTPP_LOG(spa->log, RTPP_LOG_INFO,
          "lookup on ports %d/%d, session timer restarted", spa->rtp->stream[0]->port,
          spa->rtp->stream[1]->port);
    } else {
        struct rtpp_hash_table_entry *hte;

        RTPP_DBG_ASSERT(cmd->cca.op == UPDATE);
        RTPP_LOG(cf->stable->glog, RTPP_LOG_INFO,
          "new session %s, tag %s requested, type %s",
          cmd->cca.call_id, cmd->cca.from_tag, ulop->weak ? "weak" : "strong");
        if (cf->stable->slowshutdown != 0) {
            RTPP_LOG(cf->stable->glog, RTPP_LOG_INFO,
              "proxy is in the deorbiting-burn mode, new session rejected");
            reply_error(cmd, ECODE_SLOWSHTDN);
            goto err_undo_0;
        }
        if (ulop->local_addr != NULL) {
            ulop->lia[0] = ulop->lia[1] = ulop->local_addr;
        }
        if (rtpp_create_listener(cf, ulop->lia[0], &lport, fds) == -1) {
            RTPP_LOG(cf->stable->glog, RTPP_LOG_ERR, "can't create listener");
            reply_error(cmd, ECODE_LSTFAIL_2);
            goto err_undo_0;
        }

        /*
         * Session creation. If creation is requested with weak flag,
         * set weak[0].
         */
        spa = rtpp_session_ctor(cf->stable, &cmd->cca, cmd->dtime, ulop->lia,
          ulop->weak, lport, fds);
        if (spa == NULL) {
            handle_nomem(cf, cmd, ECODE_NOMEM_4, ulop,
              fds, NULL);
            return (-1);
        }

        hte = CALL_METHOD(cf->stable->sessions_ht, append_refcnt, spa->call_id,
          spa->rcnt);
        if (hte == NULL) {
            handle_nomem(cf, cmd, ECODE_NOMEM_5, ulop, NULL, spa);
            return (-1);
        }
        if (CALL_METHOD(cf->stable->sessions_wrt, reg, spa->rcnt, spa->seuid) != 0) {
            CALL_METHOD(cf->stable->sessions_ht, remove, spa->call_id, hte);
            handle_nomem(cf, cmd, ECODE_NOMEM_8, ulop, NULL, spa);
            return (-1);
        }

        cmd->csp->nsess_created.cnt++;

        /*
         * Each session can consume up to 5 open file descriptors (2 RTP,
         * 2 RTCP and 1 logging) so that warn user when he is likely to
         * exceed 80% mark on hard limit.
         */
        sessions_active = CALL_METHOD(cf->stable->sessions_wrt, get_length);
        if (sessions_active > (rtpp_rlim_max(cf) * 80 / (100 * 5)) &&
          cf->nofile_limit_warned == 0) {
            cf->nofile_limit_warned = 1;
            RTPP_LOG(cf->stable->glog, RTPP_LOG_WARN, "passed 80%% "
              "threshold on the open file descriptors limit (%d), "
              "consider increasing the limit using -L command line "
              "option", (int)rtpp_rlim_max(cf));
        }

        RTPP_LOG(spa->log, RTPP_LOG_INFO, "new session on a port %d created, "
          "tag %s", lport, cmd->cca.from_tag);
        if (cf->stable->record_all != 0) {
            handle_copy(cf, spa, 0, NULL, 0);
            handle_copy(cf, spa, 1, NULL, 0);
        }
        /* Save ref, it will be decref'd by the command disposal code */
        RTPP_DBG_ASSERT(cmd->sp == NULL);
        cmd->sp = spa;
    }

    if (cmd->cca.op == UPDATE) {
        if (!CALL_METHOD(cf->stable->rtpp_tnset_cf, isenabled) && ulop->notify_socket != NULL)
            RTPP_LOG(spa->log, RTPP_LOG_ERR, "must permit notification socket with -n");
        if (spa->timeout_data.notify_tag != NULL) {
            free(spa->timeout_data.notify_tag);
            spa->timeout_data.notify_tag = NULL;
        }
        if (ulop->notify_socket != NULL) {
            struct rtpp_tnotify_target *rttp;

            rttp = CALL_METHOD(cf->stable->rtpp_tnset_cf, lookup, ulop->notify_socket,
              (cmd->rlen > 0) ? sstosa(&cmd->raddr) : NULL, (cmd->rlen > 0) ? cmd->laddr : NULL);
            if (rttp == NULL) {
                RTPP_LOG(spa->log, RTPP_LOG_ERR, "invalid socket name %s", ulop->notify_socket);
                ulop->notify_socket = NULL;
            } else {
                RTPP_LOG(spa->log, RTPP_LOG_INFO, "setting timeout handler");
                spa->timeout_data.notify_target = rttp;
                spa->timeout_data.notify_tag = strdup(ulop->notify_tag);
            }
        } else if (spa->timeout_data.notify_target != NULL) {
            spa->timeout_data.notify_target = NULL;
            RTPP_LOG(spa->log, RTPP_LOG_INFO, "disabling timeout handler");
        }
    }

    if (ulop->ia[0] != NULL && ulop->ia[1] != NULL) {
        CALL_METHOD(spa->rtp->stream[pidx], prefill_addr, &(ulop->ia[0]),
          cmd->dtime);
        CALL_METHOD(spa->rtcp->stream[pidx], prefill_addr, &(ulop->ia[1]),
          cmd->dtime);
    }
    spa->rtp->stream[pidx]->asymmetric = spa->rtcp->stream[pidx]->asymmetric = ulop->asymmetric;
    spa->rtp->stream[pidx]->latch_info.latched = spa->rtcp->stream[pidx]->latch_info.latched = ulop->asymmetric;
    if (spa->rtp->stream[pidx]->codecs != NULL) {
        free(spa->rtp->stream[pidx]->codecs);
        spa->rtp->stream[pidx]->codecs = NULL;
    }
    if (ulop->codecs != NULL) {
        spa->rtp->stream[pidx]->codecs = ulop->codecs;
        ulop->codecs = NULL;
    }
    spa->rtp->stream[NOT(pidx)]->ptime = ulop->requested_ptime;
    actor = CALL_METHOD(spa->rtp->stream[pidx], get_actor);
    if (ulop->requested_ptime > 0) {
        RTPP_LOG(spa->log, RTPP_LOG_INFO, "RTP packets from %s "
          "will be resized to %d milliseconds", actor, ulop->requested_ptime);
    } else if (spa->rtp->stream[pidx]->resizer != NULL) {
          RTPP_LOG(spa->log, RTPP_LOG_INFO, "Resizing of RTP "
          "packets from %s has been disabled", actor);
    }
    if (ulop->requested_ptime > 0) {
        if (spa->rtp->stream[pidx]->resizer != NULL) {
            rtp_resizer_set_ptime(spa->rtp->stream[pidx]->resizer, ulop->requested_ptime);
        } else {
            spa->rtp->stream[pidx]->resizer = rtp_resizer_new(ulop->requested_ptime);
        }
    } else if (spa->rtp->stream[pidx]->resizer != NULL) {
        rtp_resizer_free(cf->stable->rtpp_stats, spa->rtp->stream[pidx]->resizer);
        spa->rtp->stream[pidx]->resizer = NULL;
    }

    RTPP_DBG_ASSERT(lport != 0);
    ulop->reply.port = lport;
    ulop->reply.ia = ulop->lia[0];
    if (cf->stable->advaddr[0] != NULL) {
        if (cf->stable->bmode != 0 && cf->stable->advaddr[1] != NULL &&
          ulop->lia[0] == cf->stable->bindaddr[1]) {
            ulop->reply.ia_ov = cf->stable->advaddr[1];
        } else {
            ulop->reply.ia_ov = cf->stable->advaddr[0];
        }
    }
    ul_reply_port(cmd, &ulop->reply);
    rtpp_command_ul_opts_free(ulop);
    return (0);

err_undo_0:
    rtpp_command_ul_opts_free(ulop);
    return (-1);
}
示例#30
0
void spi_dev_init(int spi_clkg, int spi_speed)
{

	if (use_spidev) {
		lprintf("### using SPI_DEV\n");
	
		if (spi_fd != -1) close(spi_fd);
	
		if ((spi_fd = open(SPI_DEVNAME, O_RDWR)) < 0) sys_panic("open spidev");
	
		u4_t max_speed, check_speed;
		if (spi_speed == SPI_48M) max_speed = 48000000; else
		if (spi_speed == SPI_24M) max_speed = 24000000; else
		if (spi_speed == SPI_12M) max_speed = 12000000; else
		if (spi_speed == SPI_6M) max_speed = 6000000; else
		if (spi_speed == SPI_3M) max_speed = 3000000; else
		if (spi_speed == SPI_1_5M) max_speed = 1500000; else
			panic("unknown spi_speed");
		speed = max_speed;
		if (ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &max_speed) < 0) sys_panic("SPI_IOC_WR_MAX_SPEED_HZ");
		check_speed = 0;
		if (ioctl(spi_fd, SPI_IOC_RD_MAX_SPEED_HZ, &check_speed) < 0) sys_panic("SPI_IOC_RD_MAX_SPEED_HZ");
		check(max_speed == check_speed);
		char bpw = SPI_BPW, check_bpw;
		if (ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &bpw) < 0) sys_panic("SPI_IOC_WR_BITS_PER_WORD");
		check_bpw = -1;
		if (ioctl(spi_fd, SPI_IOC_RD_BITS_PER_WORD, &check_bpw) < 0) sys_panic("SPI_IOC_RD_BITS_PER_WORD");
		check(bpw == check_bpw);
		printf("SPIDEV: max_speed %d bpw %d\n", check_speed, check_bpw);
		u4_t mode = SPI_MODE_0 | NOT(SPI_CS_HIGH) | NOT(SPI_NO_CS) | NOT(SPI_LSB_FIRST);
		if (ioctl(spi_fd, SPI_IOC_WR_MODE, &mode) < 0) sys_panic("SPI_IOC_WR_MODE");
	} else {
		lprintf("### using SPI PIO\n");
	
		SPI_CONFIG = IDLEMODE | SOFT_RST | AUTOIDLE;
		spin_ms(10);
		SPI_MODULE = MASTER | GEN_CS | SINGLE_CHAN;
		
		// disable FIFO use by SPI1 before SPI0 can use (see manual)
		SPI1_CTRL = 0;
		SPI1_CONF = 0;
		
		SPI0_CTRL = 0;
		SPI0_CONF = 0;
		SPI_XFERLVL = RX_AFL;
		
		u4_t div = (spi_clkg)? (spi_speed + 1) : (1 << spi_speed);
		printf("SPI: clkg %d speed %d div %d %.3f MHz\n", spi_clkg, spi_speed, div, 48e6 / div / 1e6);
		#if 0
		printf("SPI: config 0x%x status 0x%x irqena 0x%x module 0x%x\n", SPI_CONFIG, SPI_STATUS, SPI_IRQENA, SPI_MODULE);
		printf("SPI1: conf 0x%x stat 0x%x ctrl 0x%x\n", SPI1_CONF, SPI1_STAT, SPI1_CTRL);
		printf("SPI0: conf 0x%x stat 0x%x ctrl 0x%x\n", SPI0_CONF, SPI0_STAT, SPI0_CTRL);
		#endif
	
		SPI0_CONF = SPI_CONF(spi_clkg, spi_speed);
		spin_ms(1);
		//printf("SPI_CONF: conf 0x%08x stat 0x%x ctrl 0x%x\n", SPI0_CONF, SPI0_STAT, SPI0_CTRL);
	}

	spi_init();
	init = true;
}