Beispiel #1
0
int obj_equals(Object a, Object b){
    if(TM_TYPE(a) != TM_TYPE(b)) return 0;
    switch(TM_TYPE(a)){
        case TYPE_NUM:return GET_NUM(a) == GET_NUM(b);
        case TYPE_STR: {
            String* s1 = GET_STR_OBJ(a);
            String* s2 = GET_STR_OBJ(b);
            return s1->value == s2->value || 
                (s1->len == s2->len && strncmp(s1->value, s2->value, s1->len) == 0);
        }
        case TYPE_LIST:    {
            if(GET_LIST(a) == GET_LIST(b)) return 1;
            int i;
            int len = GET_LIST(a)->len;
            Object* nodes1 = GET_LIST(a)->nodes;
            Object* nodes2 = GET_LIST(b)->nodes;
            for(i = 0; i < len; i++){
                if(!obj_equals(nodes1[i], nodes2[i]) ){
                    return 0;
                }
            }
            return 1;
        }
        case TYPE_NONE:return 1;
        case TYPE_DICT:return GET_DICT(a) == GET_DICT(b);
        case TYPE_FUNCTION: return GET_FUNCTION(a) == GET_FUNCTION(b);
        default: {
            const char* ltype = tm_type(a.type);
            const char* rtype = tm_type(b.type);
            tm_raise("equals(): not supported type %d:%s and %d:%s", TM_TYPE(a), ltype, TM_TYPE(b), rtype);
        } 
    }
    return 0;
}
Beispiel #2
0
Object obj_add(Object a, Object b) {
    if (TM_TYPE(a) == TM_TYPE(b)) {
        switch (TM_TYPE(a)) {
        case TYPE_NUM:
            GET_NUM(a) += GET_NUM(b);
            return a;
        case TYPE_STR: {
            char* sa = GET_STR(a);
            char* sb = GET_STR(b);
            int la = GET_STR_LEN(a);
            int lb = GET_STR_LEN(b);
            if (la == 0) {return b;    }
            if (lb == 0) {return a;    }
            int len = la + lb;
            Object des = string_alloc(NULL, len);
            char*s = GET_STR(des);
            memcpy(s, sa, la);
            memcpy(s + la, sb, lb);
            return des;
        }
        case TYPE_LIST: {
            return list_add(GET_LIST(a), GET_LIST(b));
        }
        }
    }
    tm_raise("obj_add: can not add %o and %o", (a), (b));
    return NONE_OBJECT;
}
Beispiel #3
0
Object obj_mul(Object a, Object b) {
    if (a.type == b.type && a.type == TYPE_NUM) {
        GET_NUM(a) *= GET_NUM(b);
        return a;
    }
    if (a.type == TYPE_NUM && b.type == TYPE_STR) {
        Object temp = a;
        a = b;
        b = temp;
    }
    if (a.type == TYPE_STR && b.type == TYPE_NUM) {
        int len = GET_STR_LEN(a);
        Object des;
        if (len == 0)
            return a;
        int times = (int) GET_NUM(b);
        if (times <= 0)
            return sz_to_string("");
        if (times == 1)
            return a;
        des = string_alloc(NULL, len * times);
        char* s = GET_STR(des);
        int i;
        for (i = 0; i < times; i++) {
            strncpy(s, GET_STR(a), len);
            s += len;
        }
        return des;
    }
    tm_raise("obj_mul: can not multiply %o and %o", a, b);
    return NONE_OBJECT;
}
Beispiel #4
0
Object obj_div(Object a, Object b) {
    if (a.type == b.type && a.type == TYPE_NUM) {
        GET_NUM(a) /= GET_NUM(b);
        return a;
    }
    tm_raise("obj_div: can not divide %o and %o", a, b);
    return NONE_OBJECT;
}
Beispiel #5
0
Object obj_neg(Object o) {
    if (o.type == TYPE_NUM) {
        GET_NUM(o) = -GET_NUM(o);
        return o;
    }
    tm_raise("obj_neg: can not handle %o", o);
    return NONE_OBJECT;
}
Beispiel #6
0
Object obj_sub(Object a, Object b) {
    if (a.type == b.type) {
        if (a.type == TYPE_NUM) {
            GET_NUM(a) -= GET_NUM(b);
            return a;
        }
    }
    tm_raise("obj_sub: can not substract %o and %o", a, b);
    return NONE_OBJECT;
}
Beispiel #7
0
bool AtomicQueue::Dequeue(void* data_item) {
  const size_t buffer_size = mItemSize * mNumItems;
  for (;;) {
    const uint64_t cur_head = mHead;
    const uint64_t cur_tail = mTail;
    MemoryBarrier();

    // Check if empty (both counter and numbers match)
    if (cur_head == cur_tail)
      return false;

    const uint64_t cur_head_num = GET_NUM(cur_head);

    memcpy(data_item, static_cast<char*>(mBuffer) + cur_head_num, mItemSize);

    const uint64_t new_head_num = cur_head_num + mItemSize;
    const uint64_t head_cnt = GET_CNT(cur_head);

    // Check if looped through buffer.
    const uint64_t new_head_val = (new_head_num == buffer_size) ?
                                  CONSTRUCT_NEXT_VALUE(head_cnt, 0) :
                                  CONSTRUCT_VALUE(head_cnt, new_head_num);

    if (AtomicCmpSet64(&mHead, cur_head, new_head_val))
      break;
  }

  return true;
}
Beispiel #8
0
void AtomicMemPool::Remove(uint32_t index) {
  uint64_t next_free_index_value = mNextFreeIndex;
  MemoryBarrier();

  const size_t item_size = mItemSize;
  uint8_t* buffer_ptr = static_cast<uint8_t*>(mBuffer);

  for (;;) {
    const uint64_t next_free_index_num = GET_NUM(next_free_index_value);
    const uint32_t next_free_index = static_cast<uint32_t>(next_free_index_num);

    uint8_t* remove_loc = &buffer_ptr[item_size*index];
    *reinterpret_cast<uint32_t*>(remove_loc) = next_free_index;

    if (AtomicCmpSet64(&mNextFreeIndex,
                       next_free_index_value,
                       CONSTRUCT_NEXT_VALUE(GET_CNT(next_free_index_value),
                                            static_cast<uint64_t>(index)))) {
        break;
    }

    next_free_index_value = mNextFreeIndex;
    MemoryBarrier();
  }
}
Beispiel #9
0
Object obj_get(Object self, Object k) {
    Object v;
    switch (TM_TYPE(self)) {
    case TYPE_STR: {
        DictNode* node;
        if (TM_TYPE(k) == TYPE_NUM) {
            double d = GET_NUM(k);
            int n = d;
            if (n < 0) {
                n += GET_STR_LEN(self);
            }
            if (n >= GET_STR_LEN(self) || n < 0)
                tm_raise("String_get: index overflow ,len=%d,index=%d, str=%o",
                        GET_STR_LEN(self), n, self);
            return string_chr(0xff & GET_STR(self)[n]);
        } else if ((node = dict_get_node(GET_DICT(tm->str_proto), k)) != NULL) {
            return method_new(node->val, self);
        }
        break;
    }
    case TYPE_LIST:{
        DictNode* node;
        if (TM_TYPE(k) == TYPE_NUM) {
            return list_get(GET_LIST(self), GET_NUM(k));
        } else if ((node = dict_get_node(GET_DICT(tm->list_proto), k))!=NULL) {
            return method_new(node->val, self);
        }
        break;
    }
    case TYPE_DICT:{
        DictNode* node;
        node = dict_get_node(GET_DICT(self), k);
        if (node != NULL) {
            return node->val;
        } else if ((node = dict_get_node(GET_DICT(tm->dict_proto), k))!=NULL) {
            return method_new(node->val, self);
        }
        break;
    }
    case TYPE_FUNCTION:
        return get_func_attr(GET_FUNCTION(self), k);
    case TYPE_DATA:
        return GET_DATA(self)->get(GET_DATA(self), k);
    }
    tm_raise("keyError %o", k);
    return NONE_OBJECT;
}
Beispiel #10
0
Object obj_mod(Object a, Object b) {
    if (a.type == b.type && a.type == TYPE_NUM) {
        return tm_number((long) GET_NUM(a) % (long) GET_NUM(b));
    } else if (a.type == TYPE_STR) {
        Object *__mod__ = get_builtin("__mod__");
        if (__mod__ == NULL) {
            tm_raise("__mod__ is not defined");
        } else {
            arg_start();
            arg_push(a);
            arg_push(b);
            return call_function(*__mod__);
        }        
    }
    tm_raise("obj_mod: can not module %o and %o", a, b);
    return NONE_OBJECT;
}
Beispiel #11
0
/* Process the START pseudo operator.                                        */
void PSEUDO_START(char *LABEL_NAME,char *ARGUMENTS,int *LOCATION,
                  SYMBOL_TABLE *SYM_TAB,FILE *OUTPUT_STREAM)
{
  struct SYMBOL_TABLE_ENTRY *TABLE_ENTRY;
  int VALUE;
  char *START;

  if (!SEEN_END_OP) {
    (void) fprintf(OUTPUT_STREAM,"eERROR[27]: Section %s has no 'end'.\n",
	    MODULE_NAME);
    OUTPUT_BUFFER(&MOD_REC_BUF,OUTPUT_STREAM,1);
    LOCATION_EXCEEDS_MEM_SIZE = 0;
    (void) fprintf(OUTPUT_STREAM,"E\n");
    TABLE_ENTRY = LOOK_UP_SYMBOL(MODULE_NAME,MODULE_NAME,SYM_TAB);
    (*TABLE_ENTRY).LENGTH = (*LOCATION) - (*TABLE_ENTRY).LOCATION;
  }
  if (SEEN_START_OP == SEEN_START_1) 
    (void) fprintf(OUTPUT_STREAM,
		   "eERROR[32]: Multiple STARTs in this file.\n");

  SEEN_START_OP = SEEN_START_1;
  SEEN_END_OP = NO_END_SEEN_1;

  if (!strcmp(LABEL_NAME,"")) {
    (void) fprintf(OUTPUT_STREAM,"eERROR[33]: START requires a label.\n");
    GET_NEXT_MISSING_LABEL(LABEL_NAME,SYM_TAB);
  } 

  if (LOOK_UP_SYMBOL(LABEL_NAME,LABEL_NAME,SYM_TAB) != NULL) {
   (void) fprintf(OUTPUT_STREAM,"eERROR[55]: Multiply defined module name.\n");
   (void) strcpy(MODULE_NAME,LABEL_NAME);
  } else {
/* --------------- Modify LABEL_NAMEs symbol table entry to reflect that it  */
/*                 is a module name.                                         */
    TABLE_ENTRY = LOOK_UP_SYMBOL(MODULE_NAME,LABEL_NAME,SYM_TAB);
    START = ARGUMENTS;
    VALUE = GET_NUM(&START,MEM_ADDR_SIZE_1+1,10);
    OUTPUT_BUFFER(&ERROR_REC_BUF,OUTPUT_STREAM,1);

    if (VALUE < 0)
      (void) fprintf(OUTPUT_STREAM,"eERROR[34]: Negative starting address.\n");
    else (*TABLE_ENTRY).LOCATION = VALUE;

    if (!IS_BLANK_OR_TAB(*START) && !eoln(*START) &&
	(START != ARGUMENTS))
      (void) fprintf(OUTPUT_STREAM,
	     "eERROR[13]: Expected a <space> after the operand, found %c.\n",
		     *START);

/* ---------------- Indicate that is a module and the MAIN module.           */
    (void) strcpy(  (*TABLE_ENTRY).MODULE, LABEL_NAME);
    (void) strcpy(MODULE_NAME,LABEL_NAME);
    (void) strcpy(MAIN_ROUTINE,LABEL_NAME);
    
    (*LOCATION) = (*TABLE_ENTRY).LOCATION;
    (void) fprintf(OUTPUT_STREAM,"s%s\n",MODULE_NAME);
  }
}
Beispiel #12
0
int obj_cmp(Object a, Object b) {
    if (TM_TYPE(a) == TM_TYPE(b)) {
        switch (TM_TYPE(a)) {
            case TYPE_NUM: {
                double diff = GET_NUM(a) - GET_NUM(b);
                if (diff > 0.0) {
                    return 1;
                } else if (diff < 0.0) {
                    return -1;
                }
                return 0;
            }
            case TYPE_STR: return strcmp(GET_STR(a), GET_STR(b));
        }
    }
    tm_raise("obj_cmp: can not compare %o and %o", a, b);
    return 0;
}
Beispiel #13
0
JNI int JNINAME(run)(JNIEnv *env, jobject jobj, jstring jtxt) {
    JavaLink context(env, jobj);
    const char *txt = env->GetStringUTFChars(jtxt, 0);
    Pepper pepper(&context);
    Func *f = pepper.parseStatList(txt);
    env->ReleaseStringUTFChars(jtxt, txt);
    Value v = pepper.run(f, 0, 0);
    return IS_NUM(v) ? (int) GET_NUM(v) : -1;
}
Beispiel #14
0
int main(int argc, char * const argv[])
{
    int c;

    while ((c = getopt(argc, argv, "m:p:r:n:e:")) != -1) {
        switch (c) {
        case 'm':
            if      (MATCH_STR("riffle")) mode = RIFFLE;
            else if (MATCH_STR("pile"))   mode = PILE;
            else if (MATCH_STR("random")) mode = RANDOM;
            else                          exit(usage());
            break;
        case 'p':
            GET_NUM(&piles);
            break;
        case 'r':
            GET_NUM(&reps);
            break;
        case 'n':
            GET_NUM(&cards);
            break;
        case 'e':
            GET_NUM(&error);
            break;
        case '?':
        default:
            exit(usage());
        }
    }
    if ((file = argv[optind]) == NULL) {
        printf("No output file specified.\n");
        exit(usage());
    }
    if (error < 0 || error > 100) {
        printf("Error must be between 0 and 100 (percent)\n");
        exit(usage());
    } else if (cards > 65536) {
        printf("Too many cards (%ld)\n", cards);
        exit(usage());
    }
    sgenrand(time(NULL));
    // printf("piles: %ld, reps: %ld, cards: %ld, mode: %d, file: %s\n", piles, reps, cards, mode, argv[optind]);
    return go();
}
Beispiel #15
0
size_t AtomicQueue::CurrentSize() const {
  const uint64_t cur_head = mHead;
  const uint64_t cur_tail = mTail;
  MemoryBarrier();

  const uint64_t size = static_cast<uint64_t>(mItemSize);
  const uint64_t cur_head_num = GET_NUM(cur_head);
  const uint64_t cur_tail_num = GET_NUM(cur_tail);

  if (cur_head_num == cur_tail_num) {
    // Empty if the counters match, full otherwise.
    return (cur_head == cur_tail) ? 0 : mItemSize;
  } else if (cur_tail_num > cur_head_num) {
    return static_cast<size_t>((cur_tail_num - cur_head_num) / size);
  } else {
    const uint64_t looped_tail = cur_tail_num + (size * mNumItems);
    return static_cast<size_t>((looped_tail - cur_head_num) / size);
  }
}
Beispiel #16
0
/**
 * slice string/list
 * string.slice(a,b) [a,b), b is not included
 * string.slice(0,-1) = string.slice(0,len(string))
 * @since 2016-11-19
 * <code>
 * 'test'.slice(0,1) = 't'
 * 'test'.slice(0,-1) = 'test'
 * </code>
 */
Object obj_slice(Object self, Object first, Object second) {
    int start = GET_NUM(first);
    int end = GET_NUM(second);
    Object ret = NONE_OBJECT;
    
    if (IS_STR(self)) {
        int length = GET_STR_LEN(self);
        start = start >= 0 ? start : start + length + 1;
        end   = end   >= 0 ? end   : end   + length + 1;
        if (start < 0 || start > length) {
            start = 0;
        } 
        if (end < 0 || end > length) {
            end = length; // do not overflow;
        } 
        if (end <= start) {
            return string_alloc("", 0);
        }
        return string_alloc(GET_STR(self) + start, end - start);
    } else if (IS_LIST(self)) {
        int length = LIST_LEN(self);
        start = start > 0 ? start : start + length + 1;
        end   = end   > 0 ? end   : end   + length + 1;
        if (start < 0 || start > length) {
            start = 0;
        } 
        if (end < 0 || end > length) {
            end = length;
        } 
        int i = 0;
        ret = list_new(end - start);
        for (i = start; i < end ; i++) {
            obj_append(ret, LIST_GET(self, i));
        }
    } else {
        tm_raise("slice not implemented for type %s", tm_type(self.type));
    }
    return ret;
}
Beispiel #17
0
// func Object tm_str(Object a)
Object tm_str(Object a) {
    char buf[100];
    memset(buf, 0, sizeof(buf));
    switch (TM_TYPE(a)) {
    case TYPE_STR:
        return a;
    case TYPE_NUM: {
        char s[20];
        double v = GET_NUM(a);
        number_format(s, a);
        return string_new(s);
    }
    case TYPE_LIST: {
        Object str = string_new("");

        str = string_append_char(str, '[');
        int i, l = LIST_LEN(a);
        for (i = 0; i < l; i++) {
            Object obj = GET_LIST(a)->nodes[i];
            /* reference to self in list */
            if (obj_equals(a, obj)) {
                str = string_append_sz(str, "[...]");
            } else if (obj.type == TYPE_STR) {
                str = string_append_char(str, '"');
                str = string_append_obj(str, obj);
                str = string_append_char(str, '"');
            } else {
                str = string_append_obj(str, obj);
            }
            if (i != l - 1) {
                str = string_append_char(str, ',');
            }
        }
        str = string_append_char(str, ']');
        return str;
    }
    case TYPE_DICT:
        sprintf(buf, "<dict at %p>", GET_DICT(a));
        return string_new(buf);
    case TYPE_FUNCTION:
        function_format(buf, a);
        return string_new(buf);
    case TYPE_NONE:
        return sz_to_string("None");
    case TYPE_DATA:
        return GET_DATA(a)->str(GET_DATA(a));
    default:
        tm_raise("str: not supported type %d", a.type);
    }
    return string_alloc("", 0);
}
Beispiel #18
0
uint32_t AtomicMemPool::Allocate() {
  uint32_t used_indexes = mUsedIndexes;
  uint64_t next_free_index_value = mNextFreeIndex;
  MemoryBarrier();

  const size_t item_size = mItemSize;
  uint8_t* buffer_ptr = static_cast<uint8_t*>(mBuffer);

  // Check if there are any free items
  uint32_t next_num = static_cast<uint32_t>(GET_NUM(next_free_index_value));
  while (next_num != static_cast<uint32_t>(-1)) {
    uint8_t* next_free_loc = &buffer_ptr[item_size*next_num];
    uint32_t new_next_free_index = *reinterpret_cast<uint32_t*>(next_free_loc);

    if (AtomicCmpSet64(&mNextFreeIndex,
                       next_free_index_value,
                       CONSTRUCT_NEXT_VALUE(GET_CNT(next_free_index_value),
                                            new_next_free_index))) {
      return next_num;
    }

    next_free_index_value = mNextFreeIndex;
    MemoryBarrier();

    next_num = static_cast<uint32_t>(GET_NUM(next_free_index_value));
  }

  // Check if used rest of array
  const size_t array_size = mNumItems;
  if (used_indexes < array_size) {
    uint32_t new_index = AtomicAdd32(&mUsedIndexes, 1);
    if (new_index < array_size) {
      return new_index;
    }
  }

  return static_cast<uint32_t>(-1);
}
Beispiel #19
0
inline Value doAdd(GC *gc, Value a, Value b) {
    int ta = TAG(a);
    if (IS_NUM_TAG(ta) && IS_NUM(b)) {
        return VAL_NUM(GET_NUM(a) + GET_NUM(b));
    } else if (IS_STRING(a)) {
        return String::concat(gc, a, b);
    } else {
        if (ta != T_OBJ) { return E_WRONG_TYPE; }
        int type = O_TYPE(a);
        if (type == O_ARRAY && (IS_ARRAY(b) || IS_MAP(b) || IS_STRING(b))) {
            Array *array = Array::alloc(gc);
            array->add(a);
            array->add(b);
            return VAL_OBJ(array);
        } else if (type == O_MAP && (IS_ARRAY(b) || IS_MAP(b) || IS_STRING(b))) {
            Map *map = MAP(a)->copy(gc);
            map->add(b);
            return VAL_OBJ(map);
        } else {
            return VERR;
        }
    }
}
Beispiel #20
0
bool AtomicQueue::Enqueue(const void* data_item) {
  const uint64_t cur_head = mHead;
  const uint64_t cur_tail = mTail;
  MemoryBarrier();

  const uint64_t cur_head_num = GET_NUM(cur_head);
  const uint64_t cur_tail_num = GET_NUM(cur_tail);

  // Check if full (numbers match, but counters do not)
  if (cur_head_num == cur_tail_num && cur_head != cur_tail)
    return false;

  memcpy(static_cast<char*>(mBuffer) + cur_tail_num, data_item, mItemSize);

  const uint64_t new_tail_num = cur_tail_num + mItemSize;
  const uint64_t tail_cnt = GET_CNT(cur_tail);

  // Check if looped through buffer.
  mTail = (new_tail_num == (mItemSize * mNumItems)) ?
          CONSTRUCT_NEXT_VALUE(tail_cnt, 0) :
          CONSTRUCT_VALUE(tail_cnt, new_tail_num);

  return true;
}
Beispiel #21
0
void obj_set(Object self, Object k, Object v) {
    // gc_mark_single(k); // used between gc scan
    // gc_mark_single(v); // only need to mark single.
    switch (TM_TYPE(self)) {
    case TYPE_LIST: {
        tm_assert_type(k, TYPE_NUM, "obj_set");
        double d = GET_NUM(k);
        tm_assert_int(d, "list_set");
        list_set(GET_LIST(self), (int)d, v);
    }
        return;
    case TYPE_DICT:
        dict_set0(GET_DICT(self), k, v);
        return;
    }
    tm_raise("obj_set: Self %o, Key %o, Val %o", self, k, v);
}
Beispiel #22
0
/*
	Synchronises the options data with what is held in the gui structures 
	(the gui holds the "latest" data, so this is copied into here)

	This should be used when the application wants to store the settings on disk
	i.e save them in the configuration file

	or when the application wants to use the new settings with the screamer system
	since it will not ask the gui for this information, when the gui structures are updated
	(this is the only way the user can alter the configuration, apart from hand editing the configuration file)
	any attempt to run screamer must be done with the new configuration, so when the options are updated and ok'd
	they need to be synchronised with the backend options structures, so screamer can use those changes in the options
*/
void Options::Update(void)
{
#define GET_TEXT(name)		gtk_entry_get_text(GTK_ENTRY(lookup_widget(OptionsWindow,name)))
#define GET_NUM(name)			atoi(gtk_entry_get_text(GTK_ENTRY(lookup_widget(OptionsWindow,name))))
#define GET_SPIN(name)		gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(lookup_widget(OptionsWindow,name)))
#define	GET_TOGGLE(name)	gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(OptionsWindow,name)))
	
	ScreamerName					=	GET_TEXT("ScreamerName");
	ScreamerCPUNumbers		=	GET_NUM("ScreamerCPUNumbers");
	NumberFrames					=	GET_SPIN("NumberFrames");
	CommandDirectory			=	GET_TEXT("CommandDirectory");
	ScreamerExecutable		=	GET_TEXT("ScreamerExecutable");
	ScreamerConfigDir			=	GET_TEXT("ScreamerConfigDir");
	ScreamerPriority			=	GET_SPIN("ScreamerPriority");
	FindScreamerInterval	=	GET_SPIN("ScreamerInterval");
	WineCmd								=	GET_TEXT("WineCmd");
}
Beispiel #23
0
int is_true_obj(Object v) {
    switch (TM_TYPE(v)) {
    case TYPE_NUM:
        return GET_NUM(v) != 0;
    case TYPE_NONE:
        return 0;
    case TYPE_STR:
        return GET_STR_LEN(v) > 0;
    case TYPE_LIST:
        return LIST_LEN(v) > 0;
    case TYPE_DICT:
        return DICT_LEN(v) > 0;
    case TYPE_FUNCTION:
    case TYPE_DATA:
        return 1;
    }
    return 0;
}
Beispiel #24
0
void StringBuilder::append(Value v, bool raw) {
    void *ptr = GET_PTR(v);
    if (IS_STRING(v)) {
        if (!raw) { append('\''); }
        append(GET_CSTR(v), len(v));
        if (!raw) { append('\''); }
    } else if (IS_NUM(v)) {
        append(GET_NUM(v));
        return;
    } else if (IS_ARRAY(v)) {
        Array *a = (Array *) ptr;
        int size = a->size();
        append('[');
        for (int i = 0; i < size; ++i) {
            append(i ? ", " : "");
            append(a->getI(i));
        }
        append(']');
    } else if (IS_MAP(v)) {
        Map *m = (Map *) ptr;
        int size = m->size();
        append('{');
        Value *keys = m->keyBuf();
        Value *vals = m->valBuf();
        for (int i = 0; i < size; ++i) {
            append(i ? ", " : "");
            append(keys[i]);
            append(':');
            append(vals[i]);
        }
        append('}');
    } else if (IS_NIL(v)) {
        append("nil");
    } else {
        append('<');
        append(typeStr(v));
        append('>');
        char tmp[32];
        snprintf(tmp, sizeof(tmp), "%p", ptr);
        append(tmp);
    }
}
Beispiel #25
0
static Value doSHL(Value v, int shift) {
    if (!IS_NUM(v)) { return VERR; }
    if (shift < 0) { shift = 0; }
    return VAL_NUM(shift >= 32 ? 0 : ((unsigned)GET_NUM(v) << shift));
}
Beispiel #26
0
Value doPow(Value a, Value b) {
    if(!IS_NUM(a) || !IS_NUM(b)) { return VERR; }
    return VAL_NUM(pow(GET_NUM(a), GET_NUM(b)));
}
Beispiel #27
0
Value doMod(Value a, Value b) {
    if (!IS_NUM(a) || !IS_NUM(b)) { return VERR; }
    double da = GET_NUM(a);
    double db = GET_NUM(b);
    return VAL_NUM(da - floor(da / db) * db);
}
Beispiel #28
0
// extern __thread jmp_buf jumpBuf;
int VM::call(Value A, int nEffArgs, Value *regs, Stack *stack) {
    Vector<RetInfo> retInfo; // only used if FAST_CALL

    if (!(IS_O_TYPE(A, O_FUNC) || IS_CF(A) || IS_O_TYPE(A, O_CFUNC))) { return -1; }
    regs  = stack->maybeGrow(regs, 256);
    int nExpectedArgs = IS_O_TYPE(A, O_FUNC) ? ((Func *)GET_OBJ(A))->proto->nArgs : NARGS_CFUNC;
    nEffArgs = prepareStackForCall(regs, nExpectedArgs, nEffArgs, gc);

    if (IS_CF(A) || IS_O_TYPE(A, O_CFUNC)) {
        if (IS_CF(A)) {
            tfunc f = GET_CF(A);
            *regs = f(this, CFunc::CFUNC_CALL, 0, regs, nEffArgs);
        } else {
            ((CFunc *) GET_OBJ(A))->call(this, regs, nEffArgs);
        }
        return 0;
    }

    unsigned code = 0;
    Value B;
    Value *ptrC;
    Func *activeFunc = (Func *) GET_OBJ(A);
    unsigned *pc = (unsigned *) activeFunc->proto->code.buf();

    static void *dispatch[] = {
#define _(name) &&name
#include "opcodes.inc"
#undef _
    };

    assert(sizeof(dispatch)/sizeof(dispatch[0]) == N_OPCODES);

    copyUpvals(activeFunc, regs);

    STEP;

 JMP:  pc += OD(code);    STEP;
 JT:   if (!IS_FALSE(*ptrC)) { pc += OD(code);  } STEP;
 JF:   if ( IS_FALSE(*ptrC)) { pc += OD(code);  } STEP;
 JLT:  if (lessThan(A, B))   { pc += OSC(code); } STEP;
 JNIS: if (A != B)           { pc += OSC(code); } STEP;

 FOR: 
    A = *(ptrC + 1);
    B = *(ptrC + 2);
    if (!IS_NUM(A) || !IS_NUM(B)) { goto error; } // E_FOR_NOT_NUMBER
    *ptrC = B;
    if (!(GET_NUM(B) < GET_NUM(A))) { pc += OD(code); }
    STEP;

 LOOP: {
        const double counter = GET_NUM(*ptrC) + 1;
        if (counter < GET_NUM(*(ptrC+1))) { pc += OD(code); }
        *ptrC = VAL_NUM(counter);
        STEP;
    }

 FUNC:
    assert(IS_PROTO(A));
    *ptrC = VAL_OBJ(Func::alloc(gc, PROTO(A), regs + 256, regs, OB(code)));
    STEP;

    // index, A[B]
 GETI: *ptrC = types->type(A)->indexGet(A, B); if (*ptrC == VERR) { goto error; } STEP;
 GETF: *ptrC = types->type(A)->fieldGet(A, B); if (*ptrC == VERR) { goto error; } STEP;
    
 SETI: if (!types->type(*ptrC)->indexSet(*ptrC, A, B)) { goto error; } STEP;
 SETF: if (!types->type(*ptrC)->fieldSet(*ptrC, A, B)) { goto error; } STEP;
    /*
      const int oa = OA(code);
      const int ob = OB(code);
      int top = max(oa, ob) + 1;
      top = max(top, activeFunc->proto->localsTop);
      Value *base = regs + top;
      printf("top %d\n", top);
      base[0] = A;
      base[1] = B;
      int cPos = ptrC - regs;
      DO_CALL(v, 2, regs, base, stack);
      regs[cPos] = base[0];
      break;
      if (*ptrC == VERR) { goto error; }
    */
        
 GETS: *ptrC = getSlice(gc, A, B, regs[OB(code)+1]); if (*ptrC==VERR) { goto error; } STEP;
 SETS: if (setSlice(*ptrC, A, regs[OA(code)+1], B)) { goto error; } STEP;

 RET: {
        regs[0] = A;
        Value *root = stack->base;
        gc->maybeCollect(root, regs - root + 1);
#if FAST_CALL
        if (!retInfo.size()) {
            return 0;
        }
        RetInfo *ri = retInfo.top();
        pc         = ri->pc;
        regs       = stack->base + ri->base;
        activeFunc = ri->func;
        retInfo.pop();
        copyUpvals(activeFunc, regs);
        STEP;
#else
        return 0;
#endif
    }

CALL: { 
        if (!IS_OBJ(A) && !IS_CF(A)) { goto error; } // E_CALL_NOT_FUNC
        int nEffArgs = OSB(code);
        assert(nEffArgs != 0);
        Value *base = ptrC;
#if FAST_CALL
        if (IS_O_TYPE(A, O_FUNC)) {
            Func *f = (Func *) GET_OBJ(A);
            Proto *proto = f->proto;
            prepareStackForCall(base, proto->nArgs, nEffArgs, gc);
            RetInfo *ret = retInfo.push();
            ret->pc    = pc;
            ret->base  = regs - stack->base;
            ret->func  = activeFunc;
            regs = stack->maybeGrow(base, 256);
            copyUpvals(f, regs);
            pc   = proto->code.buf();
            activeFunc = f;
        } else {
#endif
            int ret = DO_CALL(A, nEffArgs, regs, base, stack);
            if (ret) { goto error; }
#if FAST_CALL
        }
#endif
        STEP;
    }
    
 MOVEUP: {
        const int slot = regs + 256 - ptrC;
        activeFunc->setUp(slot, A);
    }
    
 MOVE_R: *ptrC = A; STEP;
 MOVE_I: *ptrC = VAL_NUM(OD(code)); STEP;
 MOVE_V: {
        int id = OA(code);
        *ptrC =
            id == CONST_NIL          ? VNIL :
            id == CONST_EMPTY_STRING ? EMPTY_STRING :
            id == CONST_EMPTY_ARRAY  ? VAL_OBJ(emptyArray->copy(gc)) :
            VAL_OBJ(emptyMap->copy(gc));
        STEP;
    }
    
 MOVE_C: {
        Value v = *pc | (((u64) *(pc+1)) << 32);
        pc += 2;
        if (IS_ARRAY(v)) {
            v = VAL_OBJ(ARRAY(v)->copy(gc));
        } else if (IS_MAP(v)) {
            v = VAL_OBJ(MAP(v)->copy(gc));
        }
        *ptrC = v;
        STEP;
    }
 LEN:    *ptrC = VAL_NUM(len(A)); STEP;
 NOTL:   *ptrC = IS_FALSE(A) ? TRUE : FALSE; STEP;
    // notb: *ptrC = IS_INT(A)? VAL_INT(~getInteger(A)):ERROR(E_WRONG_TYPE); STEP;

 ADD: *ptrC = doAdd(gc, A, B); if (*ptrC == VERR) { goto error; } STEP;
 SUB: *ptrC = BINOP(-, A, B); STEP;
 MUL: *ptrC = BINOP(*, A, B); STEP;
 DIV: *ptrC = BINOP(/, A, B); STEP;
 MOD: *ptrC = doMod(A, B); if (*ptrC == VERR) { goto error; } STEP;
 POW: *ptrC = doPow(A, B); if (*ptrC == VERR) { goto error; } STEP;

 AND: *ptrC = BITOP(&,  A, B); STEP;
 OR:  *ptrC = BITOP(|,  A, B); STEP;
 XOR: *ptrC = BITOP(^,  A, B); STEP;

 SHL_RR: ERR(!IS_NUM(B), E_WRONG_TYPE); *ptrC = doSHL(A, (int)GET_NUM(B)); STEP;
 SHR_RR: ERR(!IS_NUM(B), E_WRONG_TYPE); *ptrC = doSHR(A, (int)GET_NUM(B)); STEP;
 SHL_RI: *ptrC = doSHL(A, OSB(code));       STEP;
 SHR_RI: *ptrC = doSHR(A, OSB(code));       STEP;

 EQ:  *ptrC = equals(A, B)  ? TRUE : FALSE; STEP;
 NEQ: *ptrC = !equals(A, B) ? TRUE : FALSE; STEP;
 IS:  *ptrC = A == B ? TRUE : FALSE; STEP;
 NIS: *ptrC = A != B ? TRUE : FALSE; STEP;

 LT:  *ptrC = lessThan(A, B) ? TRUE : FALSE; STEP;
 LE:  *ptrC = (equals(A, B) || lessThan(A, B)) ? TRUE : FALSE; STEP;

 error: return pc - (unsigned *) activeFunc->proto->code.buf();
}
Beispiel #29
0
bool lessThan(Value a, Value b) {
    return (IS_NUM(a) && IS_NUM(b)) ? GET_NUM(a) < GET_NUM(b) : lessThanNonNum(a, b);
}
void BG_PatchWeaponDef(char* weapon, AttachmentDef* attachment)
{
	Com_Printf(0, "Patching weapon %s using %s\n", *(char**)weapon, attachment->name);

	for (int i = 0; i < attachment->numPatches; i++)
	{
		AttachmentPatch* patch = &attachment->patches[i];
		weaponEntry_t* entry = FindWeaponEntry(patch->fieldName);

		if (!entry)
		{
			Com_Error(1, "Unknown weapon field %s in %s.", patch->fieldName, attachment->name);
		}

		assetType_t assetType;

		switch (entry->type)
		{
			case 0: // string
				{
					char** string = (char**)(weapon + entry->offset);

					if (patch->operation == APO_ADD)
					{
						*string = strdup(va("%s%s", *string, patch->string));
					}
					else
					{
						if (strchr(patch->string, ' '))
						{
							char* oldName = *(char**)(weapon + entry->offset);

							// TODO: needs to be changed to SL?
							*string = DoStringParse(oldName, patch);
							//char* newStr = DoStringParse(oldName, patch);
														
							//free(newStr);
						}
						else
						{
							*string = (char*)patch->string; // ?!
						}
					}

					break;
				}
			case 1: // char[1024]
			case 2: // char[64]
			case 3: // char[256]
				{
					if (strchr(patch->string, ' '))
					{
						char* oldName = (char*)(weapon + entry->offset);

						// TODO: needs to be changed to SL?
						char* str = DoStringParse(oldName, patch);
						sprintf((char*)(weapon + entry->offset), "%s", str);
						free(str);
					}
					else
					{
						sprintf((char*)(weapon + entry->offset), "%s", patch->string);
					}
					break;
				}

#define DO_NUM_PATCH(variable, source) if (patch->operation == APO_ADD) \
				{ \
					variable += source; \
				} else if (patch->operation == APO_MULTIPLY) { \
					variable *= source; \
				} else { \
					variable = source; \
				}

#define GET_NUM(patch) ((patch->type == APT_FLOAT) ? patch->value : ((patch->type == APT_INTEGER) ? patch->integer : atof(patch->string)))

			case 4:
			case 5: // bool-as-int
				{
					//*(int*)(weapon + entry->offset) = patch->integer;

					int oldNum = *(int*)(weapon + entry->offset);
					DO_NUM_PATCH(oldNum, GET_NUM(patch));
					*(int*)(weapon + entry->offset) = oldNum;

					break;
				}
			case 6:
				{
					*(bool*)(weapon + entry->offset) = patch->integer;
					break;
				}

			case 7:
				{
					float oldNum = *(float*)(weapon + entry->offset);

					DO_NUM_PATCH(oldNum, GET_NUM(patch));

					*(float*)(weapon + entry->offset) = oldNum;
					break;
				}
			case 8:
				{
					float oldNum = *(float*)(weapon + entry->offset) / 17.6f;

					DO_NUM_PATCH(oldNum, GET_NUM(patch));

					*(float*)(weapon + entry->offset) = oldNum * 17.6f; // miles/hour - inch/sec
					break;
				}
			case 9:
				{
					float oldNum = *(float*)(weapon + entry->offset) / 1000.f;

					DO_NUM_PATCH(oldNum, GET_NUM(patch));

					*(float*)(weapon + entry->offset) = oldNum * 1000.f;
					break;
				}
#define WEAPON_DO_ARRAY(arr, count) \
	{ \
		for (int i = 0; i < (count); i++) { \
			if (patch->type == APT_STRING && !_stricmp(*(char**)(arr + (i * 4)), patch->string)) { \
				*(int*)(weapon + entry->offset) = i; \
			} \
		} \
	}
			case 16:
				WEAPON_DO_ARRAY(0x795DA0, 4)
				break;
			case 17:
				WEAPON_DO_ARRAY(0x795DB0, 12)
				break;
			case 18:
				WEAPON_DO_ARRAY(0x795E68, 2)
				break;
			case 19:
				WEAPON_DO_ARRAY(0x795E10, 4)
				break;
			case 20:
				WEAPON_DO_ARRAY(0x795E20, 11)
					break;
			case 21:
				WEAPON_DO_ARRAY(0x795E70, 3)
					break;
			case 22:
				WEAPON_DO_ARRAY(0x795E4C, 7)
					break;
			case 23:
				WEAPON_DO_ARRAY(0x795E7C, 6)
					break;
			case 24:
				WEAPON_DO_ARRAY(0x7BE928, *(int*)0x7BDDDC)
					break;
			case 25:
				WEAPON_DO_ARRAY(0x795E94, 3)
					break;
			case 26:
				WEAPON_DO_ARRAY(0x795EA0, 4)
					break;
			case 28:
				WEAPON_DO_ARRAY(0x795EB0, 6)
					break;
			case 29:
				WEAPON_DO_ARRAY(0x795EC8, 3)
					break;
			case 30:
				WEAPON_DO_ARRAY(0x795DE0, 6)
					break;
			case 31:
				WEAPON_DO_ARRAY(0x795DF8, 6)
					break;
			case 32:
				WEAPON_DO_ARRAY(0x795ED4, 7)
					break;
			case 33:
				WEAPON_DO_ARRAY(0x795EF0, 3)
					break;
			case 34:
				WEAPON_DO_ARRAY(0x795EF0, 3) // same as 33
					break;
			case 35:
				WEAPON_DO_ARRAY(0x795EF0, 3) // same as 33
					break;
			case 36:
				WEAPON_DO_ARRAY(0x795EF0, 3) // same as 33
					break;
			case 37:
				WEAPON_DO_ARRAY(0x795EF0, 3) // same as 33
					break;
			/*case 13: // phys collmap
				break;*/
			case 10: // fx
				assetType = ASSET_TYPE_FX;
				goto loadThingAsset;
			case 11: // xmodel
				assetType = ASSET_TYPE_XMODEL;
				goto loadThingAsset;
			case 12: // material
				assetType = ASSET_TYPE_MATERIAL;
				goto loadThingAsset;
			case 14: // soundalias
				assetType = ASSET_TYPE_SOUND;
				goto loadThingAsset;
			case 15: // tracer
				assetType = ASSET_TYPE_TRACER;

loadThingAsset:
				{
					if (strchr(patch->string, ' '))
					{
						char* oldName = **(char***)(weapon + entry->offset);

						char* newStr = DoStringParse(oldName, patch);

						// and get the asset/free the string
						*(void**)(weapon + entry->offset) = DB_FindXAssetHeader(assetType, newStr);

						free(newStr);
					}
					else
					{
						*(void**)(weapon + entry->offset) = DB_FindXAssetHeader(assetType, patch->string);
					}
					break;
				}
			/*case 38: // hideTags
				{
					// hopefully we'll have useful shit here, as if we don't, we're screwed
					// for some reason this code made me go deja vu - seems like I've done SL_ConvertToString before.
					short* tags = (short*)data;
					for (int i = 0; i < 32; i++)
					{
						short tag = tags[i];

						if (tag)
						{
							fprintf(file, "%s%s", SL_ConvertToString(tag), (i == 31 || tags[i + 1] == 0) ? "" : "\n"); // it seems like a newline is needed for all but the last tag
						}
					}
					break;
				}
			case 27: // bounceSound; surface sound
				{
					char*** dat = *(char****)data;
					if (dat != 0)
					{
						char bounceName[128];
						strcpy(bounceName, **dat);
						strrchr(bounceName, '_')[0] = '\0';

						fprintf(file, "%s", bounceName);
					}
					break;
				}*/
			default:
				Com_Error(1, "Unhandled weapon field type %i in %s\n", entry->type, entry->name);
				break;
		}
	}
}