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