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