Coverage Report

Created: 2025-07-11 06:33

/src/testdir/build/lua-master/source/lobject.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
** $Id: lobject.c $
3
** Some generic functions over Lua objects
4
** See Copyright Notice in lua.h
5
*/
6
7
#define lobject_c
8
#define LUA_CORE
9
10
#include "lprefix.h"
11
12
13
#include <float.h>
14
#include <locale.h>
15
#include <math.h>
16
#include <stdarg.h>
17
#include <stdio.h>
18
#include <stdlib.h>
19
#include <string.h>
20
21
#include "lua.h"
22
23
#include "lctype.h"
24
#include "ldebug.h"
25
#include "ldo.h"
26
#include "lmem.h"
27
#include "lobject.h"
28
#include "lstate.h"
29
#include "lstring.h"
30
#include "lvm.h"
31
32
33
/*
34
** Computes ceil(log2(x))
35
*/
36
51.9M
lu_byte luaO_ceillog2 (unsigned int x) {
37
51.9M
  static const lu_byte log_2[256] = {  /* log_2[i - 1] = ceil(log2(i)) */
38
51.9M
    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,
39
51.9M
    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,
40
51.9M
    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,
41
51.9M
    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,
42
51.9M
    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,
43
51.9M
    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,
44
51.9M
    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,
45
51.9M
    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
46
51.9M
  };
47
51.9M
  int l = 0;
48
51.9M
  x--;
49
53.3M
  while (x >= 256) { l += 8; x >>= 8; }
50
51.9M
  return cast_byte(l + log_2[x]);
51
51.9M
}
52
53
/*
54
** Encodes 'p'% as a floating-point byte, represented as (eeeexxxx).
55
** The exponent is represented using excess-7. Mimicking IEEE 754, the
56
** representation normalizes the number when possible, assuming an extra
57
** 1 before the mantissa (xxxx) and adding one to the exponent (eeee)
58
** to signal that. So, the real value is (1xxxx) * 2^(eeee - 7 - 1) if
59
** eeee != 0, and (xxxx) * 2^-7 otherwise (subnormal numbers).
60
*/
61
357k
lu_byte luaO_codeparam (unsigned int p) {
62
357k
  if (p >= (cast(lu_mem, 0x1F) << (0xF - 7 - 1)) * 100u)  /* overflow? */
63
0
    return 0xFF;  /* return maximum value */
64
357k
  else {
65
357k
    p = (cast(l_uint32, p) * 128 + 99) / 100;  /* round up the division */
66
357k
    if (p < 0x10) {  /* subnormal number? */
67
      /* exponent bits are already zero; nothing else to do */
68
0
      return cast_byte(p);
69
0
    }
70
357k
    else {  /* p >= 0x10 implies ceil(log2(p + 1)) >= 5 */
71
      /* preserve 5 bits in 'p' */
72
357k
      unsigned log = luaO_ceillog2(p + 1) - 5u;
73
357k
      return cast_byte(((p >> log) - 0x10) | ((log + 1) << 4));
74
357k
    }
75
357k
  }
76
357k
}
77
78
79
/*
80
** Computes 'p' times 'x', where 'p' is a floating-point byte. Roughly,
81
** we have to multiply 'x' by the mantissa and then shift accordingly to
82
** the exponent.  If the exponent is positive, both the multiplication
83
** and the shift increase 'x', so we have to care only about overflows.
84
** For negative exponents, however, multiplying before the shift keeps
85
** more significant bits, as long as the multiplication does not
86
** overflow, so we check which order is best.
87
*/
88
3.62M
l_mem luaO_applyparam (lu_byte p, l_mem x) {
89
3.62M
  unsigned int m = p & 0xF;  /* mantissa */
90
3.62M
  int e = (p >> 4);  /* exponent */
91
3.62M
  if (e > 0) {  /* normalized? */
92
3.62M
    e--;  /* correct exponent */
93
3.62M
    m += 0x10;  /* correct mantissa; maximum value is 0x1F */
94
3.62M
  }
95
3.62M
  e -= 7;  /* correct excess-7 */
96
3.62M
  if (e >= 0) {
97
1.01M
    if (x < (MAX_LMEM / 0x1F) >> e)  /* no overflow? */
98
1.01M
      return (x * m) << e;  /* order doesn't matter here */
99
0
    else  /* real overflow */
100
0
      return MAX_LMEM;
101
1.01M
  }
102
2.61M
  else {  /* negative exponent */
103
2.61M
    e = -e;
104
2.61M
    if (x < MAX_LMEM / 0x1F)  /* multiplication cannot overflow? */
105
2.61M
      return (x * m) >> e;  /* multiplying first gives more precision */
106
0
    else if ((x >> e) <  MAX_LMEM / 0x1F)  /* cannot overflow after shift? */
107
0
      return (x >> e) * m;
108
0
    else  /* real overflow */
109
0
      return MAX_LMEM;
110
2.61M
  }
111
3.62M
}
112
113
114
static lua_Integer intarith (lua_State *L, int op, lua_Integer v1,
115
3.51M
                                                   lua_Integer v2) {
116
3.51M
  switch (op) {
117
199k
    case LUA_OPADD: return intop(+, v1, v2);
118
780k
    case LUA_OPSUB:return intop(-, v1, v2);
119
72.6k
    case LUA_OPMUL:return intop(*, v1, v2);
120
340k
    case LUA_OPMOD: return luaV_mod(L, v1, v2);
121
264k
    case LUA_OPIDIV: return luaV_idiv(L, v1, v2);
122
16.0k
    case LUA_OPBAND: return intop(&, v1, v2);
123
13.0k
    case LUA_OPBOR: return intop(|, v1, v2);
124
117k
    case LUA_OPBXOR: return intop(^, v1, v2);
125
23.8k
    case LUA_OPSHL: return luaV_shiftl(v1, v2);
126
80.8k
    case LUA_OPSHR: return luaV_shiftr(v1, v2);
127
404k
    case LUA_OPUNM: return intop(-, 0, v1);
128
1.20M
    case LUA_OPBNOT: return intop(^, ~l_castS2U(0), v1);
129
0
    default: lua_assert(0); return 0;
130
3.51M
  }
131
3.51M
}
132
133
134
static lua_Number numarith (lua_State *L, int op, lua_Number v1,
135
4.38M
                                                  lua_Number v2) {
136
4.38M
  switch (op) {
137
34.0k
    case LUA_OPADD: return luai_numadd(L, v1, v2);
138
302k
    case LUA_OPSUB: return luai_numsub(L, v1, v2);
139
288k
    case LUA_OPMUL: return luai_nummul(L, v1, v2);
140
435k
    case LUA_OPDIV: return luai_numdiv(L, v1, v2);
141
2.53M
    case LUA_OPPOW: return luai_numpow(L, v1, v2);
142
149k
    case LUA_OPIDIV: return luai_numidiv(L, v1, v2);
143
566k
    case LUA_OPUNM: return luai_numunm(L, v1);
144
76.5k
    case LUA_OPMOD: return luaV_modf(L, v1, v2);
145
0
    default: lua_assert(0); return 0;
146
4.38M
  }
147
4.38M
}
148
149
150
int luaO_rawarith (lua_State *L, int op, const TValue *p1, const TValue *p2,
151
7.90M
                   TValue *res) {
152
7.90M
  switch (op) {
153
146k
    case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR:
154
251k
    case LUA_OPSHL: case LUA_OPSHR:
155
1.45M
    case LUA_OPBNOT: {  /* operate only on integers */
156
1.45M
      lua_Integer i1; lua_Integer i2;
157
1.45M
      if (tointegerns(p1, &i1) && tointegerns(p2, &i2)) {
158
1.45M
        setivalue(res, intarith(L, op, i1, i2));
159
1.45M
        return 1;
160
1.45M
      }
161
0
      else return 0;  /* fail */
162
1.45M
    }
163
2.96M
    case LUA_OPDIV: case LUA_OPPOW: {  /* operate only on floats */
164
2.96M
      lua_Number n1; lua_Number n2;
165
2.96M
      if (tonumberns(p1, n1) && tonumberns(p2, n2)) {
166
2.96M
        setfltvalue(res, numarith(L, op, n1, n2));
167
2.96M
        return 1;
168
2.96M
      }
169
0
      else return 0;  /* fail */
170
2.96M
    }
171
3.47M
    default: {  /* other operations */
172
3.47M
      lua_Number n1; lua_Number n2;
173
3.47M
      if (ttisinteger(p1) && ttisinteger(p2)) {
174
2.06M
        setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2)));
175
2.06M
        return 1;
176
2.06M
      }
177
1.41M
      else if (tonumberns(p1, n1) && tonumberns(p2, n2)) {
178
1.41M
        setfltvalue(res, numarith(L, op, n1, n2));
179
1.41M
        return 1;
180
1.41M
      }
181
0
      else return 0;  /* fail */
182
3.47M
    }
183
7.90M
  }
184
7.90M
}
185
186
187
void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2,
188
1.20M
                 StkId res) {
189
1.20M
  if (!luaO_rawarith(L, op, p1, p2, s2v(res))) {
190
    /* could not perform raw operation; try metamethod */
191
0
    luaT_trybinTM(L, p1, p2, res, cast(TMS, (op - LUA_OPADD) + TM_ADD));
192
0
  }
193
1.20M
}
194
195
196
3.46M
lu_byte luaO_hexavalue (int c) {
197
3.46M
  lua_assert(lisxdigit(c));
198
3.46M
  if (lisdigit(c)) return cast_byte(c - '0');
199
3.46M
  else return cast_byte((ltolower(c) - 'a') + 10);
200
3.46M
}
201
202
203
60.5M
static int isneg (const char **s) {
204
60.5M
  if (**s == '-') { (*s)++; return 1; }
205
60.4M
  else if (**s == '+') (*s)++;
206
60.4M
  return 0;
207
60.5M
}
208
209
210
211
/*
212
** {==================================================================
213
** Lua's implementation for 'lua_strx2number'
214
** ===================================================================
215
*/
216
217
#if !defined(lua_strx2number)
218
219
/* maximum number of significant digits to read (to avoid overflows
220
   even with single floats) */
221
#define MAXSIGDIG 30
222
223
/*
224
** convert a hexadecimal numeric string to a number, following
225
** C99 specification for 'strtod'
226
*/
227
static lua_Number lua_strx2number (const char *s, char **endptr) {
228
  int dot = lua_getlocaledecpoint();
229
  lua_Number r = l_mathop(0.0);  /* result (accumulator) */
230
  int sigdig = 0;  /* number of significant digits */
231
  int nosigdig = 0;  /* number of non-significant digits */
232
  int e = 0;  /* exponent correction */
233
  int neg;  /* 1 if number is negative */
234
  int hasdot = 0;  /* true after seen a dot */
235
  *endptr = cast_charp(s);  /* nothing is valid yet */
236
  while (lisspace(cast_uchar(*s))) s++;  /* skip initial spaces */
237
  neg = isneg(&s);  /* check sign */
238
  if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X')))  /* check '0x' */
239
    return l_mathop(0.0);  /* invalid format (no '0x') */
240
  for (s += 2; ; s++) {  /* skip '0x' and read numeral */
241
    if (*s == dot) {
242
      if (hasdot) break;  /* second dot? stop loop */
243
      else hasdot = 1;
244
    }
245
    else if (lisxdigit(cast_uchar(*s))) {
246
      if (sigdig == 0 && *s == '0')  /* non-significant digit (zero)? */
247
        nosigdig++;
248
      else if (++sigdig <= MAXSIGDIG)  /* can read it without overflow? */
249
          r = (r * l_mathop(16.0)) + luaO_hexavalue(*s);
250
      else e++;  /* too many digits; ignore, but still count for exponent */
251
      if (hasdot) e--;  /* decimal digit? correct exponent */
252
    }
253
    else break;  /* neither a dot nor a digit */
254
  }
255
  if (nosigdig + sigdig == 0)  /* no digits? */
256
    return l_mathop(0.0);  /* invalid format */
257
  *endptr = cast_charp(s);  /* valid up to here */
258
  e *= 4;  /* each digit multiplies/divides value by 2^4 */
259
  if (*s == 'p' || *s == 'P') {  /* exponent part? */
260
    int exp1 = 0;  /* exponent value */
261
    int neg1;  /* exponent sign */
262
    s++;  /* skip 'p' */
263
    neg1 = isneg(&s);  /* sign */
264
    if (!lisdigit(cast_uchar(*s)))
265
      return l_mathop(0.0);  /* invalid; must have at least one digit */
266
    while (lisdigit(cast_uchar(*s)))  /* read exponent */
267
      exp1 = exp1 * 10 + *(s++) - '0';
268
    if (neg1) exp1 = -exp1;
269
    e += exp1;
270
    *endptr = cast_charp(s);  /* valid up to here */
271
  }
272
  if (neg) r = -r;
273
  return l_mathop(ldexp)(r, e);
274
}
275
276
#endif
277
/* }====================================================== */
278
279
280
/* maximum length of a numeral to be converted to a number */
281
#if !defined (L_MAXLENNUM)
282
86.3k
#define L_MAXLENNUM 200
283
#endif
284
285
/*
286
** Convert string 's' to a Lua number (put in 'result'). Return NULL on
287
** fail or the address of the ending '\0' on success. ('mode' == 'x')
288
** means a hexadecimal numeral.
289
*/
290
13.1M
static const char *l_str2dloc (const char *s, lua_Number *result, int mode) {
291
13.1M
  char *endptr;
292
13.1M
  *result = (mode == 'x') ? lua_strx2number(s, &endptr)  /* try to convert */
293
13.1M
                          : lua_str2number(s, &endptr);
294
13.1M
  if (endptr == s) return NULL;  /* nothing recognized? */
295
5.18M
  while (lisspace(cast_uchar(*endptr))) endptr++;  /* skip trailing spaces */
296
5.18M
  return (*endptr == '\0') ? endptr : NULL;  /* OK iff no trailing chars */
297
13.1M
}
298
299
300
/*
301
** Convert string 's' to a Lua number (put in 'result') handling the
302
** current locale.
303
** This function accepts both the current locale or a dot as the radix
304
** mark. If the conversion fails, it may mean number has a dot but
305
** locale accepts something else. In that case, the code copies 's'
306
** to a buffer (because 's' is read-only), changes the dot to the
307
** current locale radix mark, and tries to convert again.
308
** The variable 'mode' checks for special characters in the string:
309
** - 'n' means 'inf' or 'nan' (which should be rejected)
310
** - 'x' means a hexadecimal numeral
311
** - '.' just optimizes the search for the common case (no special chars)
312
*/
313
43.7M
static const char *l_str2d (const char *s, lua_Number *result) {
314
43.7M
  const char *endptr;
315
43.7M
  const char *pmode = strpbrk(s, ".xXnN");  /* look for special chars */
316
43.7M
  int mode = pmode ? ltolower(cast_uchar(*pmode)) : 0;
317
43.7M
  if (mode == 'n')  /* reject 'inf' and 'nan' */
318
30.6M
    return NULL;
319
13.0M
  endptr = l_str2dloc(s, result, mode);  /* try to convert */
320
13.0M
  if (endptr == NULL) {  /* failed? may be a different locale */
321
8.43M
    char buff[L_MAXLENNUM + 1];
322
8.43M
    const char *pdot = strchr(s, '.');
323
8.43M
    if (pdot == NULL || strlen(s) > L_MAXLENNUM)
324
8.38M
      return NULL;  /* string too long or no dot; fail */
325
51.2k
    strcpy(buff, s);  /* copy string to buffer */
326
51.2k
    buff[pdot - s] = lua_getlocaledecpoint();  /* correct decimal point */
327
51.2k
    endptr = l_str2dloc(buff, result, mode);  /* try again */
328
51.2k
    if (endptr != NULL)
329
0
      endptr = s + (endptr - buff);  /* make relative to 's' */
330
51.2k
  }
331
4.70M
  return endptr;
332
13.0M
}
333
334
335
67.2M
#define MAXBY10   cast(lua_Unsigned, LUA_MAXINTEGER / 10)
336
18.5k
#define MAXLASTD  cast_int(LUA_MAXINTEGER % 10)
337
338
60.5M
static const char *l_str2int (const char *s, lua_Integer *result) {
339
60.5M
  lua_Unsigned a = 0;
340
60.5M
  int empty = 1;
341
60.5M
  int neg;
342
60.5M
  while (lisspace(cast_uchar(*s))) s++;  /* skip initial spaces */
343
60.5M
  neg = isneg(&s);
344
60.5M
  if (s[0] == '0' &&
345
60.5M
      (s[1] == 'x' || s[1] == 'X')) {  /* hex? */
346
140k
    s += 2;  /* skip '0x' */
347
2.99M
    for (; lisxdigit(cast_uchar(*s)); s++) {
348
2.99M
      a = a * 16 + luaO_hexavalue(*s);
349
2.99M
      empty = 0;
350
2.99M
    }
351
140k
  }
352
60.3M
  else {  /* decimal */
353
67.0M
    for (; lisdigit(cast_uchar(*s)); s++) {
354
67.0M
      int d = *s - '0';
355
67.0M
      if (a >= MAXBY10 && (a > MAXBY10 || d > MAXLASTD + neg))  /* overflow? */
356
135k
        return NULL;  /* do not accept it (as integer) */
357
66.9M
      a = a * 10 + cast_uint(d);
358
66.9M
      empty = 0;
359
66.9M
    }
360
60.3M
  }
361
60.4M
  while (lisspace(cast_uchar(*s))) s++;  /* skip trailing spaces */
362
60.4M
  if (empty || *s != '\0') return NULL;  /* something wrong in the numeral */
363
16.8M
  else {
364
16.8M
    *result = l_castU2S((neg) ? 0u - a : a);
365
16.8M
    return s;
366
16.8M
  }
367
60.4M
}
368
369
370
60.5M
size_t luaO_str2num (const char *s, TValue *o) {
371
60.5M
  lua_Integer i; lua_Number n;
372
60.5M
  const char *e;
373
60.5M
  if ((e = l_str2int(s, &i)) != NULL) {  /* try as an integer */
374
16.8M
    setivalue(o, i);
375
16.8M
  }
376
43.7M
  else if ((e = l_str2d(s, &n)) != NULL) {  /* else try as a float */
377
4.65M
    setfltvalue(o, n);
378
4.65M
  }
379
39.0M
  else
380
39.0M
    return 0;  /* conversion failed */
381
21.4M
  return ct_diff2sz(e - s) + 1;  /* success; return string size */
382
60.5M
}
383
384
385
17.9k
int luaO_utf8esc (char *buff, l_uint32 x) {
386
17.9k
  int n = 1;  /* number of bytes put in buffer (backwards) */
387
17.9k
  lua_assert(x <= 0x7FFFFFFFu);
388
17.9k
  if (x < 0x80)  /* ASCII? */
389
6.49k
    buff[UTF8BUFFSZ - 1] = cast_char(x);
390
11.4k
  else {  /* need continuation bytes */
391
11.4k
    unsigned int mfb = 0x3f;  /* maximum that fits in first byte */
392
31.2k
    do {  /* add continuation bytes */
393
31.2k
      buff[UTF8BUFFSZ - (n++)] = cast_char(0x80 | (x & 0x3f));
394
31.2k
      x >>= 6;  /* remove added bits */
395
31.2k
      mfb >>= 1;  /* now there is one less bit available in first byte */
396
31.2k
    } while (x > mfb);  /* still needs continuation byte? */
397
11.4k
    buff[UTF8BUFFSZ - n] = cast_char((~mfb << 1) | x);  /* add first byte */
398
11.4k
  }
399
17.9k
  return n;
400
17.9k
}
401
402
403
/*
404
** The size of the buffer for the conversion of a number to a string
405
** 'LUA_N2SBUFFSZ' must be enough to accommodate both LUA_INTEGER_FMT
406
** and LUA_NUMBER_FMT.  For a long long int, this is 19 digits plus a
407
** sign and a final '\0', adding to 21. For a long double, it can go to
408
** a sign, the dot, an exponent letter, an exponent sign, 4 exponent
409
** digits, the final '\0', plus the significant digits, which are
410
** approximately the *_DIG attribute.
411
*/
412
#if LUA_N2SBUFFSZ < (20 + l_floatatt(DIG))
413
#error "invalid value for LUA_N2SBUFFSZ"
414
#endif
415
416
417
/*
418
** Convert a float to a string, adding it to a buffer. First try with
419
** a not too large number of digits, to avoid noise (for instance,
420
** 1.1 going to "1.1000000000000001"). If that lose precision, so
421
** that reading the result back gives a different number, then do the
422
** conversion again with extra precision. Moreover, if the numeral looks
423
** like an integer (without a decimal point or an exponent), add ".0" to
424
** its end.
425
*/
426
13.2M
static int tostringbuffFloat (lua_Number n, char *buff) {
427
  /* first conversion */
428
13.2M
  int len = l_sprintf(buff, LUA_N2SBUFFSZ, LUA_NUMBER_FMT,
429
13.2M
                            (LUAI_UACNUMBER)n);
430
13.2M
  lua_Number check = lua_str2number(buff, NULL);  /* read it back */
431
13.2M
  if (check != n) {  /* not enough precision? */
432
    /* convert again with more precision */
433
1.63M
    len = l_sprintf(buff, LUA_N2SBUFFSZ, LUA_NUMBER_FMT_N,
434
1.63M
                          (LUAI_UACNUMBER)n);
435
1.63M
  }
436
  /* looks like an integer? */
437
13.2M
  if (buff[strspn(buff, "-0123456789")] == '\0') {
438
6.64M
    buff[len++] = lua_getlocaledecpoint();
439
6.64M
    buff[len++] = '0';  /* adds '.0' to result */
440
6.64M
  }
441
13.2M
  return len;
442
13.2M
}
443
444
445
/*
446
** Convert a number object to a string, adding it to a buffer.
447
*/
448
42.4M
unsigned luaO_tostringbuff (const TValue *obj, char *buff) {
449
42.4M
  int len;
450
42.4M
  lua_assert(ttisnumber(obj));
451
42.4M
  if (ttisinteger(obj))
452
29.2M
    len = lua_integer2str(buff, LUA_N2SBUFFSZ, ivalue(obj));
453
13.2M
  else
454
13.2M
    len = tostringbuffFloat(fltvalue(obj), buff);
455
42.4M
  lua_assert(len < LUA_N2SBUFFSZ);
456
42.4M
  return cast_uint(len);
457
42.4M
}
458
459
460
/*
461
** Convert a number object to a Lua string, replacing the value at 'obj'
462
*/
463
8.30M
void luaO_tostring (lua_State *L, TValue *obj) {
464
8.30M
  char buff[LUA_N2SBUFFSZ];
465
8.30M
  unsigned len = luaO_tostringbuff(obj, buff);
466
8.30M
  setsvalue(L, obj, luaS_newlstr(L, buff, len));
467
8.30M
}
468
469
470
471
472
/*
473
** {==================================================================
474
** 'luaO_pushvfstring'
475
** ===================================================================
476
*/
477
478
/*
479
** Size for buffer space used by 'luaO_pushvfstring'. It should be
480
** (LUA_IDSIZE + LUA_N2SBUFFSZ) + a minimal space for basic messages,
481
** so that 'luaG_addinfo' can work directly on the static buffer.
482
*/
483
#define BUFVFS    cast_uint(LUA_IDSIZE + LUA_N2SBUFFSZ + 95)
484
485
/*
486
** Buffer used by 'luaO_pushvfstring'. 'err' signals an error while
487
** building result (memory error [1] or buffer overflow [2]).
488
*/
489
typedef struct BuffFS {
490
  lua_State *L;
491
  char *b;
492
  size_t buffsize;
493
  size_t blen;  /* length of string in 'buff' */
494
  int err;
495
  char space[BUFVFS];  /* initial buffer */
496
} BuffFS;
497
498
499
32.2M
static void initbuff (lua_State *L, BuffFS *buff) {
500
32.2M
  buff->L = L;
501
32.2M
  buff->b = buff->space;
502
32.2M
  buff->buffsize = sizeof(buff->space);
503
32.2M
  buff->blen = 0;
504
32.2M
  buff->err = 0;
505
32.2M
}
506
507
508
/*
509
** Push final result from 'luaO_pushvfstring'. This function may raise
510
** errors explicitly or through memory errors, so it must run protected.
511
*/
512
32.2M
static void pushbuff (lua_State *L, void *ud) {
513
32.2M
  BuffFS *buff = cast(BuffFS*, ud);
514
32.2M
  switch (buff->err) {
515
0
    case 1:  /* memory error */
516
0
      luaD_throw(L, LUA_ERRMEM);
517
0
      break;
518
0
    case 2:  /* length overflow: Add "..." at the end of result */
519
0
      if (buff->buffsize - buff->blen < 3)
520
0
        strcpy(buff->b + buff->blen - 3, "...");  /* 'blen' must be > 3 */
521
0
      else {  /* there is enough space left for the "..." */
522
0
        strcpy(buff->b + buff->blen, "...");
523
0
        buff->blen += 3;
524
0
      }
525
      /* FALLTHROUGH */
526
32.2M
    default: {  /* no errors, but it can raise one creating the new string */
527
32.2M
      TString *ts = luaS_newlstr(L, buff->b, buff->blen);
528
32.2M
      setsvalue2s(L, L->top.p, ts);
529
32.2M
      L->top.p++;
530
32.2M
    }
531
32.2M
  }
532
32.2M
}
533
534
535
32.2M
static const char *clearbuff (BuffFS *buff) {
536
32.2M
  lua_State *L = buff->L;
537
32.2M
  const char *res;
538
32.2M
  if (luaD_rawrunprotected(L, pushbuff, buff) != LUA_OK)  /* errors? */
539
0
    res = NULL;  /* error message is on the top of the stack */
540
32.2M
  else
541
32.2M
    res = getstr(tsvalue(s2v(L->top.p - 1)));
542
32.2M
  if (buff->b != buff->space)  /* using dynamic buffer? */
543
761k
    luaM_freearray(L, buff->b, buff->buffsize);  /* free it */
544
32.2M
  return res;
545
32.2M
}
546
547
548
162M
static void addstr2buff (BuffFS *buff, const char *str, size_t slen) {
549
162M
  size_t left = buff->buffsize - buff->blen;  /* space left in the buffer */
550
162M
  if (buff->err)  /* do nothing else after an error */
551
0
    return;
552
162M
  if (slen > left) {  /* new string doesn't fit into current buffer? */
553
823k
    if (slen > ((MAX_SIZE/2) - buff->blen)) {  /* overflow? */
554
0
      memcpy(buff->b + buff->blen, str, left);  /* copy what it can */
555
0
      buff->blen = buff->buffsize;
556
0
      buff->err = 2;  /* doesn't add anything else */
557
0
      return;
558
0
    }
559
823k
    else {
560
823k
      size_t newsize = buff->buffsize + slen;  /* limited to MAX_SIZE/2 */
561
823k
      char *newb =
562
823k
        (buff->b == buff->space)  /* still using static space? */
563
823k
        ? luaM_reallocvector(buff->L, NULL, 0, newsize, char)
564
823k
        : luaM_reallocvector(buff->L, buff->b, buff->buffsize, newsize,
565
823k
                                                               char);
566
823k
      if (newb == NULL) {  /* allocation error? */
567
0
        buff->err = 1;  /* signal a memory error */
568
0
        return;
569
0
      }
570
823k
      if (buff->b == buff->space)  /* new buffer (not reallocated)? */
571
761k
        memcpy(newb, buff->b, buff->blen);  /* copy previous content */
572
823k
      buff->b = newb;  /* set new (larger) buffer... */
573
823k
      buff->buffsize = newsize;  /* ...and its new size */
574
823k
    }
575
823k
  }
576
162M
  memcpy(buff->b + buff->blen, str, slen);  /* copy new content */
577
162M
  buff->blen += slen;
578
162M
}
579
580
581
/*
582
** Add a numeral to the buffer.
583
*/
584
12.3M
static void addnum2buff (BuffFS *buff, TValue *num) {
585
12.3M
  char numbuff[LUA_N2SBUFFSZ];
586
12.3M
  unsigned len = luaO_tostringbuff(num, numbuff);
587
12.3M
  addstr2buff(buff, numbuff, len);
588
12.3M
}
589
590
591
/*
592
** this function handles only '%d', '%c', '%f', '%p', '%s', and '%%'
593
   conventional formats, plus Lua-specific '%I' and '%U'
594
*/
595
32.2M
const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
596
32.2M
  BuffFS buff;  /* holds last part of the result */
597
32.2M
  const char *e;  /* points to next '%' */
598
32.2M
  initbuff(L, &buff);
599
97.3M
  while ((e = strchr(fmt, '%')) != NULL) {
600
65.1M
    addstr2buff(&buff, fmt, ct_diff2sz(e - fmt));  /* add 'fmt' up to '%' */
601
65.1M
    switch (*(e + 1)) {  /* conversion specifier */
602
50.5M
      case 's': {  /* zero-terminated string */
603
50.5M
        const char *s = va_arg(argp, char *);
604
50.5M
        if (s == NULL) s = "(null)";
605
50.5M
        addstr2buff(&buff, s, strlen(s));
606
50.5M
        break;
607
0
      }
608
1.65M
      case 'c': {  /* an 'int' as a character */
609
1.65M
        char c = cast_char(va_arg(argp, int));
610
1.65M
        addstr2buff(&buff, &c, sizeof(char));
611
1.65M
        break;
612
0
      }
613
12.3M
      case 'd': {  /* an 'int' */
614
12.3M
        TValue num;
615
12.3M
        setivalue(&num, va_arg(argp, int));
616
12.3M
        addnum2buff(&buff, &num);
617
12.3M
        break;
618
0
      }
619
27
      case 'I': {  /* a 'lua_Integer' */
620
27
        TValue num;
621
27
        setivalue(&num, cast_Integer(va_arg(argp, l_uacInt)));
622
27
        addnum2buff(&buff, &num);
623
27
        break;
624
0
      }
625
15
      case 'f': {  /* a 'lua_Number' */
626
15
        TValue num;
627
15
        setfltvalue(&num, cast_num(va_arg(argp, l_uacNumber)));
628
15
        addnum2buff(&buff, &num);
629
15
        break;
630
0
      }
631
388k
      case 'p': {  /* a pointer */
632
388k
        char bf[LUA_N2SBUFFSZ];  /* enough space for '%p' */
633
388k
        void *p = va_arg(argp, void *);
634
388k
        int len = lua_pointer2str(bf, LUA_N2SBUFFSZ, p);
635
388k
        addstr2buff(&buff, bf, cast_uint(len));
636
388k
        break;
637
0
      }
638
613
      case 'U': {  /* an 'unsigned long' as a UTF-8 sequence */
639
613
        char bf[UTF8BUFFSZ];
640
613
        unsigned long arg = va_arg(argp, unsigned long);
641
613
        int len = luaO_utf8esc(bf, cast(l_uint32, arg));
642
613
        addstr2buff(&buff, bf + UTF8BUFFSZ - len, cast_uint(len));
643
613
        break;
644
0
      }
645
114k
      case '%': {
646
114k
        addstr2buff(&buff, "%", 1);
647
114k
        break;
648
0
      }
649
0
      default: {
650
0
        addstr2buff(&buff, e, 2);  /* keep unknown format in the result */
651
0
        break;
652
0
      }
653
65.1M
    }
654
65.1M
    fmt = e + 2;  /* skip '%' and the specifier */
655
65.1M
  }
656
32.2M
  addstr2buff(&buff, fmt, strlen(fmt));  /* rest of 'fmt' */
657
32.2M
  return clearbuff(&buff);  /* empty buffer into a new string */
658
32.2M
}
659
660
661
20.8M
const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) {
662
20.8M
  const char *msg;
663
20.8M
  va_list argp;
664
20.8M
  va_start(argp, fmt);
665
20.8M
  msg = luaO_pushvfstring(L, fmt, argp);
666
20.8M
  va_end(argp);
667
20.8M
  if (msg == NULL)  /* error? */
668
0
    luaD_throw(L, LUA_ERRMEM);
669
20.8M
  return msg;
670
20.8M
}
671
672
/* }================================================================== */
673
674
675
#define RETS  "..."
676
#define PRE "[string \""
677
15.4M
#define POS "\"]"
678
679
40.6M
#define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) )
680
681
19.5M
void luaO_chunkid (char *out, const char *source, size_t srclen) {
682
19.5M
  size_t bufflen = LUA_IDSIZE;  /* free space in buffer */
683
19.5M
  if (*source == '=') {  /* 'literal' source */
684
4.10M
    if (srclen <= bufflen)  /* small enough? */
685
4.08M
      memcpy(out, source + 1, srclen * sizeof(char));
686
15.8k
    else {  /* truncate it */
687
15.8k
      addstr(out, source + 1, bufflen - 1);
688
15.8k
      *out = '\0';
689
15.8k
    }
690
4.10M
  }
691
15.4M
  else if (*source == '@') {  /* file name */
692
16.1k
    if (srclen <= bufflen)  /* small enough? */
693
8.75k
      memcpy(out, source + 1, srclen * sizeof(char));
694
7.42k
    else {  /* add '...' before rest of name */
695
7.42k
      addstr(out, RETS, LL(RETS));
696
7.42k
      bufflen -= LL(RETS);
697
7.42k
      memcpy(out, source + 1 + srclen - bufflen, bufflen * sizeof(char));
698
7.42k
    }
699
16.1k
  }
700
15.4M
  else {  /* string; format as [string "source"] */
701
15.4M
    const char *nl = strchr(source, '\n');  /* find first new line (if any) */
702
15.4M
    addstr(out, PRE, LL(PRE));  /* add prefix */
703
15.4M
    bufflen -= LL(PRE RETS POS) + 1;  /* save space for prefix+suffix+'\0' */
704
15.4M
    if (srclen < bufflen && nl == NULL) {  /* small one-line source? */
705
5.62M
      addstr(out, source, srclen);  /* keep it */
706
5.62M
    }
707
9.79M
    else {
708
9.79M
      if (nl != NULL)
709
7.33M
        srclen = ct_diff2sz(nl - source);  /* stop at first newline */
710
9.79M
      if (srclen > bufflen) srclen = bufflen;
711
9.79M
      addstr(out, source, srclen);
712
9.79M
      addstr(out, RETS, LL(RETS));
713
9.79M
    }
714
15.4M
    memcpy(out, POS, (LL(POS) + 1) * sizeof(char));
715
15.4M
  }
716
19.5M
}
717