void fx_Number(txMachine* the) { if (mxResult->kind == XS_UNDEFINED_KIND) { if (mxArgc > 0) { txInteger anInteger; txNumber aNumber; fxToNumber(the, mxArgv(0)); anInteger = (txInteger)mxArgv(0)->value.number; aNumber = anInteger; if (mxArgv(0)->value.number == aNumber) { mxResult->value.integer = anInteger; mxResult->kind = XS_INTEGER_KIND; } else *mxResult = *mxArgv(0); } else { mxResult->kind = XS_NUMBER_KIND; mxResult->value.number = 0; } } else { txSlot* aNumber = fxGetInstance(the, mxResult); mxCheckNumber(aNumber); if (mxArgc > 0) { fxToNumber(the, mxArgv(0)); aNumber->next->value.number = mxArgv(0)->value.number; } } }
void fx_setTimeout(txMachine* the) { txTimeoutData* data; #if mxMacOSX CFRunLoopTimerContext context; #endif txNumber duration = fxToNumber(the, mxArgv(1)) / 1000; data = c_malloc(sizeof(txTimeoutData)); mxElseError(data); c_memset(data, 0, sizeof(txTimeoutData)); data->the = the; data->function.kind = mxArgv(0)->kind; data->function.value = mxArgv(0)->value; fxRemember(the, &(data->function)); if (mxArgc > 2) { data->argument.kind = mxArgv(2)->kind; data->argument.value = mxArgv(2)->value; } fxRemember(the, &(data->argument)); #if mxMacOSX memset(&context, 0, sizeof(context)); context.info = data; context.release = fx_setTimeoutRelease; data->timer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + duration, 0, 0, 0, fx_setTimeoutCallback, &context); CFRunLoopAddTimer(CFRunLoopGetCurrent(), data->timer, gxRunLoopMode); #endif }
void fx_isNaN(txMachine* the) { int fpclass; txNumber number = (mxArgc < 1) ? C_NAN : fxToNumber(the, mxArgv(0)); mxResult->kind = XS_BOOLEAN_KIND; mxResult->value.boolean = 0; fpclass = c_fpclassify(number); if (fpclass == FP_NAN) mxResult->value.boolean = 1; }
txIndex fxArgToArrayLimit(txMachine* the, txInteger argi) { if (mxArgc > argi) { txNumber i = c_trunc(fxToNumber(the, mxArgv(argi))); if (c_isnan(i)) i = 0; else if (i < 0) i = 0; else if (i > XS_MAX_INDEX) i = XS_MAX_INDEX; return (txIndex)i; } return XS_MAX_INDEX; }
void fx_Number_toString(txMachine* the) { txSlot* aNumber; txSlot* aProperty; txInteger aRadix; aNumber = fxGetInstance(the, mxThis); mxCheckNumber(aNumber); aProperty = aNumber->next; if (mxArgc > 0) { aRadix = fxToInteger(the, mxArgv(0)); if (aRadix) { if ((aRadix < 2) || (36 < aRadix)) mxDebug0(the, XS_RANGE_ERROR, "invalid radix"); } else aRadix = 10; } else aRadix = 10; mxResult->kind = aProperty->kind; mxResult->value = aProperty->value; if (aRadix == 10) fxToString(the, mxResult); else { static char gxDigits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; char aBuffer[256]; txString aString; txNumber aValue; txBoolean aMinus; fxToNumber(the, mxResult); aString = aBuffer + sizeof(aBuffer); *(--aString) = 0; aValue = mxResult->value.number; if (aValue < 0) { aMinus = 1; aValue = -aValue; } else aMinus = 0; do { *(--aString) = gxDigits[(txInteger)c_fmod(aValue, aRadix)]; aValue = aValue / aRadix; } while (aValue >= 1); if (aMinus) *(--aString) = '-'; fxCopyStringC(the, mxResult, aString); } }
txSlot* fxCheckNumber(txMachine* the, txSlot* it) { txSlot* result = C_NULL; if (it->kind == XS_INTEGER_KIND) { fxToNumber(the, it); result = it; } else if (it->kind == XS_NUMBER_KIND) result = it; else if (it->kind == XS_REFERENCE_KIND) { txSlot* instance = it->value.reference; it = instance->next; if ((instance->flag & XS_VALUE_FLAG) && (it->kind == XS_NUMBER_KIND) && (instance != mxNumberPrototype.value.reference)) result = it; } return result; }
txIndex fxArgToIndex(txMachine* the, txInteger argi, txIndex index, txIndex length) { if (mxArgc > argi) { txNumber c = length; txNumber i = c_trunc(fxToNumber(the, mxArgv(argi))); if (c_isnan(i)) i = 0; if (i < 0) { i = c + i; if (i < 0) i = 0; } else if (i > c) i = c; index = (txIndex)i; } return index; }
int fxCompareArrayItem(txMachine* the, txSlot* function, txSlot* array, txInteger i) { txSlot* address = array->value.array.address; txSlot* a = address + i; txSlot* b = the->stack; int result; if (!(a->ID)) result = (!(b->ID)) ? 0 : 1; else if (!(b->ID)) result = -1; else if (a->kind == XS_UNDEFINED_KIND) result = (b->kind == XS_UNDEFINED_KIND) ? 0 : 1; else if (b->kind == XS_UNDEFINED_KIND) result = -1; else { mxPushSlot(a); mxPushSlot(b); if (function) { /* ARGC */ mxPushInteger(2); /* THIS */ mxPushSlot(mxThis); /* FUNCTION */ mxPushReference(function); fxCall(the); if (the->stack->kind == XS_INTEGER_KIND) result = the->stack->value.integer; else { txNumber number = fxToNumber(the, the->stack); result = (number < 0) ? -1 : (number > 0) ? 1 : 0; } the->stack++; } else { fxToString(the, the->stack + 1); fxToString(the, the->stack); result = c_strcmp((the->stack + 1)->value.string, the->stack->value.string); the->stack += 2; } } return result; }
void fx_Date_prototype_setTime(txMachine* the) { txSlot* slot = fxCheckDate(the, mxThis); if (!slot) mxTypeError("this is no date"); if (mxArgc < 1) slot->value.number = C_NAN; else { txNumber number = fxToNumber(the, mxArgv(0)); int fpclass = c_fpclassify(number); if (fpclass != FP_NAN) { if (c_fabs(number) > 8.64e15) number = C_NAN; else number = c_trunc(number); } slot->value.number = number; } mxResult->value.number = slot->value.number; mxResult->kind = XS_NUMBER_KIND; }
void fx_Number(txMachine* the) { txSlot* slot = fxCheckNumber(the, mxThis); txNumber value = 0; if (mxArgc > 0) value = fxToNumber(the, mxArgv(0)); if (slot) slot->value.number = value; else { txInteger integer = (txInteger)value; txNumber number = integer; if (number == value) { mxResult->kind = XS_INTEGER_KIND; mxResult->value.integer = integer; } else { mxResult->kind = XS_NUMBER_KIND; mxResult->value.number = value; } } }
void fx_Date(txMachine* the) { txTimeDescription td; c_timeval tv; char buffer[256]; c_time_t time; txNumber number; if ((mxThis->kind == XS_REFERENCE_KIND) && ((mxThis->value.reference->flag & XS_SHARED_FLAG) == 0)) { txSlot* anInstance = mxThis->value.reference; if (mxIsDate(anInstance)) { if (mxArgc > 1) { td.tm.tm_year = fxToInteger(the, mxArgv(0)); if ((td.tm.tm_year < 0) || (99 < td.tm.tm_year)) td.tm.tm_year -= 1900; td.tm.tm_mon = fxToInteger(the, mxArgv(1)); if (mxArgc > 2) td.tm.tm_mday = fxToInteger(the, mxArgv(2)); else td.tm.tm_mday = 1; if (mxArgc > 3) td.tm.tm_hour = fxToInteger(the, mxArgv(3)); else td.tm.tm_hour = 0; if (mxArgc > 4) td.tm.tm_min = fxToInteger(the, mxArgv(4)); else td.tm.tm_min = 0; if (mxArgc > 5) td.tm.tm_sec = fxToInteger(the, mxArgv(5)); else td.tm.tm_sec = 0; if (mxArgc > 6) td.ms = fxToInteger(the, mxArgv(6)); else td.ms = 0; td.tm.tm_isdst = -1; time = c_mktime(&(td.tm)); if (time == -1) number = NAN; else number = (time * 1000.0) + td.ms; } else if (mxArgc > 0) { number = fxToNumber(the, mxArgv(0)); } else { c_gettimeofday(&tv, NULL); // According to 15.9.1.1, time precision in JS is milliseconds number = ((txNumber)(tv.tv_sec) * 1000.0) + ((txNumber)(tv.tv_usec / 1000)); } anInstance->next->value.number = number; *mxResult = *mxThis; } return; } { c_time_t sec; c_gettimeofday(&tv, NULL); sec = tv.tv_sec; // necessary because on Windows tv.tv_sec is a long (32 bits), which is diffrent from time_t (64 bits) td.tm = *c_localtime(&sec); c_strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S", &(td.tm)); fxCopyStringC(the, mxResult, buffer); } }