mirror of
				https://github.com/RfidResearchGroup/proxmark3.git
				synced 2025-10-31 08:26:15 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			293 lines
		
	
	
	
		
			8.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			293 lines
		
	
	
	
		
			8.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
| ** $Id: lobject.c,v 2.58 2013/02/20 14:08:56 roberto Exp $
 | |
| ** Some generic functions over Lua objects
 | |
| ** See Copyright Notice in lua.h
 | |
| */
 | |
| 
 | |
| #include <stdarg.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| 
 | |
| #define lobject_c
 | |
| #define LUA_CORE
 | |
| 
 | |
| #include "lua.h"
 | |
| 
 | |
| #include "lctype.h"
 | |
| #include "ldebug.h"
 | |
| #include "ldo.h"
 | |
| #include "lmem.h"
 | |
| #include "lobject.h"
 | |
| #include "lstate.h"
 | |
| #include "lstring.h"
 | |
| #include "lvm.h"
 | |
| 
 | |
| 
 | |
| 
 | |
| LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT};
 | |
| 
 | |
| 
 | |
| /*
 | |
| ** converts an integer to a "floating point byte", represented as
 | |
| ** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if
 | |
| ** eeeee != 0 and (xxx) otherwise.
 | |
| */
 | |
| int luaO_int2fb(unsigned int x) {
 | |
|     int e = 0;  /* exponent */
 | |
|     if (x < 8) return x;
 | |
|     while (x >= 0x10) {
 | |
|         x = (x + 1) >> 1;
 | |
|         e++;
 | |
|     }
 | |
|     return ((e + 1) << 3) | (cast_int(x) - 8);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* converts back */
 | |
| int luaO_fb2int(int x) {
 | |
|     int e = (x >> 3) & 0x1f;
 | |
|     if (e == 0) return x;
 | |
|     else return ((x & 7) + 8) << (e - 1);
 | |
| }
 | |
| 
 | |
| 
 | |
| int luaO_ceillog2(unsigned int x) {
 | |
|     static const lu_byte log_2[256] = {
 | |
|         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,
 | |
|         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,
 | |
|         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,
 | |
|         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,
 | |
|         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,
 | |
|         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,
 | |
|         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,
 | |
|         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
 | |
|     };
 | |
|     int l = 0;
 | |
|     x--;
 | |
|     while (x >= 256) { l += 8; x >>= 8; }
 | |
|     return l + log_2[x];
 | |
| }
 | |
| 
 | |
| 
 | |
| lua_Number luaO_arith(int op, lua_Number v1, lua_Number v2) {
 | |
|     switch (op) {
 | |
|         case LUA_OPADD:
 | |
|             return luai_numadd(NULL, v1, v2);
 | |
|         case LUA_OPSUB:
 | |
|             return luai_numsub(NULL, v1, v2);
 | |
|         case LUA_OPMUL:
 | |
|             return luai_nummul(NULL, v1, v2);
 | |
|         case LUA_OPDIV:
 | |
|             return luai_numdiv(NULL, v1, v2);
 | |
|         case LUA_OPMOD:
 | |
|             return luai_nummod(NULL, v1, v2);
 | |
|         case LUA_OPPOW:
 | |
|             return luai_numpow(NULL, v1, v2);
 | |
|         case LUA_OPUNM:
 | |
|             return luai_numunm(NULL, v1);
 | |
|         default:
 | |
|             lua_assert(0);
 | |
|             return 0;
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| int luaO_hexavalue(int c) {
 | |
|     if (lisdigit(c)) return c - '0';
 | |
|     else return ltolower(c) - 'a' + 10;
 | |
| }
 | |
| 
 | |
| 
 | |
| #if !defined(lua_strx2number)
 | |
| 
 | |
| #include <math.h>
 | |
| 
 | |
| 
 | |
| static int isneg(const char **s) {
 | |
|     if (**s == '-') { (*s)++; return 1; }
 | |
|     else if (**s == '+')(*s)++;
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| static lua_Number readhexa(const char **s, lua_Number r, int *count) {
 | |
|     for (; lisxdigit(cast_uchar(**s)); (*s)++) {  /* read integer part */
 | |
|         r = (r * cast_num(16.0)) + cast_num(luaO_hexavalue(cast_uchar(**s)));
 | |
|         (*count)++;
 | |
|     }
 | |
|     return r;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
| ** convert an hexadecimal numeric string to a number, following
 | |
| ** C99 specification for 'strtod'
 | |
| */
 | |
| static lua_Number lua_strx2number(const char *s, char **endptr) {
 | |
|     lua_Number r = 0.0;
 | |
|     int e = 0, i = 0;
 | |
|     int neg = 0;  /* 1 if number is negative */
 | |
|     *endptr = cast(char *, s);  /* nothing is valid yet */
 | |
|     while (lisspace(cast_uchar(*s))) s++;  /* skip initial spaces */
 | |
|     neg = isneg(&s);  /* check signal */
 | |
|     if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X')))  /* check '0x' */
 | |
|         return 0.0;  /* invalid format (no '0x') */
 | |
|     s += 2;  /* skip '0x' */
 | |
|     r = readhexa(&s, r, &i);  /* read integer part */
 | |
|     if (*s == '.') {
 | |
|         s++;  /* skip dot */
 | |
|         r = readhexa(&s, r, &e);  /* read fractional part */
 | |
|     }
 | |
|     if (i == 0 && e == 0)
 | |
|         return 0.0;  /* invalid format (no digit) */
 | |
|     e *= -4;  /* each fractional digit divides value by 2^-4 */
 | |
|     *endptr = cast(char *, s);  /* valid up to here */
 | |
|     if (*s == 'p' || *s == 'P') {  /* exponent part? */
 | |
|         int exp1 = 0;
 | |
|         int neg1;
 | |
|         s++;  /* skip 'p' */
 | |
|         neg1 = isneg(&s);  /* signal */
 | |
|         if (!lisdigit(cast_uchar(*s)))
 | |
|             goto ret;  /* must have at least one digit */
 | |
|         while (lisdigit(cast_uchar(*s)))  /* read exponent */
 | |
|             exp1 = exp1 * 10 + *(s++) - '0';
 | |
|         if (neg1) exp1 = -exp1;
 | |
|         e += exp1;
 | |
|     }
 | |
|     *endptr = cast(char *, s);  /* valid up to here */
 | |
| ret:
 | |
|     if (neg) r = -r;
 | |
|     return l_mathop(ldexp)(r, e);
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| 
 | |
| int luaO_str2d(const char *s, size_t len, lua_Number *result) {
 | |
|     char *endptr;
 | |
|     if (strpbrk(s, "nN"))  /* reject 'inf' and 'nan' */
 | |
|         return 0;
 | |
|     else if (strpbrk(s, "xX"))  /* hexa? */
 | |
|         *result = lua_strx2number(s, &endptr);
 | |
|     else
 | |
|         *result = lua_str2number(s, &endptr);
 | |
|     if (endptr == s) return 0;  /* nothing recognized */
 | |
|     while (lisspace(cast_uchar(*endptr))) endptr++;
 | |
|     return (endptr == s + len);  /* OK if no trailing characters */
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| static void pushstr(lua_State *L, const char *str, size_t l) {
 | |
|     setsvalue2s(L, L->top++, luaS_newlstr(L, str, l));
 | |
| }
 | |
| 
 | |
| 
 | |
| /* this function handles only `%d', `%c', %f, %p, and `%s' formats */
 | |
| const char *luaO_pushvfstring(lua_State *L, const char *fmt, va_list argp) {
 | |
|     int n = 0;
 | |
|     for (;;) {
 | |
|         const char *e = strchr(fmt, '%');
 | |
|         if (e == NULL) break;
 | |
|         luaD_checkstack(L, 2);  /* fmt + item */
 | |
|         pushstr(L, fmt, e - fmt);
 | |
|         switch (*(e + 1)) {
 | |
|             case 's': {
 | |
|                 const char *s = va_arg(argp, char *);
 | |
|                 if (s == NULL) s = "(null)";
 | |
|                 pushstr(L, s, strlen(s));
 | |
|                 break;
 | |
|             }
 | |
|             case 'c': {
 | |
|                 char buff;
 | |
|                 buff = cast(char, va_arg(argp, int));
 | |
|                 pushstr(L, &buff, 1);
 | |
|                 break;
 | |
|             }
 | |
|             case 'd': {
 | |
|                 setnvalue(L->top++, cast_num(va_arg(argp, int)));
 | |
|                 break;
 | |
|             }
 | |
|             case 'f': {
 | |
|                 setnvalue(L->top++, cast_num(va_arg(argp, l_uacNumber)));
 | |
|                 break;
 | |
|             }
 | |
|             case 'p': {
 | |
|                 char buff[4 * sizeof(void *) + 8]; /* should be enough space for a `%p' */
 | |
|                 int l = sprintf(buff, "%p", va_arg(argp, void *));
 | |
|                 pushstr(L, buff, l);
 | |
|                 break;
 | |
|             }
 | |
|             case '%': {
 | |
|                 pushstr(L, "%", 1);
 | |
|                 break;
 | |
|             }
 | |
|             default: {
 | |
|                 luaG_runerror(L,
 | |
|                               "invalid option " LUA_QL("%%%c") " to " LUA_QL("lua_pushfstring"),
 | |
|                               *(e + 1));
 | |
|             }
 | |
|         }
 | |
|         n += 2;
 | |
|         fmt = e + 2;
 | |
|     }
 | |
|     luaD_checkstack(L, 1);
 | |
|     pushstr(L, fmt, strlen(fmt));
 | |
|     if (n > 0) luaV_concat(L, n + 1);
 | |
|     return svalue(L->top - 1);
 | |
| }
 | |
| 
 | |
| 
 | |
| const char *luaO_pushfstring(lua_State *L, const char *fmt, ...) {
 | |
|     const char *msg;
 | |
|     va_list argp;
 | |
|     va_start(argp, fmt);
 | |
|     msg = luaO_pushvfstring(L, fmt, argp);
 | |
|     va_end(argp);
 | |
|     return msg;
 | |
| }
 | |
| 
 | |
| 
 | |
| /* number of chars of a literal string without the ending \0 */
 | |
| #define LL(x) (sizeof(x)/sizeof(char) - 1)
 | |
| 
 | |
| #define RETS "..."
 | |
| #define PRE "[string \""
 | |
| #define POS "\"]"
 | |
| 
 | |
| #define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) )
 | |
| 
 | |
| void luaO_chunkid(char *out, const char *source, size_t bufflen) {
 | |
|     size_t l = strlen(source);
 | |
|     if (*source == '=') {  /* 'literal' source */
 | |
|         if (l <= bufflen)  /* small enough? */
 | |
|             memcpy(out, source + 1, l * sizeof(char));
 | |
|         else {  /* truncate it */
 | |
|             addstr(out, source + 1, bufflen - 1);
 | |
|             *out = '\0';
 | |
|         }
 | |
|     } else if (*source == '@') { /* file name */
 | |
|         if (l <= bufflen)  /* small enough? */
 | |
|             memcpy(out, source + 1, l * sizeof(char));
 | |
|         else {  /* add '...' before rest of name */
 | |
|             addstr(out, RETS, LL(RETS));
 | |
|             bufflen -= LL(RETS);
 | |
|             memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char));
 | |
|         }
 | |
|     } else { /* string; format as [string "source"] */
 | |
|         const char *nl = strchr(source, '\n');  /* find first new line (if any) */
 | |
|         addstr(out, PRE, LL(PRE));  /* add prefix */
 | |
|         bufflen -= LL(PRE RETS POS) + 1;  /* save space for prefix+suffix+'\0' */
 | |
|         if (l < bufflen && nl == NULL) {  /* small one-line source? */
 | |
|             addstr(out, source, l);  /* keep it */
 | |
|         } else {
 | |
|             if (nl != NULL) l = nl - source;  /* stop at first newline */
 | |
|             if (l > bufflen) l = bufflen;
 | |
|             addstr(out, source, l);
 | |
|             addstr(out, RETS, LL(RETS));
 | |
|         }
 | |
|         memcpy(out, POS, (LL(POS) + 1) * sizeof(char));
 | |
|     }
 | |
| }
 | |
| 
 |