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