|
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 } |