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