Committed lnum patch 031007
[lua.git] / src / lobject.c
blobbf1527aefc2b2af738164cae6e5f48312f4535ba
1 /*
2 ** $Id: lobject.c,v 2.22 2006/02/10 17:43:52 roberto Exp $
3 ** Some generic functions over Lua objects
4 ** See Copyright Notice in lua.h
5 */
7 #include <ctype.h>
8 #include <stdarg.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
13 #define lobject_c
14 #define LUA_CORE
16 #include "lua.h"
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 #include "llex.h"
25 #include "lnum.h"
28 const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL};
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; /* expoent */
38 while (x >= 16) {
39 x = (x+1) >> 1;
40 e++;
42 if (x < 8) return x;
43 else return ((e+1) << 3) | (cast_int(x) - 8);
47 /* converts back */
48 int luaO_fb2int (int x) {
49 int e = (x >> 3) & 31;
50 if (e == 0) return x;
51 else return ((x & 7)+8) << (e - 1);
55 int luaO_log2 (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
66 int l = -1;
67 while (x >= 256) { l += 8; x >>= 8; }
68 return l + log_2[x];
73 lu_bool luaO_rawequalObj (const TValue *t1, const TValue *t2) {
74 if (ttype(t1) != ttype(t2)) return 0;
75 else switch (ttype(t1)) {
76 case LUA_TNIL:
77 return 1;
78 case LUA_TNUMBER:
79 #ifdef LUA_TINT
80 # ifdef LNUM_COMPLEX
81 if (!luai_numeq( nvalue_img_fast(t1), nvalue_img_fast(t2) )) return 0;
82 # endif
83 return luai_numeq(nvalue_fast(t1), nvalue_fast(t2));
84 case LUA_TINT:
85 return ivalue(t1) == ivalue(t2);
86 #else
87 return luai_numeq(nvalue(t1), nvalue(t2));
88 #endif
89 case LUA_TBOOLEAN:
90 return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */
91 case LUA_TLIGHTUSERDATA:
92 return pvalue(t1) == pvalue(t2);
93 default:
94 lua_assert(iscollectable(t1));
95 return gcvalue(t1) == gcvalue(t2);
99 static void pushstr (lua_State *L, const char *str) {
100 setsvalue2s(L, L->top, luaS_new(L, str));
101 incr_top(L);
105 /* this function handles only `%d', `%c', %f, %p, and `%s' formats */
106 const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
107 int n = 1;
108 pushstr(L, "");
109 for (;;) {
110 const char *e = strchr(fmt, '%');
111 if (e == NULL) break;
112 setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt));
113 incr_top(L);
114 switch (*(e+1)) {
115 case 's': {
116 const char *s = va_arg(argp, char *);
117 if (s == NULL) s = "(null)";
118 pushstr(L, s);
119 break;
121 case 'c': {
122 char buff[2];
123 buff[0] = cast(char, va_arg(argp, int));
124 buff[1] = '\0';
125 pushstr(L, buff);
126 break;
128 case 'd': {
129 #if 1
130 //in 5.1.1: setivalue(L->top, va_arg(argp, int));
131 setivalue(L->top, (lua_Integer) va_arg(argp, l_uacInteger));
132 #else
133 setivalue(L->top, va_arg(argp, int));
134 #endif
135 incr_top(L);
136 break;
138 case 'f': {
139 setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber)));
140 incr_top(L);
141 break;
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;
149 case '%': {
150 pushstr(L, "%");
151 break;
153 default: {
154 char buff[3];
155 buff[0] = '%';
156 buff[1] = *(e+1);
157 buff[2] = '\0';
158 pushstr(L, buff);
159 break;
162 n += 2;
163 fmt = e+2;
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);
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;
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 */
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, "...");
198 strcat(out, source);
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, "...");
209 else
210 strcat(out, source);
211 strcat(out, "\"]");