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