コード例 #1
0
ファイル: extvars.c プロジェクト: WeiY/mihini-repo
/* Called from `api_get`: add the list of every child id to children_set. */
static int get_all_var_names( lua_State *L) {
    // Initial stack state: ctx, hpath=="" (irrelevant)
    ExtVars_Mod_t *mod = checkmod(L);
    int nvars, *vars, i;
    swi_status_t r;

    lua_newtable( L); // ctx, "", children_set

    if( ! mod->list) return 0; /* Var listing not implemented */

    r = mod->list(&nvars, &vars);

    if( r) RETURN_ERROR_NUMBER( "get", r);

    for( i = 0; i<nvars; i++) {
        lua_pushnumber(  L, vars[i]); // ctx, "", children_set, var_number
        lua_tostring(    L, -1);      // ctx, "", children_set, var_string
        lua_pushboolean( L, 1);       // ctx, "", children_set, var_string, true
        lua_settable(    L, -3);      // ctx, "", children_set
    }

    lua_pushnil(   L);     // ctx, "", children_set, nil
    lua_pushvalue( L, -2); // ctx, "", children_set, nil, children_set
    if (mod->list_release)
        mod->list_release(nvars, vars);
    return 2;              // return nil, children_set
}
コード例 #2
0
ファイル: extvars.c プロジェクト: WeiY/mihini-repo
/* Called from `api_get`: push the appropriate value, retrieved from callback, on the Lua stack. */
static int get_leaf_value( lua_State *L) {
    ExtVars_Mod_t *mod = checkmod(L);
    int var = (int) lua_tonumber( L, 2);
    ExtVars_type_t  type;
    void       *value;
    swi_status_t   r;

    if(!lua_isnumber(L, 2)) RETURN_DA_NOT_FOUND;

    r = mod->get(var, & value, & type);

    if(r) {
        if (r == SWI_STATUS_DA_NOT_FOUND) {
            RETURN_DA_NOT_FOUND;
        }
        else {
            RETURN_ERROR_NUMBER( "get", r);
	}
    }
    switch( type) {
        case EXTVARS_TYPE_STR:    lua_pushstring(  L, value ? (const char *) value : ""); break;
        case EXTVARS_TYPE_INT:    lua_pushinteger( L, *(int*)        value); break;
        case EXTVARS_TYPE_DOUBLE: lua_pushnumber(  L, *(double*)     value); break;
        case EXTVARS_TYPE_BOOL:   lua_pushboolean( L, *(int*)        value); break;
        case EXTVARS_TYPE_NIL:    lua_pushnil(L); break;
        default:                  RETURN_ERROR_STRING( "Unknown ExtVars type"); // TODO get_release leak
    }
    if (mod->get_release)
        mod->get_release(var, value, type);
    return 1;
}
コード例 #3
0
ファイル: extvars.c プロジェクト: WeiY/mihini-repo
static int register_unregister( lua_State *L, int enable) {
    ExtVars_Mod_t *mod = checkmod(L);
    if( lua_isstring( L, 2) && lua_objlen( L, 2) == 0) {
        if(mod->register_all) {
	    swi_status_t r = mod->register_all(enable);
            if( r) RETURN_ERROR_NUMBER( "register", r);
        }
    } else {
      if (! lua_isnumber(L, 2)) {
	    RETURN_OK;
        }
        else if(mod->register_var) {
            swi_status_t r = mod->register_var(luaL_checkint( L, 2), enable);
            if( r) RETURN_ERROR_NUMBER( "register", r);
        }
    }
    RETURN_OK;
}
コード例 #4
0
static String desperate_check_mod_kludge_for_time_skewing(Relation &R, int o)
{
  Variable_ID Out_1, Out_3, In_4, In_8, alpha, v, k1, k2, k3, k4;
  int Out_1_coef, Out_3_coef, v_coef, const_term;
  int sign;
  F_Exists *exists_k1, *exists_k1k2, *exists_k3, *exists_k4;
  F_And *st_k1, *st_k1k2, *st_k3, *st_k4;
  GEQ_Handle geq_L_k1, geq_U_k1, geq_L_k3, geq_U_k3, geq_L_k4, geq_U_k4;
  EQ_Handle eq_k1, eq_k3, eq_k4;

  // R must be a single conjunct


  // PROBLEM:  FOR SOME REASON, THE RELEVANT EQUALITY SHOWS UP AS
  // 	t8 == 7+8*xbmod2+8*t4+Out_3+16*alpha  // note Out_1 is xbmod2
  // WHEN WE DO PRINT_WITH SUBS, BUT THE "TRUE" FORM IS
  //	8*xbmod2+8*t4+t8 == 7+Out_3+16*alpha
  // AS EVIDENCED BY THIS prefix_print.
  //
  // IS THIS CORRECT?  PRESUMABLY SO...
  // BASED ON AN UNDERSTANDING OF HOW ITS CORRECT, WE NEED TO
  // GENERALIZE OR CHANGE THE TEST BELOW.

  // R.prefix_print(stdout);

  if (tcodegen_debug)
    {
      fprintf(DebugFile, "%s%s\n", debug_mark_cp,
	      "desperately looking for special case mod and div substitution.");
    }

  // check that the only EQ constraint using Out_1 and Out_3 is of the form
  //	exists alpha : 8*Out_1 + 8*In_4 + In_8 == 7 + Out_3 + 16*alpha

  Out_1 = R.output_var(1);
  Out_3 = R.output_var(3);
  In_4=0, In_8=0, alpha=0;	// look for these vars in the loop --
				// In_4 must play the appropriate role
				// in the equality above, but may not
				// actually be the 4th input variable.
  DNF_Iterator di(R.query_DNF());

  // This loop looks for any one equality of the right form.
  // We we find it, we break out of the loop with alpha, In_4, and In_8 set;
  // When we discover we've got the wrong form, we continue the loop.

  for (EQ_Iterator ei = (*di)->EQs(); ei; ei++, alpha = In_4 = In_8 = 0)
    {
      Out_1_coef = (*ei).get_coef(Out_1);
      Out_3_coef = (*ei).get_coef(Out_3);
      if (abs(Out_3_coef) == 1 && Out_1_coef * Out_3_coef == -8)
	{
	  sign = Out_3_coef;
	  const_term = -sign * (*ei).get_const();
	  for (Constr_Vars_Iter cvi(*ei); cvi; cvi++)
	    {
	      v = (*cvi).var;
	      v_coef = (*cvi).coef;

	      if (v->kind() == Wildcard_Var ||
		  v->kind() == Exists_Var)	// must be alpha
		{
		  if (alpha || v_coef != 16)
		    goto continue_ei;
		  alpha = v;
		}
	      
	      else if (v_coef % 16 == 0)  // anything else doesn't matter
		continue;

	      else if (v->kind() == Output_Var)	// must be Out_3 or Out_1
		{
		  if (v != Out_1 && v != Out_3)
		    goto continue_ei;
		}

	      else if (v->kind() == Input_Var)	// must be In_4 or In_8
		{
		  if (v_coef * sign == -1)
		    {
		      if (In_8)
			goto continue_ei;
		      In_8 = v;
		    }
		  else if (v_coef * sign == -8)
		    {
		      if (In_4)
			goto continue_ei;
		      In_4 = v;
		    }
		  else
		    goto continue_ei;
		}

	      else // some other kind of variable I haven't considered
		goto continue_ei;

	    }  // for all vars in constraint

	  if (alpha && In_4 && In_8)
	    break;

	}  // end of "if Out and In have reasonable coefficients"

    continue_ei:
      ;
    }   // end of equality iteration

  if (! (alpha && In_4 && In_8))
    return "";

  // if o=3, assert (and return) substitution (In_8-8In_4-7) mod 8
  if (o == 3)
    {
#if ! defined NDEBUG
      // DO AN ASSERTION THAT THIS IS CORRECT

      Relation checkmod(R.n_inp(),R.n_out());

      assert(Out_1->kind() == Output_Var && Out_1->get_position() == 1);
      assert(Out_3->kind() == Output_Var && Out_3->get_position() == 3);
      assert(In_4->kind() == Input_Var);      // Note then In_4 may not actually be input var #4.
      assert(In_8->kind() == Input_Var);
      //Variable_ID cm_out_1 = checkmod.output_var(Out_1->get_position());
      Variable_ID cm_out_3 = checkmod.output_var(Out_3->get_position());
      Variable_ID cm_in_4  = checkmod.input_var (In_4->get_position());
      Variable_ID cm_in_8  = checkmod.input_var (In_8->get_position());

      exists_k1=checkmod.add_exists();
      k1=(*exists_k1).declare("k1_modbase");
      st_k1=(*exists_k1).add_and();
      geq_L_k1=(*st_k1).add_GEQ();
      geq_L_k1.update_coef(cm_out_3,1);
      geq_U_k1=(*st_k1).add_GEQ();
      geq_U_k1.update_coef(cm_out_3,-1);
      geq_U_k1.update_const(7);
      eq_k1=(*st_k1).add_EQ();
      eq_k1.update_coef(cm_out_3,-1);
      eq_k1.update_coef(cm_in_8,1);
      eq_k1.update_coef(cm_in_4,-8);
      eq_k1.update_coef(k1,8);
      eq_k1.update_const(-7);
      checkmod.finalize();

      checkmod = Intersection(checkmod, copy(R));
      // by definition, checkmod is a subset of R;
      // if the above mod constraint is redundant, R is a subset of checkmod
      assert(Must_Be_Subset(copy(checkmod),copy(R)));  // the obvious one
      assert(Must_Be_Subset(copy(R),checkmod));  // mod constraint is redundant

#endif
      return (String) "intMod(" + In_8->char_name() + "-8*" +
	In_4->char_name() + "+" + itoS(const_term) + ",8)";
      // return "intMod(t8-8*t4-7,8)";
    }


  // if o=1, assert&return the sub ( (8*((In_8-8In_4-7) div 8)) mod 16 ) div 8
  else if (o == 1)
    {
#if ! defined NDEBUG
      Relation checkmod(R.n_inp(),R.n_out());

      assert(Out_1->kind() == Output_Var && Out_1->get_position() == 1);
      assert(Out_3->kind() == Output_Var && Out_3->get_position() == 3);
      assert(In_4->kind() == Input_Var);      // Note then In_4 may not actually be input var #4.
      assert(In_8->kind() == Input_Var);
      Variable_ID cm_out_1 = checkmod.output_var(Out_1->get_position());
      //Variable_ID cm_out_3 = checkmod.output_var(Out_3->get_position());
      Variable_ID cm_in_4  = checkmod.input_var (In_4->get_position());
      Variable_ID cm_in_8  = checkmod.input_var (In_8->get_position());
  
      exists_k1k2=checkmod.add_exists();
      k1=(*exists_k1k2).declare("k1_modbase");
      k2=(*exists_k1k2).declare("k2_modbase");
      st_k1k2=(*exists_k1k2).add_and();
      geq_L_k1=(*st_k1k2).add_GEQ();
      geq_L_k1.update_coef(k1,1);  
      geq_L_k1.update_coef(cm_in_8,-1); 
      geq_L_k1.update_coef(cm_in_4,8); 
      geq_L_k1.update_const(14); 
      geq_U_k1=(*st_k1k2).add_GEQ();
      geq_U_k1.update_coef(k1,-1);
      geq_U_k1.update_coef(cm_in_8,1);
      geq_U_k1.update_coef(cm_in_4,-8);
      geq_U_k1.update_const(-7);

      exists_k3=(*st_k1k2).add_exists();
      k3=(*exists_k3).declare("k3_modbase");
      st_k3=(*exists_k3).add_and();
      geq_L_k3=(*st_k3).add_GEQ();
      geq_L_k3.update_coef(k2,1);
      geq_U_k3=(*st_k3).add_GEQ();
      geq_U_k3.update_coef(k2,-1);
      geq_U_k3.update_const(15);
      eq_k3=(*st_k3).add_EQ();
      eq_k3.update_coef(k1,1);
      eq_k3.update_coef(k3,-8);
     
      exists_k4=(*st_k3).add_exists();
      k4=(*exists_k4).declare("k4_modbase");
      st_k4=(*exists_k4).add_and();
      geq_L_k4=(*st_k4).add_GEQ();
      geq_L_k4.update_coef(k2,1);
      geq_L_k4.update_coef(cm_out_1,-8);
      geq_U_k4=(*st_k4).add_GEQ();
      geq_U_k4.update_coef(k2,-1);
      geq_U_k4.update_coef(cm_out_1,8);
      geq_U_k4.update_const(7);
      eq_k4=(*st_k4).add_EQ();
      eq_k4.update_coef(k1,-1);
      eq_k4.update_coef(k2,1);
      eq_k4.update_coef(k4,16);

      checkmod.finalize();
      checkmod = Intersection(checkmod, copy(R));

      // by definition, checkmod is a subset of R;
      // if the above mod constraint is redundant, R is a subset of checkmod
      assert(Must_Be_Subset(copy(checkmod),copy(R)));  // the obvious one
      assert(Must_Be_Subset(copy(R),checkmod));  // mod constraint is redundant


#endif
      return (String) "intDiv(intMod(8*intDiv(" + (*In_8).char_name() + 
        "-8*" + (*In_4).char_name() + "+" + itoS(const_term) + ",8),16),8)";
      // return "intDiv(intMod(8*intDiv(t8-8*t4-7,8),16),8)";
    }

  else return "";
}
コード例 #5
0
static modinfo check_mod(Relation &R, int o, bool tightmod)
{
  // R must be a single conjunct

  modinfo m, badm;
  m.modbase = 0;
  m.input_var = 0;
  m.input_var_coef = 0;
  badm = m;

  if (tcodegen_debug)
    {
      fprintf(DebugFile, "%s%s%d%s\n", debug_mark_cp,
	      "looking for mod substitution for output variable #",
	      o,
	      " in relation");
      fprintf(DebugFile, "%s", debug_mark_cp);
      R.print_with_subs(DebugFile);
    }


  // look for:  exists k s.t. 0 <= o < modbase && o = i + offset + k * modbase

  Variable_ID ov = R.output_var(o);
  Variable_ID k = 0;

  // Start by looking for
  //	exists k s.t.  o = i_coef * i + offset + k * modbase
  // We may also need to ignore "modbase * anything_else" terms,
  //  which we call "junk terms".
  // This is most easily done if we just hunt down modbase first

  DNF_Iterator di(R.query_DNF());
  for (EQ_Iterator ei = (*di)->EQs(); ei; ei++)
    {
      int o_coef = (*ei).get_coef(ov);
      if (o_coef != 0)
	{
	  if (m.modbase   != 0 ||  // there can be ... only one
	      abs(o_coef) != 1)    // above form requires this
	    return badm;

	  assert(m.input_var == 0);

	  // First, just figure out what modbase is
	  // Currently just find the (hopefully unique) wildcard/exists var.
	  // This does not allow junk wildcard terms.

	  for (Constr_Vars_Iter cvi(*ei); cvi; cvi++)
	    {
	      Variable_ID v = (*cvi).var;
	      int v_coef    = (*cvi).coef;

	      if ((v->kind() == Wildcard_Var ||
		   v->kind() == Exists_Var))
		{
		  if (m.modbase == 0)
		    {
		      m.modbase = abs(v_coef);
		      k = v;
		      assert(m.modbase != 0);
		    }
		  else
		    {
		      if (tcodegen_debug)
			{
			  fprintf(DebugFile, "%s%s\n", debug_mark_cp,
				  "giving up on possible junk wildcard term --"
				  " test, though simple, is not implemented");
			}
			return badm;
		    }
		}
	    }

 	  if (m.modbase == 0)
	    return badm;
	  assert(k);

	  {   // extra braces apparently avoid Visual C++ bug
	  for (Constr_Vars_Iter cvi(*ei); cvi; cvi++)
	    {
	      Variable_ID v = (*cvi).var;
	      int v_coef    = (*cvi).coef;
	      // we could find i, k (again), ov (again), junk, or a problem
	      // throw out junk terms first, in case of junk i before real i
	      if ((v_coef % m.modbase) != 0)
		{
		  if ((v->kind() == Input_Var) && // found i
		      m.input_var == 0)		  // there can be ... only one
		    {
		      assert(v_coef);
		      assert(abs(o_coef) == 1);
		      m.input_var_coef = v_coef * -o_coef;
		      m.input_var = v->get_position();
		      assert(m.input_var != 0);
		    }
		  else if (v != ov)
		    {
		      // Anything else is a legal junk term or "k" again
		      // as long as its divisible by m.modbase.
		      return badm;
		    }
		}
	    }
	  }

	  if (m.input_var == 0) // found eq, but not base
	    return badm;

	  m.offset = -o_coef * (*ei).get_const();
	  // now, as long as we don't find another eq, we should be set
	}
    }

  if (m.modbase == 0)   // no eq involving ov
    return badm;


  // only that one eq should use k

  assert(k);
  bool k_used_already = false;
  {
  for (EQ_Iterator ei = (*di)->EQs(); ei; ei++)
    {
      if ((*ei).get_coef(k))
	if (k_used_already)
	  return badm;
	else
	  k_used_already = true;
    }
  }

  // we've found the right eq, now check for the inequalities 0 <= o < modbase
  // also test for other (inappropriate) uses of k

  bool found_lb = false, found_ub = false;
  
  for (GEQ_Iterator gi = (*di)->GEQs(); gi; gi++)
    {
      int ov_coef = (*gi).get_coef(ov);
      if (ov_coef)
	{
	  if (ov_coef > 0)  //    hope for ov >= 0
	    {
	      if (ov_coef != 1 || (*gi).get_const() != 0)
		return badm;
	      found_lb = true;
	    }
	  else  // ov_coef < 0    hope for modbase-1 - ov >= 0
	    {
	      if (ov_coef != -1)
		return badm;
	      if (!(
		    ((*gi).get_const() == m.modbase-1)  // got it exactly
		    // we'll settle for x-ov >= 0 for x<=modbase-1 if looking for "tight" mod
		    || (tightmod && (*gi).get_const() <= m.modbase-1)))
		return badm;
	      if (tcodegen_debug && (*gi).get_const() < m.modbase-1)
		{
		  fprintf(DebugFile, "%s%s"coef_fmt"%s%d\n", debug_mark_cp,
			  "found \"tight\" mod constraint output < ",
			  (*gi).get_const(),
			  " rather than output < ",
			  m.modbase-1);
		}
	      found_ub = true;
	    }
	  // all other coefficients must be 0 for this geq
	  for (Constr_Vars_Iter cvi(*gi); cvi; cvi++)
	    {
	      if ((*cvi).var != ov && (*cvi).coef)
		return badm;
	    }
	}

      // also, k should not appear in any inequalities
      if ((*gi).get_coef(k))
	return badm;
    }
  
  if (!found_lb || !found_ub)
    return badm;

  if (tcodegen_debug)
    {
      fprintf(DebugFile, "%s%s%d%s%d%s%d%s%d\n", debug_mark_cp,
	      "found substitution: (",
	      m.input_var_coef,
	      "* input variable #",
	      m.input_var,
	      "+",
	      m.offset,
	      ") mod ",
	      m.modbase);
    }

#if ! defined NDEBUG
  if (m.modbase)
    {
      // build { [ ... i ... ] -> [ ... (ic * i + offset) mod modbase ... ] }
      // build { [ ... i ... ] -> [ ... o ... ] : exists k s.t. 
      //	    0 <= o < modbase &&  o = ic * i + offset + k * modbase }
      Relation checkmod(R.n_inp(), R.n_out());
      Variable_ID ic = checkmod.input_var(m.input_var);
      Variable_ID oc = checkmod.output_var(o);
      F_Exists *exists_k = checkmod.add_exists();
      Variable_ID  k = exists_k->declare("o_div_modbase");
      F_And *suchthat = exists_k->add_and();
      // 0 <= o
      GEQ_Handle o_geq_0 = suchthat->add_GEQ();
      o_geq_0.update_coef(oc,1);
      // o < modbase --> modbase-1-o >= 0
      GEQ_Handle o_lt_checkmod = suchthat->add_GEQ();
      o_lt_checkmod.update_coef(oc,-1);
      o_lt_checkmod.update_const(m.modbase-1);
      // ic * i + offset + k * modbase - o = 0
      EQ_Handle o_eq = suchthat->add_EQ();
      o_eq.update_coef(ic,m.input_var_coef);
      o_eq.update_const(m.offset);
      o_eq.update_coef(k,m.modbase);
      o_eq.update_coef(oc,-1);
      checkmod.finalize();

      checkmod = Intersection(checkmod, copy(R));

      // by definition, checkmod is a subset of R;
      // if the above mod constraint is redundant, R is a subset of checkmod

      assert(Must_Be_Subset(copy(checkmod),copy(R)));  // the obvious one
      assert(Must_Be_Subset(copy(R),checkmod));  // mod constraint is redundant
    }
#endif

  return m;
}
コード例 #6
0
ファイル: extvars.c プロジェクト: WeiY/mihini-repo
/* Takes an hmap,
 * converts it into nvars / vars / values / types,
 * calls the corresponding `set` C callback. */
static int api_set( lua_State *L) {
    // Initial stack state: ctx, hmap
    ExtVars_Mod_t *mod = checkmod(L);
    int n_entries = 0, n_ints = 0, n_numbers = 0;
    int val_false = 0, val_true = 1;

    luaL_checktype( L, 2, LUA_TTABLE);

    /* First pass: count entries and numbers, to determine how much malloc space is needed. */
    lua_pushnil( L);           // ctx, hmap, key==nil
    while( lua_next( L, -2)) { // ctx, hmap, key, value
        n_entries ++;
        if( lua_type( L, -1) == LUA_TNUMBER) {
            lua_Number n = lua_tonumber( L, -1);
            if( (lua_Number) (int) n == n) n_ints ++; else n_numbers ++;
        }
        lua_pop( L, 1); // ctx, hmap, key
    }                   // ctx, hmap


    /* Allocate all tables as a single memory chunk.
     * By using Lua's allocator, we avoid an unnecessary dependency to malloc(). */
    int chunk_size =
            sizeof( int)            * n_entries + /* variable ids */
            sizeof( void*)          * n_entries + /* values       */
            sizeof( ExtVars_type_t) * n_entries + /* types        */
            sizeof( int)            * n_ints    + /* ints         */
            sizeof( lua_Number)     * n_numbers;  /* doubles      */
#ifdef NOMALLOC
    void *alloc_ctx;
    lua_Alloc allocf = lua_getallocf( L, & alloc_ctx);
    void *chunk = allocf( alloc_ctx, NULL, 0, chunk_size);
#else
    void *chunk = malloc( chunk_size);
#endif
    if( ! chunk) RETURN_ERROR_STRING( "Not enough memory");

    int            *variables = (int*)            chunk;
    void          **values    = (void**)          (variables + n_entries);
    ExtVars_type_t *types     = (ExtVars_type_t*) (values    + n_entries);
    int            *ints      = (int*)            (types     + n_entries);
    lua_Number     *numbers   = (lua_Number*)     (ints      + n_ints);

    int i=0, i_int=0, i_number=0;

    /* 2nd pass: actually fill the tables for the set callback. */
    lua_pushnil( L); // ctx, hmap, key==nil
    while( lua_next( L, -2)) { // ctx, hmap, key, value

        /* Fill the variable id */
        int var = lua_tonumber( L, -2);
        if( ! var) RETURN_ERROR_STRING( "Not a numeric variable name");
        variables[i] = var;

        /* Fill type and value, allocate number value if necessary */
        int ltype = lua_type( L, -1);
        if( isniltoken( L, -1)) {
            types[i] = EXTVARS_TYPE_NIL;
        } else if( ltype == LUA_TNUMBER) {
            lua_Number n = lua_tonumber( L, -1);
            if( (lua_Number)  (int) n == n) {
                ints[i_int] = (int) n;
                types[i] = EXTVARS_TYPE_INT;
                values[i] = ints + i_int;
                i_int++;
            } else {
                numbers[i_number] = (lua_Number) n;
                types[i] = EXTVARS_TYPE_DOUBLE;
                values[i] = numbers + i_number;
                i_number++;
            }
        } else if( ltype == LUA_TSTRING) {
            types[i]  = EXTVARS_TYPE_STR;
            values[i] = (void *) lua_tostring( L, -1);
        } else if( ltype == LUA_TBOOLEAN) {
            types[i] = EXTVARS_TYPE_BOOL;
            values[i] = lua_toboolean( L, -1) ? & val_true : & val_false;
        } else {
            RETURN_ERROR_STRING( "Unsupported Lua type");
        }
        lua_pop( L, 1); // ctx, hmap, key
        i++;
    } // ctx, hmap

    swi_status_t r = mod->set(n_entries, variables, values, types);

    /* Lua-allocated chunks are freed by reallocating them to a 0 size. */
#ifdef NOMALLOC
    allocf( alloc_ctx, chunk, chunk_size, 0);
#else
    free( chunk);
#endif
    if( r) RETURN_ERROR_NUMBER( "set", r); else RETURN_OK;
}