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