OBJ readNumber(OBJ inStream, char firstChar, int isNegative){ //printf(YEL "\nreadNumber>" RESET); /* * TO-DO refactor! */ jscheme_int64 *iVal = NULL; char ch; OBJ retVal; // substract the ASCII value of '0' from char to get the actual value between 0 and 9. jscheme_int64 start = (jscheme_int64) firstChar - '0'; if(isNegative) start *= -1; iVal = &start; while( isDigit( ch = nextChar(inStream) )){ //iVal = iVal * 10 + ( (int)ch - '0'); jscheme_int64 ch_val = (jscheme_int64) ch - '0'; if(isNegative){ int mul = __builtin_smull_overflow(*iVal, 10, iVal); int sub = __builtin_ssubl_overflow(*iVal, ch_val, iVal); if( mul || sub ){ if(thisIsTheEnd(inStream)){ prompt_on(); } js_error("readNumber: integer underflow", newInteger(*iVal)); } }else{ int mul = __builtin_smull_overflow(*iVal, 10, iVal); int add = __builtin_saddl_overflow(*iVal, ch_val, iVal); if( mul || add ){ if(thisIsTheEnd(inStream)){ prompt_on(); } js_error("readNumber: integer overflow", newInteger(*iVal)); } } } unreadChar(inStream, ch); retVal = newInteger( *iVal ); return retVal; }
OBJ builtin_minus(int numArgs){ OBJ theArg; switch (numArgs){ case 0: js_error("(-): at least one arg expected", js_nil); /* NOT REACHED */ case 1: theArg = POP(); if( !ISINTEGER(theArg)){ js_error("(-): non-integer argument", theArg); } return newInteger( -INTVAL(theArg) ); default: theArg = NTH_ARG(numArgs, 0); if( !ISINTEGER(theArg)){ POPN(numArgs); js_error("(-): non-integer argument", theArg); } jscheme_int64 *difference = NULL; jscheme_int64 start = INTVAL(theArg); difference = &start; for(int i = 1; i < numArgs; i++){ OBJ nextArg = NTH_ARG(numArgs, i); if( !ISINTEGER(nextArg)){ POPN(numArgs); js_error("(-): non-integer argument", theArg); } if(__builtin_ssubl_overflow(*difference, INTVAL(nextArg), difference)){ // clean stack POPN(numArgs); js_error("(-): integer overflow", newInteger(*difference)); }; } POPN(numArgs); return newInteger(*difference); } /* NOT REACHED */ return js_nil; }
extern "C" Box* sub_i64_i64(i64 lhs, i64 rhs) { i64 result; if (!__builtin_ssubl_overflow(lhs, rhs, &result)) return boxInt(result); return longSub(boxLong(lhs), boxLong(rhs)); }