1eda14cbcSMatt Macy /* 2eda14cbcSMatt Macy ** $Id: lobject.c,v 2.58.1.1 2013/04/12 18:48:47 roberto Exp $ 3eda14cbcSMatt Macy ** Some generic functions over Lua objects 4eda14cbcSMatt Macy ** See Copyright Notice in lua.h 5eda14cbcSMatt Macy */ 6eda14cbcSMatt Macy 7eda14cbcSMatt Macy #define lobject_c 8eda14cbcSMatt Macy #define LUA_CORE 9eda14cbcSMatt Macy 10eda14cbcSMatt Macy #include <sys/lua/lua.h> 11eda14cbcSMatt Macy 12eda14cbcSMatt Macy #include "lctype.h" 13eda14cbcSMatt Macy #include "ldebug.h" 14eda14cbcSMatt Macy #include "ldo.h" 15eda14cbcSMatt Macy #include "lmem.h" 16eda14cbcSMatt Macy #include "lobject.h" 17eda14cbcSMatt Macy #include "lstate.h" 18eda14cbcSMatt Macy #include "lstring.h" 19eda14cbcSMatt Macy #include "lvm.h" 20eda14cbcSMatt Macy 21eda14cbcSMatt Macy 22eda14cbcSMatt Macy 23eda14cbcSMatt Macy LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT}; 24eda14cbcSMatt Macy 25eda14cbcSMatt Macy 26eda14cbcSMatt Macy /* 27eda14cbcSMatt Macy ** converts an integer to a "floating point byte", represented as 28eda14cbcSMatt Macy ** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if 29eda14cbcSMatt Macy ** eeeee != 0 and (xxx) otherwise. 30eda14cbcSMatt Macy */ 31eda14cbcSMatt Macy int luaO_int2fb (unsigned int x) { 32eda14cbcSMatt Macy int e = 0; /* exponent */ 33eda14cbcSMatt Macy if (x < 8) return x; 34eda14cbcSMatt Macy while (x >= 0x10) { 35eda14cbcSMatt Macy x = (x+1) >> 1; 36eda14cbcSMatt Macy e++; 37eda14cbcSMatt Macy } 38eda14cbcSMatt Macy return ((e+1) << 3) | (cast_int(x) - 8); 39eda14cbcSMatt Macy } 40eda14cbcSMatt Macy 41eda14cbcSMatt Macy 42eda14cbcSMatt Macy /* converts back */ 43eda14cbcSMatt Macy int luaO_fb2int (int x) { 44eda14cbcSMatt Macy int e = (x >> 3) & 0x1f; 45eda14cbcSMatt Macy if (e == 0) return x; 46eda14cbcSMatt Macy else return ((x & 7) + 8) << (e - 1); 47eda14cbcSMatt Macy } 48eda14cbcSMatt Macy 49eda14cbcSMatt Macy 50eda14cbcSMatt Macy int luaO_ceillog2 (unsigned int x) { 51eda14cbcSMatt Macy static const lu_byte log_2[256] = { 52eda14cbcSMatt Macy 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, 53eda14cbcSMatt Macy 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, 54eda14cbcSMatt Macy 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, 55eda14cbcSMatt Macy 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, 56eda14cbcSMatt Macy 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, 57eda14cbcSMatt Macy 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, 58eda14cbcSMatt Macy 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, 59eda14cbcSMatt Macy 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 60eda14cbcSMatt Macy }; 61eda14cbcSMatt Macy int l = 0; 62eda14cbcSMatt Macy x--; 63eda14cbcSMatt Macy while (x >= 256) { l += 8; x >>= 8; } 64eda14cbcSMatt Macy return l + log_2[x]; 65eda14cbcSMatt Macy } 66eda14cbcSMatt Macy 67eda14cbcSMatt Macy 68eda14cbcSMatt Macy lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2) { 69eda14cbcSMatt Macy switch (op) { 70eda14cbcSMatt Macy case LUA_OPADD: return luai_numadd(NULL, v1, v2); 71eda14cbcSMatt Macy case LUA_OPSUB: return luai_numsub(NULL, v1, v2); 72eda14cbcSMatt Macy case LUA_OPMUL: return luai_nummul(NULL, v1, v2); 73eda14cbcSMatt Macy case LUA_OPDIV: return luai_numdiv(NULL, v1, v2); 74eda14cbcSMatt Macy case LUA_OPMOD: return luai_nummod(NULL, v1, v2); 75eda14cbcSMatt Macy case LUA_OPPOW: return luai_numpow(NULL, v1, v2); 76eda14cbcSMatt Macy case LUA_OPUNM: return luai_numunm(NULL, v1); 77eda14cbcSMatt Macy default: lua_assert(0); return 0; 78eda14cbcSMatt Macy } 79eda14cbcSMatt Macy } 80eda14cbcSMatt Macy 81eda14cbcSMatt Macy 82eda14cbcSMatt Macy int luaO_hexavalue (int c) { 83eda14cbcSMatt Macy if (lisdigit(c)) return c - '0'; 84eda14cbcSMatt Macy else return ltolower(c) - 'a' + 10; 85eda14cbcSMatt Macy } 86eda14cbcSMatt Macy 87eda14cbcSMatt Macy 88eda14cbcSMatt Macy #if !defined(lua_strx2number) 89eda14cbcSMatt Macy 90eda14cbcSMatt Macy 91eda14cbcSMatt Macy 92eda14cbcSMatt Macy static int isneg (const char **s) { 93eda14cbcSMatt Macy if (**s == '-') { (*s)++; return 1; } 94eda14cbcSMatt Macy else if (**s == '+') (*s)++; 95eda14cbcSMatt Macy return 0; 96eda14cbcSMatt Macy } 97eda14cbcSMatt Macy 98eda14cbcSMatt Macy 99eda14cbcSMatt Macy static lua_Number readhexa (const char **s, lua_Number r, int *count) { 100eda14cbcSMatt Macy for (; lisxdigit(cast_uchar(**s)); (*s)++) { /* read integer part */ 101eda14cbcSMatt Macy r = (r * cast_num(16.0)) + cast_num(luaO_hexavalue(cast_uchar(**s))); 102eda14cbcSMatt Macy (*count)++; 103eda14cbcSMatt Macy } 104eda14cbcSMatt Macy return r; 105eda14cbcSMatt Macy } 106eda14cbcSMatt Macy 107eda14cbcSMatt Macy 108eda14cbcSMatt Macy /* 109eda14cbcSMatt Macy ** convert an hexadecimal numeric string to a number, following 110eda14cbcSMatt Macy ** C99 specification for 'strtod' 111eda14cbcSMatt Macy */ 112eda14cbcSMatt Macy static lua_Number lua_strx2number (const char *s, char **endptr) { 113eda14cbcSMatt Macy lua_Number r = 0.0; 114eda14cbcSMatt Macy int e = 0, i = 0; 115eda14cbcSMatt Macy int neg = 0; /* 1 if number is negative */ 116eda14cbcSMatt Macy *endptr = cast(char *, s); /* nothing is valid yet */ 117eda14cbcSMatt Macy while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ 118eda14cbcSMatt Macy neg = isneg(&s); /* check signal */ 119eda14cbcSMatt Macy if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ 120eda14cbcSMatt Macy return 0.0; /* invalid format (no '0x') */ 121eda14cbcSMatt Macy s += 2; /* skip '0x' */ 122eda14cbcSMatt Macy r = readhexa(&s, r, &i); /* read integer part */ 123eda14cbcSMatt Macy if (*s == '.') { 124eda14cbcSMatt Macy s++; /* skip dot */ 125eda14cbcSMatt Macy r = readhexa(&s, r, &e); /* read fractional part */ 126eda14cbcSMatt Macy } 127eda14cbcSMatt Macy if (i == 0 && e == 0) 128eda14cbcSMatt Macy return 0.0; /* invalid format (no digit) */ 129eda14cbcSMatt Macy e *= -4; /* each fractional digit divides value by 2^-4 */ 130eda14cbcSMatt Macy *endptr = cast(char *, s); /* valid up to here */ 131eda14cbcSMatt Macy if (*s == 'p' || *s == 'P') { /* exponent part? */ 132eda14cbcSMatt Macy int exp1 = 0; 133eda14cbcSMatt Macy int neg1; 134eda14cbcSMatt Macy s++; /* skip 'p' */ 135eda14cbcSMatt Macy neg1 = isneg(&s); /* signal */ 136eda14cbcSMatt Macy if (!lisdigit(cast_uchar(*s))) 137eda14cbcSMatt Macy goto ret; /* must have at least one digit */ 138eda14cbcSMatt Macy while (lisdigit(cast_uchar(*s))) /* read exponent */ 139eda14cbcSMatt Macy exp1 = exp1 * 10 + *(s++) - '0'; 140eda14cbcSMatt Macy if (neg1) exp1 = -exp1; 141eda14cbcSMatt Macy e += exp1; 142eda14cbcSMatt Macy } 143eda14cbcSMatt Macy *endptr = cast(char *, s); /* valid up to here */ 144eda14cbcSMatt Macy ret: 145eda14cbcSMatt Macy if (neg) r = -r; 146*bb2d13b6SMartin Matuska return ((e >= 0) ? (r * (1ULL << e)) : (r / (1ULL << -e))); 147eda14cbcSMatt Macy } 148eda14cbcSMatt Macy 149eda14cbcSMatt Macy #endif 150eda14cbcSMatt Macy 151eda14cbcSMatt Macy 152eda14cbcSMatt Macy int luaO_str2d (const char *s, size_t len, lua_Number *result) { 153eda14cbcSMatt Macy char *endptr; 154eda14cbcSMatt Macy if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */ 155eda14cbcSMatt Macy return 0; 156eda14cbcSMatt Macy else if (strpbrk(s, "xX")) /* hexa? */ 157eda14cbcSMatt Macy *result = lua_strx2number(s, &endptr); 158eda14cbcSMatt Macy else 159eda14cbcSMatt Macy *result = lua_str2number(s, &endptr); 160eda14cbcSMatt Macy if (endptr == s) return 0; /* nothing recognized */ 161eda14cbcSMatt Macy while (lisspace(cast_uchar(*endptr))) endptr++; 162eda14cbcSMatt Macy return (endptr == s + len); /* OK if no trailing characters */ 163eda14cbcSMatt Macy } 164eda14cbcSMatt Macy 165eda14cbcSMatt Macy 166eda14cbcSMatt Macy 167eda14cbcSMatt Macy static void pushstr (lua_State *L, const char *str, size_t l) { 168eda14cbcSMatt Macy setsvalue2s(L, L->top++, luaS_newlstr(L, str, l)); 169eda14cbcSMatt Macy } 170eda14cbcSMatt Macy 171eda14cbcSMatt Macy 172eda14cbcSMatt Macy /* this function handles only `%d', `%c', %f, %p, and `%s' formats */ 173eda14cbcSMatt Macy const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { 174eda14cbcSMatt Macy int n = 0; 175eda14cbcSMatt Macy for (;;) { 176eda14cbcSMatt Macy const char *e = strchr(fmt, '%'); 177eda14cbcSMatt Macy if (e == NULL) break; 178eda14cbcSMatt Macy luaD_checkstack(L, 2); /* fmt + item */ 179eda14cbcSMatt Macy pushstr(L, fmt, e - fmt); 180eda14cbcSMatt Macy switch (*(e+1)) { 181eda14cbcSMatt Macy case 's': { 182eda14cbcSMatt Macy const char *s = va_arg(argp, char *); 183eda14cbcSMatt Macy if (s == NULL) s = "(null)"; 184eda14cbcSMatt Macy pushstr(L, s, strlen(s)); 185eda14cbcSMatt Macy break; 186eda14cbcSMatt Macy } 187eda14cbcSMatt Macy case 'c': { 188eda14cbcSMatt Macy char buff; 189eda14cbcSMatt Macy buff = cast(char, va_arg(argp, int)); 190eda14cbcSMatt Macy pushstr(L, &buff, 1); 191eda14cbcSMatt Macy break; 192eda14cbcSMatt Macy } 193eda14cbcSMatt Macy case 'd': { 194eda14cbcSMatt Macy setnvalue(L->top++, cast_num(va_arg(argp, int))); 195eda14cbcSMatt Macy break; 196eda14cbcSMatt Macy } 197eda14cbcSMatt Macy case 'f': { 198eda14cbcSMatt Macy setnvalue(L->top++, cast_num(va_arg(argp, l_uacNumber))); 199eda14cbcSMatt Macy break; 200eda14cbcSMatt Macy } 201eda14cbcSMatt Macy case 'p': { 202eda14cbcSMatt Macy char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ 203eda14cbcSMatt Macy int l = lcompat_sprintf(buff, sizeof(buff), "%p", va_arg(argp, void *)); 204eda14cbcSMatt Macy pushstr(L, buff, l); 205eda14cbcSMatt Macy break; 206eda14cbcSMatt Macy } 207eda14cbcSMatt Macy case '%': { 208eda14cbcSMatt Macy pushstr(L, "%", 1); 209eda14cbcSMatt Macy break; 210eda14cbcSMatt Macy } 211eda14cbcSMatt Macy default: { 212eda14cbcSMatt Macy luaG_runerror(L, 213eda14cbcSMatt Macy "invalid option " LUA_QL("%%%c") " to " LUA_QL("lua_pushfstring"), 214eda14cbcSMatt Macy *(e + 1)); 215eda14cbcSMatt Macy } 216eda14cbcSMatt Macy } 217eda14cbcSMatt Macy n += 2; 218eda14cbcSMatt Macy fmt = e+2; 219eda14cbcSMatt Macy } 220eda14cbcSMatt Macy luaD_checkstack(L, 1); 221eda14cbcSMatt Macy pushstr(L, fmt, strlen(fmt)); 222eda14cbcSMatt Macy if (n > 0) luaV_concat(L, n + 1); 223eda14cbcSMatt Macy return svalue(L->top - 1); 224eda14cbcSMatt Macy } 225eda14cbcSMatt Macy 226eda14cbcSMatt Macy 227eda14cbcSMatt Macy const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { 228eda14cbcSMatt Macy const char *msg; 229eda14cbcSMatt Macy va_list argp; 230eda14cbcSMatt Macy va_start(argp, fmt); 231eda14cbcSMatt Macy msg = luaO_pushvfstring(L, fmt, argp); 232eda14cbcSMatt Macy va_end(argp); 233eda14cbcSMatt Macy return msg; 234eda14cbcSMatt Macy } 235eda14cbcSMatt Macy 236eda14cbcSMatt Macy 237eda14cbcSMatt Macy /* number of chars of a literal string without the ending \0 */ 238eda14cbcSMatt Macy #define LL(x) (sizeof(x)/sizeof(char) - 1) 239eda14cbcSMatt Macy 240eda14cbcSMatt Macy #define RETS "..." 241eda14cbcSMatt Macy #define PRE "[string \"" 242eda14cbcSMatt Macy #define POS "\"]" 243eda14cbcSMatt Macy 244eda14cbcSMatt Macy #define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) ) 245eda14cbcSMatt Macy 246eda14cbcSMatt Macy void luaO_chunkid (char *out, const char *source, size_t bufflen) { 247eda14cbcSMatt Macy size_t l = strlen(source); 248eda14cbcSMatt Macy if (*source == '=') { /* 'literal' source */ 249eda14cbcSMatt Macy if (l <= bufflen) /* small enough? */ 250eda14cbcSMatt Macy memcpy(out, source + 1, l * sizeof(char)); 251eda14cbcSMatt Macy else { /* truncate it */ 252eda14cbcSMatt Macy addstr(out, source + 1, bufflen - 1); 253eda14cbcSMatt Macy *out = '\0'; 254eda14cbcSMatt Macy } 255eda14cbcSMatt Macy } 256eda14cbcSMatt Macy else if (*source == '@') { /* file name */ 257eda14cbcSMatt Macy if (l <= bufflen) /* small enough? */ 258eda14cbcSMatt Macy memcpy(out, source + 1, l * sizeof(char)); 259eda14cbcSMatt Macy else { /* add '...' before rest of name */ 260eda14cbcSMatt Macy addstr(out, RETS, LL(RETS)); 261eda14cbcSMatt Macy bufflen -= LL(RETS); 262eda14cbcSMatt Macy memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char)); 263eda14cbcSMatt Macy } 264eda14cbcSMatt Macy } 265eda14cbcSMatt Macy else { /* string; format as [string "source"] */ 266eda14cbcSMatt Macy const char *nl = strchr(source, '\n'); /* find first new line (if any) */ 267eda14cbcSMatt Macy addstr(out, PRE, LL(PRE)); /* add prefix */ 268eda14cbcSMatt Macy bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */ 269eda14cbcSMatt Macy if (l < bufflen && nl == NULL) { /* small one-line source? */ 270eda14cbcSMatt Macy addstr(out, source, l); /* keep it */ 271eda14cbcSMatt Macy } 272eda14cbcSMatt Macy else { 273eda14cbcSMatt Macy if (nl != NULL) l = nl - source; /* stop at first newline */ 274eda14cbcSMatt Macy if (l > bufflen) l = bufflen; 275eda14cbcSMatt Macy addstr(out, source, l); 276eda14cbcSMatt Macy addstr(out, RETS, LL(RETS)); 277eda14cbcSMatt Macy } 278eda14cbcSMatt Macy memcpy(out, POS, (LL(POS) + 1) * sizeof(char)); 279eda14cbcSMatt Macy } 280eda14cbcSMatt Macy } 281