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