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