rlm@1: /* rlm@1: ** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $ rlm@1: ** Some generic functions over Lua objects rlm@1: ** See Copyright Notice in lua.h rlm@1: */ rlm@1: rlm@1: #include rlm@1: #include rlm@1: #include rlm@1: #include rlm@1: #include rlm@1: rlm@1: #define lobject_c rlm@1: #define LUA_CORE rlm@1: rlm@1: #include "lua.h" rlm@1: rlm@1: #include "ldo.h" rlm@1: #include "lmem.h" rlm@1: #include "lobject.h" rlm@1: #include "lstate.h" rlm@1: #include "lstring.h" rlm@1: #include "lvm.h" rlm@1: rlm@1: rlm@1: rlm@1: const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; rlm@1: rlm@1: rlm@1: /* rlm@1: ** converts an integer to a "floating point byte", represented as rlm@1: ** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if rlm@1: ** eeeee != 0 and (xxx) otherwise. rlm@1: */ rlm@1: int luaO_int2fb (unsigned int x) { rlm@1: int e = 0; /* expoent */ rlm@1: while (x >= 16) { rlm@1: x = (x+1) >> 1; rlm@1: e++; rlm@1: } rlm@1: if (x < 8) return x; rlm@1: else return ((e+1) << 3) | (cast_int(x) - 8); rlm@1: } rlm@1: rlm@1: rlm@1: /* converts back */ rlm@1: int luaO_fb2int (int x) { rlm@1: int e = (x >> 3) & 31; rlm@1: if (e == 0) return x; rlm@1: else return ((x & 7)+8) << (e - 1); rlm@1: } rlm@1: rlm@1: rlm@1: int luaO_log2 (unsigned int x) { rlm@1: static const lu_byte log_2[256] = { rlm@1: 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, rlm@1: 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, rlm@1: 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, rlm@1: 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, rlm@1: 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, rlm@1: 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, rlm@1: 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, rlm@1: 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 rlm@1: }; rlm@1: int l = -1; rlm@1: while (x >= 256) { l += 8; x >>= 8; } rlm@1: return l + log_2[x]; rlm@1: rlm@1: } rlm@1: rlm@1: rlm@1: int luaO_rawequalObj (const TValue *t1, const TValue *t2) { rlm@1: if (ttype(t1) != ttype(t2)) return 0; rlm@1: else switch (ttype(t1)) { rlm@1: case LUA_TNIL: rlm@1: return 1; rlm@1: case LUA_TNUMBER: rlm@1: return luai_numeq(nvalue(t1), nvalue(t2)); rlm@1: case LUA_TBOOLEAN: rlm@1: return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ rlm@1: case LUA_TLIGHTUSERDATA: rlm@1: return pvalue(t1) == pvalue(t2); rlm@1: default: rlm@1: lua_assert(iscollectable(t1)); rlm@1: return gcvalue(t1) == gcvalue(t2); rlm@1: } rlm@1: } rlm@1: rlm@1: rlm@1: int luaO_str2d (const char *s, lua_Number *result) { rlm@1: char *endptr; rlm@1: *result = lua_str2number(s, &endptr); rlm@1: if (endptr == s) return 0; /* conversion failed */ rlm@1: if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */ rlm@1: *result = cast_num(strtoul(s, &endptr, 16)); rlm@1: if (*endptr == '\0') return 1; /* most common case */ rlm@1: while (isspace(cast(unsigned char, *endptr))) endptr++; rlm@1: if (*endptr != '\0') return 0; /* invalid trailing characters? */ rlm@1: return 1; rlm@1: } rlm@1: rlm@1: rlm@1: rlm@1: static void pushstr (lua_State *L, const char *str) { rlm@1: setsvalue2s(L, L->top, luaS_new(L, str)); rlm@1: incr_top(L); rlm@1: } rlm@1: rlm@1: rlm@1: /* this function handles only `%d', `%c', %f, %p, and `%s' formats */ rlm@1: const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { rlm@1: int n = 1; rlm@1: pushstr(L, ""); rlm@1: for (;;) { rlm@1: const char *e = strchr(fmt, '%'); rlm@1: if (e == NULL) break; rlm@1: setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt)); rlm@1: incr_top(L); rlm@1: switch (*(e+1)) { rlm@1: case 's': { rlm@1: const char *s = va_arg(argp, char *); rlm@1: if (s == NULL) s = "(null)"; rlm@1: pushstr(L, s); rlm@1: break; rlm@1: } rlm@1: case 'c': { rlm@1: char buff[2]; rlm@1: buff[0] = cast(char, va_arg(argp, int)); rlm@1: buff[1] = '\0'; rlm@1: pushstr(L, buff); rlm@1: break; rlm@1: } rlm@1: case 'd': { rlm@1: setnvalue(L->top, cast_num(va_arg(argp, int))); rlm@1: incr_top(L); rlm@1: break; rlm@1: } rlm@1: case 'f': { rlm@1: setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); rlm@1: incr_top(L); rlm@1: break; rlm@1: } rlm@1: case 'p': { rlm@1: char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ rlm@1: sprintf(buff, "%p", va_arg(argp, void *)); rlm@1: pushstr(L, buff); rlm@1: break; rlm@1: } rlm@1: case '%': { rlm@1: pushstr(L, "%"); rlm@1: break; rlm@1: } rlm@1: default: { rlm@1: char buff[3]; rlm@1: buff[0] = '%'; rlm@1: buff[1] = *(e+1); rlm@1: buff[2] = '\0'; rlm@1: pushstr(L, buff); rlm@1: break; rlm@1: } rlm@1: } rlm@1: n += 2; rlm@1: fmt = e+2; rlm@1: } rlm@1: pushstr(L, fmt); rlm@1: luaV_concat(L, n+1, cast_int(L->top - L->base) - 1); rlm@1: L->top -= n; rlm@1: return svalue(L->top - 1); rlm@1: } rlm@1: rlm@1: rlm@1: const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { rlm@1: const char *msg; rlm@1: va_list argp; rlm@1: va_start(argp, fmt); rlm@1: msg = luaO_pushvfstring(L, fmt, argp); rlm@1: va_end(argp); rlm@1: return msg; rlm@1: } rlm@1: rlm@1: rlm@1: void luaO_chunkid (char *out, const char *source, size_t bufflen) { rlm@1: if (*source == '=') { rlm@1: strncpy(out, source+1, bufflen); /* remove first char */ rlm@1: out[bufflen-1] = '\0'; /* ensures null termination */ rlm@1: } rlm@1: else { /* out = "source", or "...source" */ rlm@1: if (*source == '@') { rlm@1: size_t l; rlm@1: source++; /* skip the `@' */ rlm@1: bufflen -= sizeof(" '...' "); rlm@1: l = strlen(source); rlm@1: strcpy(out, ""); rlm@1: if (l > bufflen) { rlm@1: source += (l-bufflen); /* get last part of file name */ rlm@1: strcat(out, "..."); rlm@1: } rlm@1: strcat(out, source); rlm@1: } rlm@1: else { /* out = [string "string"] */ rlm@1: size_t len = strcspn(source, "\n\r"); /* stop at first newline */ rlm@1: bufflen -= sizeof(" [string \"...\"] "); rlm@1: if (len > bufflen) len = bufflen; rlm@1: strcpy(out, "[string \""); rlm@1: if (source[len] != '\0') { /* must truncate? */ rlm@1: strncat(out, source, len); rlm@1: strcat(out, "..."); rlm@1: } rlm@1: else rlm@1: strcat(out, source); rlm@1: strcat(out, "\"]"); rlm@1: } rlm@1: } rlm@1: }