misc/liblua/lobject.c
changeset 2812 0a24853de796
equal deleted inserted replaced
2811:4cad87e11bf6 2812:0a24853de796
       
     1 /*
       
     2 ** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $
       
     3 ** Some generic functions over Lua objects
       
     4 ** See Copyright Notice in lua.h
       
     5 */
       
     6 
       
     7 #include <ctype.h>
       
     8 #include <stdarg.h>
       
     9 #include <stdio.h>
       
    10 #include <stdlib.h>
       
    11 #include <string.h>
       
    12 
       
    13 #define lobject_c
       
    14 #define LUA_CORE
       
    15 
       
    16 #include "lua.h"
       
    17 
       
    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 
       
    25 
       
    26 
       
    27 const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL};
       
    28 
       
    29 
       
    30 /*
       
    31 ** converts an integer to a "floating point byte", represented as
       
    32 ** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if
       
    33 ** eeeee != 0 and (xxx) otherwise.
       
    34 */
       
    35 int luaO_int2fb (unsigned int x) {
       
    36   int e = 0;  /* expoent */
       
    37   while (x >= 16) {
       
    38     x = (x+1) >> 1;
       
    39     e++;
       
    40   }
       
    41   if (x < 8) return x;
       
    42   else return ((e+1) << 3) | (cast_int(x) - 8);
       
    43 }
       
    44 
       
    45 
       
    46 /* converts back */
       
    47 int luaO_fb2int (int x) {
       
    48   int e = (x >> 3) & 31;
       
    49   if (e == 0) return x;
       
    50   else return ((x & 7)+8) << (e - 1);
       
    51 }
       
    52 
       
    53 
       
    54 int luaO_log2 (unsigned int x) {
       
    55   static const lu_byte log_2[256] = {
       
    56     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     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     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     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     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     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   };
       
    65   int l = -1;
       
    66   while (x >= 256) { l += 8; x >>= 8; }
       
    67   return l + log_2[x];
       
    68 
       
    69 }
       
    70 
       
    71 
       
    72 int luaO_rawequalObj (const TValue *t1, const TValue *t2) {
       
    73   if (ttype(t1) != ttype(t2)) return 0;
       
    74   else switch (ttype(t1)) {
       
    75     case LUA_TNIL:
       
    76       return 1;
       
    77     case LUA_TNUMBER:
       
    78       return luai_numeq(nvalue(t1), nvalue(t2));
       
    79     case LUA_TBOOLEAN:
       
    80       return bvalue(t1) == bvalue(t2);  /* boolean true must be 1 !! */
       
    81     case LUA_TLIGHTUSERDATA:
       
    82       return pvalue(t1) == pvalue(t2);
       
    83     default:
       
    84       lua_assert(iscollectable(t1));
       
    85       return gcvalue(t1) == gcvalue(t2);
       
    86   }
       
    87 }
       
    88 
       
    89 
       
    90 int luaO_str2d (const char *s, lua_Number *result) {
       
    91   char *endptr;
       
    92   *result = lua_str2number(s, &endptr);
       
    93   if (endptr == s) return 0;  /* conversion failed */
       
    94   if (*endptr == 'x' || *endptr == 'X')  /* maybe an hexadecimal constant? */
       
    95     *result = cast_num(strtoul(s, &endptr, 16));
       
    96   if (*endptr == '\0') return 1;  /* most common case */
       
    97   while (isspace(cast(unsigned char, *endptr))) endptr++;
       
    98   if (*endptr != '\0') return 0;  /* invalid trailing characters? */
       
    99   return 1;
       
   100 }
       
   101 
       
   102 
       
   103 
       
   104 static void pushstr (lua_State *L, const char *str) {
       
   105   setsvalue2s(L, L->top, luaS_new(L, str));
       
   106   incr_top(L);
       
   107 }
       
   108 
       
   109 
       
   110 /* this function handles only `%d', `%c', %f, %p, and `%s' formats */
       
   111 const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
       
   112   int n = 1;
       
   113   pushstr(L, "");
       
   114   for (;;) {
       
   115     const char *e = strchr(fmt, '%');
       
   116     if (e == NULL) break;
       
   117     setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt));
       
   118     incr_top(L);
       
   119     switch (*(e+1)) {
       
   120       case 's': {
       
   121         const char *s = va_arg(argp, char *);
       
   122         if (s == NULL) s = "(null)";
       
   123         pushstr(L, s);
       
   124         break;
       
   125       }
       
   126       case 'c': {
       
   127         char buff[2];
       
   128         buff[0] = cast(char, va_arg(argp, int));
       
   129         buff[1] = '\0';
       
   130         pushstr(L, buff);
       
   131         break;
       
   132       }
       
   133       case 'd': {
       
   134         setnvalue(L->top, cast_num(va_arg(argp, int)));
       
   135         incr_top(L);
       
   136         break;
       
   137       }
       
   138       case 'f': {
       
   139         setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber)));
       
   140         incr_top(L);
       
   141         break;
       
   142       }
       
   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;
       
   148       }
       
   149       case '%': {
       
   150         pushstr(L, "%");
       
   151         break;
       
   152       }
       
   153       default: {
       
   154         char buff[3];
       
   155         buff[0] = '%';
       
   156         buff[1] = *(e+1);
       
   157         buff[2] = '\0';
       
   158         pushstr(L, buff);
       
   159         break;
       
   160       }
       
   161     }
       
   162     n += 2;
       
   163     fmt = e+2;
       
   164   }
       
   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);
       
   169 }
       
   170 
       
   171 
       
   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;
       
   179 }
       
   180 
       
   181 
       
   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 */
       
   186   }
       
   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, "...");
       
   197       }
       
   198       strcat(out, source);
       
   199     }
       
   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, "...");
       
   208       }
       
   209       else
       
   210         strcat(out, source);
       
   211       strcat(out, "\"]");
       
   212     }
       
   213   }
       
   214 }