1 /*
2 ** $Id$
3 ** Some generic functions over Lua objects
4 ** See Copyright Notice in lua.h
5 */
6 
7 #include "common/util.h"
8 
9 #define lobject_c
10 #define LUA_CORE
11 
12 #include "lua.h"
13 
14 #include "ldo.h"
15 #include "lmem.h"
16 #include "lobject.h"
17 #include "lstate.h"
18 #include "lstring.h"
19 #include "lvm.h"
20 
21 
22 
23 const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL};
24 
25 
26 /*
27 ** converts an integer to a "floating point byte", represented as
28 ** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if
29 ** eeeee != 0 and (xxx) otherwise.
30 */
luaO_int2fb(unsigned int x)31 int luaO_int2fb (unsigned int x) {
32   int e = 0;  /* expoent */
33   while (x >= 16) {
34     x = (x+1) >> 1;
35     e++;
36   }
37   if (x < 8) return x;
38   else return ((e+1) << 3) | (cast_int(x) - 8);
39 }
40 
41 
42 /* converts back */
luaO_fb2int(int x)43 int luaO_fb2int (int x) {
44   int e = (x >> 3) & 31;
45   if (e == 0) return x;
46   else return ((x & 7)+8) << (e - 1);
47 }
48 
49 
luaO_log2(unsigned int x)50 int luaO_log2 (unsigned int x) {
51   static const lu_byte log_2[256] = {
52     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,
53     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,
54     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,
55     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     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,
57     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     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     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   };
61   int l = -1;
62   while (x >= 256) { l += 8; x >>= 8; }
63   return l + log_2[x];
64 
65 }
66 
67 
luaO_rawequalObj(const TValue * t1,const TValue * t2)68 int luaO_rawequalObj (const TValue *t1, const TValue *t2) {
69   if (ttype(t1) != ttype(t2)) return 0;
70   else switch (ttype(t1)) {
71     case LUA_TNIL:
72       return 1;
73     case LUA_TNUMBER:
74       return luai_numeq(nvalue(t1), nvalue(t2));
75     case LUA_TBOOLEAN:
76       return bvalue(t1) == bvalue(t2);  /* boolean true must be 1 !! */
77     case LUA_TLIGHTUSERDATA:
78       return pvalue(t1) == pvalue(t2);
79     default:
80       lua_assert(iscollectable(t1));
81       return gcvalue(t1) == gcvalue(t2);
82   }
83 }
84 
85 
luaO_str2d(const char * s,lua_Number * result)86 int luaO_str2d (const char *s, lua_Number *result) {
87   char *endptr;
88   *result = lua_str2number(s, &endptr);
89   if (endptr == s) return 0;  /* conversion failed */
90   if (*endptr == 'x' || *endptr == 'X')  /* maybe an hexadecimal constant? */
91     *result = cast_num(strtoul(s, &endptr, 16));
92   if (*endptr == '\0') return 1;  /* most common case */
93   while (Common::isSpace(*endptr)) endptr++;
94   if (*endptr != '\0') return 0;  /* invalid trailing characters? */
95   return 1;
96 }
97 
98 
99 
pushstr(lua_State * L,const char * str)100 static void pushstr (lua_State *L, const char *str) {
101   setsvalue2s(L, L->top, luaS_new(L, str));
102   incr_top(L);
103 }
104 
105 
106 /* this function handles only `%d', `%c', %f, %p, and `%s' formats */
luaO_pushvfstring(lua_State * L,const char * fmt,va_list argp)107 const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
108   int n = 1;
109   pushstr(L, "");
110   for (;;) {
111     const char *e = strchr(fmt, '%');
112     if (e == NULL) break;
113     setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt));
114     incr_top(L);
115     switch (*(e+1)) {
116       case 's': {
117         const char *s = va_arg(argp, char *);
118         if (s == NULL) s = "(null)";
119         pushstr(L, s);
120         break;
121       }
122       case 'c': {
123         char buff[2];
124         buff[0] = cast(char, va_arg(argp, int));
125         buff[1] = '\0';
126         pushstr(L, buff);
127         break;
128       }
129       case 'd': {
130         setnvalue(L->top, cast_num(va_arg(argp, int)));
131         incr_top(L);
132         break;
133       }
134       case 'f': {
135         setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber)));
136         incr_top(L);
137         break;
138       }
139       case 'p': {
140         char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */
141         sprintf(buff, "%p", va_arg(argp, void *));
142         pushstr(L, buff);
143         break;
144       }
145       case '%': {
146         pushstr(L, "%");
147         break;
148       }
149       default: {
150         char buff[3];
151         buff[0] = '%';
152         buff[1] = *(e+1);
153         buff[2] = '\0';
154         pushstr(L, buff);
155         break;
156       }
157     }
158     n += 2;
159     fmt = e+2;
160   }
161   pushstr(L, fmt);
162   luaV_concat(L, n+1, cast_int(L->top - L->base) - 1);
163   L->top -= n;
164   return svalue(L->top - 1);
165 }
166 
167 
luaO_pushfstring(lua_State * L,const char * fmt,...)168 const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) {
169   const char *msg;
170   va_list argp;
171   va_start(argp, fmt);
172   msg = luaO_pushvfstring(L, fmt, argp);
173   va_end(argp);
174   return msg;
175 }
176 
177 
luaO_chunkid(char * out,const char * source,size_t bufflen)178 void luaO_chunkid (char *out, const char *source, size_t bufflen) {
179   if (*source == '=') {
180     strncpy(out, source+1, bufflen);  /* remove first char */
181     out[bufflen-1] = '\0';  /* ensures null termination */
182   }
183   else {  /* out = "source", or "...source" */
184     if (*source == '@') {
185       size_t l;
186       source++;  /* skip the `@' */
187       bufflen -= sizeof(" '...' ");
188       l = strlen(source);
189       strcpy(out, "");
190       if (l > bufflen) {
191         source += (l-bufflen);  /* get last part of file name */
192         strcat(out, "...");
193       }
194       strcat(out, source);
195     }
196     else {  /* out = [string "string"] */
197       size_t len = strcspn(source, "\n\r");  /* stop at first newline */
198       bufflen -= sizeof(" [string \"...\"] ");
199       if (len > bufflen) len = bufflen;
200       strcpy(out, "[string \"");
201       if (source[len] != '\0') {  /* must truncate? */
202         strncat(out, source, len);
203         strcat(out, "...");
204       }
205       else
206         strcat(out, source);
207       strcat(out, "\"]");
208     }
209   }
210 }
211