2 ** $Id: lobject.c,v 2.58 2013/02/20 14:08:56 roberto Exp $
3 ** Some generic functions over Lua objects
4 ** See Copyright Notice in lua.h
28 LUAI_DDEF
const TValue luaO_nilobject_
= {NILCONSTANT
};
32 ** converts an integer to a "floating point byte", represented as
33 ** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if
34 ** eeeee != 0 and (xxx) otherwise.
36 int luaO_int2fb (unsigned int x
) {
37 int e
= 0; /* exponent */
43 return ((e
+1) << 3) | (cast_int(x
) - 8);
48 int luaO_fb2int (int x
) {
49 int e
= (x
>> 3) & 0x1f;
51 else return ((x
& 7) + 8) << (e
- 1);
55 int luaO_ceillog2 (unsigned int x
) {
56 static const lu_byte log_2
[256] = {
57 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,
58 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,
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 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,
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 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
68 while (x
>= 256) { l
+= 8; x
>>= 8; }
73 lua_Number
luaO_arith (int op
, lua_Number v1
, lua_Number v2
) {
75 case LUA_OPADD
: return luai_numadd(NULL
, v1
, v2
);
76 case LUA_OPSUB
: return luai_numsub(NULL
, v1
, v2
);
77 case LUA_OPMUL
: return luai_nummul(NULL
, v1
, v2
);
78 case LUA_OPDIV
: return luai_numdiv(NULL
, v1
, v2
);
79 case LUA_OPMOD
: return luai_nummod(NULL
, v1
, v2
);
80 case LUA_OPPOW
: return luai_numpow(NULL
, v1
, v2
);
81 case LUA_OPUNM
: return luai_numunm(NULL
, v1
);
82 default: lua_assert(0); return 0;
87 int luaO_hexavalue (int c
) {
88 if (lisdigit(c
)) return c
- '0';
89 else return ltolower(c
) - 'a' + 10;
93 #if !defined(lua_strx2number)
98 static int isneg (const char **s
) {
99 if (**s
== '-') { (*s
)++; return 1; }
100 else if (**s
== '+') (*s
)++;
105 static lua_Number
readhexa (const char **s
, lua_Number r
, int *count
) {
106 for (; lisxdigit(cast_uchar(**s
)); (*s
)++) { /* read integer part */
107 r
= (r
* cast_num(16.0)) + cast_num(luaO_hexavalue(cast_uchar(**s
)));
115 ** convert an hexadecimal numeric string to a number, following
116 ** C99 specification for 'strtod'
118 static lua_Number
lua_strx2number (const char *s
, char **endptr
) {
121 int neg
= 0; /* 1 if number is negative */
122 *endptr
= cast(char *, s
); /* nothing is valid yet */
123 while (lisspace(cast_uchar(*s
))) s
++; /* skip initial spaces */
124 neg
= isneg(&s
); /* check signal */
125 if (!(*s
== '0' && (*(s
+ 1) == 'x' || *(s
+ 1) == 'X'))) /* check '0x' */
126 return 0.0; /* invalid format (no '0x') */
127 s
+= 2; /* skip '0x' */
128 r
= readhexa(&s
, r
, &i
); /* read integer part */
131 r
= readhexa(&s
, r
, &e
); /* read fractional part */
133 if (i
== 0 && e
== 0)
134 return 0.0; /* invalid format (no digit) */
135 e
*= -4; /* each fractional digit divides value by 2^-4 */
136 *endptr
= cast(char *, s
); /* valid up to here */
137 if (*s
== 'p' || *s
== 'P') { /* exponent part? */
141 neg1
= isneg(&s
); /* signal */
142 if (!lisdigit(cast_uchar(*s
)))
143 goto ret
; /* must have at least one digit */
144 while (lisdigit(cast_uchar(*s
))) /* read exponent */
145 exp1
= exp1
* 10 + *(s
++) - '0';
146 if (neg1
) exp1
= -exp1
;
149 *endptr
= cast(char *, s
); /* valid up to here */
152 return l_mathop(ldexp
)(r
, e
);
158 int luaO_str2d (const char *s
, size_t len
, lua_Number
*result
) {
160 if (strpbrk(s
, "nN")) /* reject 'inf' and 'nan' */
162 else if (strpbrk(s
, "xX")) /* hexa? */
163 *result
= lua_strx2number(s
, &endptr
);
165 *result
= lua_str2number(s
, &endptr
);
166 if (endptr
== s
) return 0; /* nothing recognized */
167 while (lisspace(cast_uchar(*endptr
))) endptr
++;
168 return (endptr
== s
+ len
); /* OK if no trailing characters */
173 static void pushstr (lua_State
*L
, const char *str
, size_t l
) {
174 setsvalue2s(L
, L
->top
++, luaS_newlstr(L
, str
, l
));
178 /* this function handles only `%d', `%c', %f, %p, and `%s' formats */
179 const char *luaO_pushvfstring (lua_State
*L
, const char *fmt
, va_list argp
) {
182 const char *e
= strchr(fmt
, '%');
183 if (e
== NULL
) break;
184 luaD_checkstack(L
, 2); /* fmt + item */
185 pushstr(L
, fmt
, e
- fmt
);
188 const char *s
= va_arg(argp
, char *);
189 if (s
== NULL
) s
= "(null)";
190 pushstr(L
, s
, strlen(s
));
195 buff
= cast(char, va_arg(argp
, int));
196 pushstr(L
, &buff
, 1);
200 setnvalue(L
->top
++, cast_num(va_arg(argp
, int)));
204 setnvalue(L
->top
++, cast_num(va_arg(argp
, l_uacNumber
)));
208 char buff
[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */
209 int l
= sprintf(buff
, "%p", va_arg(argp
, void *));
219 "invalid option " LUA_QL("%%%c") " to " LUA_QL("lua_pushfstring"),
226 luaD_checkstack(L
, 1);
227 pushstr(L
, fmt
, strlen(fmt
));
228 if (n
> 0) luaV_concat(L
, n
+ 1);
229 return svalue(L
->top
- 1);
233 const char *luaO_pushfstring (lua_State
*L
, const char *fmt
, ...) {
237 msg
= luaO_pushvfstring(L
, fmt
, argp
);
243 /* number of chars of a literal string without the ending \0 */
244 #define LL(x) (sizeof(x)/sizeof(char) - 1)
247 #define PRE "[string \""
250 #define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) )
252 void luaO_chunkid (char *out
, const char *source
, size_t bufflen
) {
253 size_t l
= strlen(source
);
254 if (*source
== '=') { /* 'literal' source */
255 if (l
<= bufflen
) /* small enough? */
256 memcpy(out
, source
+ 1, l
* sizeof(char));
257 else { /* truncate it */
258 addstr(out
, source
+ 1, bufflen
- 1);
262 else if (*source
== '@') { /* file name */
263 if (l
<= bufflen
) /* small enough? */
264 memcpy(out
, source
+ 1, l
* sizeof(char));
265 else { /* add '...' before rest of name */
266 addstr(out
, RETS
, LL(RETS
));
268 memcpy(out
, source
+ 1 + l
- bufflen
, bufflen
* sizeof(char));
271 else { /* string; format as [string "source"] */
272 const char *nl
= strchr(source
, '\n'); /* find first new line (if any) */
273 addstr(out
, PRE
, LL(PRE
)); /* add prefix */
274 bufflen
-= LL(PRE RETS POS
) + 1; /* save space for prefix+suffix+'\0' */
275 if (l
< bufflen
&& nl
== NULL
) { /* small one-line source? */
276 addstr(out
, source
, l
); /* keep it */
279 if (nl
!= NULL
) l
= nl
- source
; /* stop at first newline */
280 if (l
> bufflen
) l
= bufflen
;
281 addstr(out
, source
, l
);
282 addstr(out
, RETS
, LL(RETS
));
284 memcpy(out
, POS
, (LL(POS
) + 1) * sizeof(char));