LCOV - code coverage report
Current view: top level - src - lobject.c Coverage Total Hit
Test: Lua 5.2.4 Lines: 88.1 % 109 96
Test Date: 2024-04-28 10:23:12
Legend: Lines: hit not hit

            Line data    Source code
       1              : /*
       2              : ** $Id: lobject.c,v 2.58.1.1 2013/04/12 18:48:47 roberto Exp $
       3              : ** Some generic functions over Lua objects
       4              : ** See Copyright Notice in lua.h
       5              : */
       6              : 
       7              : #include <stdarg.h>
       8              : #include <stdio.h>
       9              : #include <stdlib.h>
      10              : #include <string.h>
      11              : 
      12              : #define lobject_c
      13              : #define LUA_CORE
      14              : 
      15              : #include "lua.h"
      16              : 
      17              : #include "lctype.h"
      18              : #include "ldebug.h"
      19              : #include "ldo.h"
      20              : #include "lmem.h"
      21              : #include "lobject.h"
      22              : #include "lstate.h"
      23              : #include "lstring.h"
      24              : #include "lvm.h"
      25              : 
      26              : 
      27              : 
      28              : LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT};
      29              : 
      30              : 
      31              : /*
      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.
      35              : */
      36         1428 : int luaO_int2fb (unsigned int x) {
      37         1428 :   int e = 0;  /* exponent */
      38         1428 :   if (x < 8) return x;
      39           16 :   while (x >= 0x10) {
      40            7 :     x = (x+1) >> 1;
      41            7 :     e++;
      42              :   }
      43            9 :   return ((e+1) << 3) | (cast_int(x) - 8);
      44              : }
      45              : 
      46              : 
      47              : /* converts back */
      48          502 : int luaO_fb2int (int x) {
      49          502 :   int e = (x >> 3) & 0x1f;
      50          502 :   if (e == 0) return x;
      51            5 :   else return ((x & 7) + 8) << (e - 1);
      52              : }
      53              : 
      54              : 
      55        38053 : int luaO_ceillog2 (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
      65              :   };
      66        38053 :   int l = 0;
      67        38053 :   x--;
      68        38170 :   while (x >= 256) { l += 8; x >>= 8; }
      69        38053 :   return l + log_2[x];
      70              : }
      71              : 
      72              : 
      73           46 : lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2) {
      74           46 :   switch (op) {
      75           10 :     case LUA_OPADD: return luai_numadd(NULL, v1, v2);
      76            6 :     case LUA_OPSUB: return luai_numsub(NULL, v1, v2);
      77           11 :     case LUA_OPMUL: return luai_nummul(NULL, v1, v2);
      78            7 :     case LUA_OPDIV: return luai_numdiv(NULL, v1, v2);
      79            5 :     case LUA_OPMOD: return luai_nummod(NULL, v1, v2);
      80            6 :     case LUA_OPPOW: return luai_numpow(NULL, v1, v2);
      81            1 :     case LUA_OPUNM: return luai_numunm(NULL, v1);
      82            0 :     default: lua_assert(0); return 0;
      83              :   }
      84              : }
      85              : 
      86              : 
      87           90 : int luaO_hexavalue (int c) {
      88           90 :   if (lisdigit(c)) return c - '0';
      89           33 :   else return ltolower(c) - 'a' + 10;
      90              : }
      91              : 
      92              : 
      93              : #if !defined(lua_strx2number)
      94              : 
      95              : #include <math.h>
      96              : 
      97              : 
      98              : static int isneg (const char **s) {
      99              :   if (**s == '-') { (*s)++; return 1; }
     100              :   else if (**s == '+') (*s)++;
     101              :   return 0;
     102              : }
     103              : 
     104              : 
     105              : static lua_Number readhexa (const char **s, lua_Number r, int *count) {
     106              :   for (; lisxdigit(cast_uchar(**s)); (*s)++) {  /* read integer part */
     107              :     r = (r * cast_num(16.0)) + cast_num(luaO_hexavalue(cast_uchar(**s)));
     108              :     (*count)++;
     109              :   }
     110              :   return r;
     111              : }
     112              : 
     113              : 
     114              : /*
     115              : ** convert an hexadecimal numeric string to a number, following
     116              : ** C99 specification for 'strtod'
     117              : */
     118              : static lua_Number lua_strx2number (const char *s, char **endptr) {
     119              :   lua_Number r = 0.0;
     120              :   int e = 0, i = 0;
     121              :   int neg = 0;  /* 1 if number is negative */
     122              :   *endptr = cast(char *, s);  /* nothing is valid yet */
     123              :   while (lisspace(cast_uchar(*s))) s++;  /* skip initial spaces */
     124              :   neg = isneg(&s);  /* check signal */
     125              :   if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X')))  /* check '0x' */
     126              :     return 0.0;  /* invalid format (no '0x') */
     127              :   s += 2;  /* skip '0x' */
     128              :   r = readhexa(&s, r, &i);  /* read integer part */
     129              :   if (*s == '.') {
     130              :     s++;  /* skip dot */
     131              :     r = readhexa(&s, r, &e);  /* read fractional part */
     132              :   }
     133              :   if (i == 0 && e == 0)
     134              :     return 0.0;  /* invalid format (no digit) */
     135              :   e *= -4;  /* each fractional digit divides value by 2^-4 */
     136              :   *endptr = cast(char *, s);  /* valid up to here */
     137              :   if (*s == 'p' || *s == 'P') {  /* exponent part? */
     138              :     int exp1 = 0;
     139              :     int neg1;
     140              :     s++;  /* skip 'p' */
     141              :     neg1 = isneg(&s);  /* signal */
     142              :     if (!lisdigit(cast_uchar(*s)))
     143              :       goto ret;  /* must have at least one digit */
     144              :     while (lisdigit(cast_uchar(*s)))  /* read exponent */
     145              :       exp1 = exp1 * 10 + *(s++) - '0';
     146              :     if (neg1) exp1 = -exp1;
     147              :     e += exp1;
     148              :   }
     149              :   *endptr = cast(char *, s);  /* valid up to here */
     150              :  ret:
     151              :   if (neg) r = -r;
     152              :   return l_mathop(ldexp)(r, e);
     153              : }
     154              : 
     155              : #endif
     156              : 
     157              : 
     158         3476 : int luaO_str2d (const char *s, size_t len, lua_Number *result) {
     159              :   char *endptr;
     160         3476 :   if (strpbrk(s, "nN"))  /* reject 'inf' and 'nan' */
     161            0 :     return 0;
     162         3476 :   else if (strpbrk(s, "xX"))  /* hexa? */
     163           99 :     *result = lua_strx2number(s, &endptr);
     164              :   else
     165         3377 :     *result = lua_str2number(s, &endptr);
     166         3476 :   if (endptr == s) return 0;  /* nothing recognized */
     167         3456 :   while (lisspace(cast_uchar(*endptr))) endptr++;
     168         3454 :   return (endptr == s + len);  /* OK if no trailing characters */
     169              : }
     170              : 
     171              : 
     172              : 
     173         8448 : static void pushstr (lua_State *L, const char *str, size_t l) {
     174         8448 :   setsvalue2s(L, L->top++, luaS_newlstr(L, str, l));
     175         8448 : }
     176              : 
     177              : 
     178              : /* this function handles only `%d', `%c', %f, %p, and `%s' formats */
     179         2272 : const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
     180         2272 :   int n = 0;
     181         3280 :   for (;;) {
     182         5552 :     const char *e = strchr(fmt, '%');
     183         5552 :     if (e == NULL) break;
     184         3280 :     luaD_checkstack(L, 2);  /* fmt + item */
     185         3280 :     pushstr(L, fmt, e - fmt);
     186         3280 :     switch (*(e+1)) {
     187         2860 :       case 's': {
     188         2860 :         const char *s = va_arg(argp, char *);
     189         2860 :         if (s == NULL) s = "(null)";
     190         2860 :         pushstr(L, s, strlen(s));
     191         2860 :         break;
     192              :       }
     193           15 :       case 'c': {
     194              :         char buff;
     195           15 :         buff = cast(char, va_arg(argp, int));
     196           15 :         pushstr(L, &buff, 1);
     197           15 :         break;
     198              :       }
     199          384 :       case 'd': {
     200          384 :         setnvalue(L->top++, cast_num(va_arg(argp, int)));
     201          384 :         break;
     202              :       }
     203            0 :       case 'f': {
     204            0 :         setnvalue(L->top++, cast_num(va_arg(argp, l_uacNumber)));
     205            0 :         break;
     206              :       }
     207           15 :       case 'p': {
     208              :         char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */
     209           15 :         int l = sprintf(buff, "%p", va_arg(argp, void *));
     210           15 :         pushstr(L, buff, l);
     211           15 :         break;
     212              :       }
     213            6 :       case '%': {
     214            6 :         pushstr(L, "%", 1);
     215            6 :         break;
     216              :       }
     217            0 :       default: {
     218            0 :         luaG_runerror(L,
     219              :             "invalid option " LUA_QL("%%%c") " to " LUA_QL("lua_pushfstring"),
     220            0 :             *(e + 1));
     221              :       }
     222              :     }
     223         3280 :     n += 2;
     224         3280 :     fmt = e+2;
     225              :   }
     226         2272 :   luaD_checkstack(L, 1);
     227         2272 :   pushstr(L, fmt, strlen(fmt));
     228         2272 :   if (n > 0) luaV_concat(L, n + 1);
     229         2272 :   return svalue(L->top - 1);
     230              : }
     231              : 
     232              : 
     233          319 : const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) {
     234              :   const char *msg;
     235              :   va_list argp;
     236          319 :   va_start(argp, fmt);
     237          319 :   msg = luaO_pushvfstring(L, fmt, argp);
     238          319 :   va_end(argp);
     239          319 :   return msg;
     240              : }
     241              : 
     242              : 
     243              : /* number of chars of a literal string without the ending \0 */
     244              : #define LL(x)   (sizeof(x)/sizeof(char) - 1)
     245              : 
     246              : #define RETS    "..."
     247              : #define PRE     "[string \""
     248              : #define POS     "\"]"
     249              : 
     250              : #define addstr(a,b,l)   ( memcpy(a,b,(l) * sizeof(char)), a += (l) )
     251              : 
     252          387 : void luaO_chunkid (char *out, const char *source, size_t bufflen) {
     253          387 :   size_t l = strlen(source);
     254          387 :   if (*source == '=') {  /* 'literal' source */
     255           60 :     if (l <= bufflen)  /* small enough? */
     256           60 :       memcpy(out, source + 1, l * sizeof(char));
     257              :     else {  /* truncate it */
     258            0 :       addstr(out, source + 1, bufflen - 1);
     259            0 :       *out = '\0';
     260              :     }
     261              :   }
     262          327 :   else if (*source == '@') {  /* file name */
     263          291 :     if (l <= bufflen)  /* small enough? */
     264          291 :       memcpy(out, source + 1, l * sizeof(char));
     265              :     else {  /* add '...' before rest of name */
     266            0 :       addstr(out, RETS, LL(RETS));
     267            0 :       bufflen -= LL(RETS);
     268            0 :       memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char));
     269              :     }
     270              :   }
     271              :   else {  /* string; format as [string "source"] */
     272           36 :     const char *nl = strchr(source, '\n');  /* find first new line (if any) */
     273           36 :     addstr(out, PRE, LL(PRE));  /* add prefix */
     274           36 :     bufflen -= LL(PRE RETS POS) + 1;  /* save space for prefix+suffix+'\0' */
     275           36 :     if (l < bufflen && nl == NULL) {  /* small one-line source? */
     276           26 :       addstr(out, source, l);  /* keep it */
     277              :     }
     278              :     else {
     279           10 :       if (nl != NULL) l = nl - source;  /* stop at first newline */
     280           10 :       if (l > bufflen) l = bufflen;
     281           10 :       addstr(out, source, l);
     282           10 :       addstr(out, RETS, LL(RETS));
     283              :     }
     284           36 :     memcpy(out, POS, (LL(POS) + 1) * sizeof(char));
     285              :   }
     286          387 : }
     287              : 
        

Generated by: LCOV version 2.0-1