~reviczky/luatex/luatex-svn

« back to all changes in this revision

Viewing changes to source/libs/luajit/LuaJIT-2.0.3/src/lib_string.c

  • Committer: Adam Reviczky
  • Date: 2015-03-29 18:56:26 UTC
  • Revision ID: adam.reviczky@kclalumni.net-20150329185626-7j7tmwyfpa69lqwo
Revision 5213

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
** String library.
 
3
** Copyright (C) 2005-2014 Mike Pall. See Copyright Notice in luajit.h
 
4
**
 
5
** Major portions taken verbatim or adapted from the Lua interpreter.
 
6
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
 
7
*/
 
8
 
 
9
#include <stdio.h>
 
10
 
 
11
#define lib_string_c
 
12
#define LUA_LIB
 
13
 
 
14
#include "lua.h"
 
15
#include "lauxlib.h"
 
16
#include "lualib.h"
 
17
 
 
18
#include "lj_obj.h"
 
19
#include "lj_gc.h"
 
20
#include "lj_err.h"
 
21
#include "lj_str.h"
 
22
#include "lj_tab.h"
 
23
#include "lj_meta.h"
 
24
#include "lj_state.h"
 
25
#include "lj_ff.h"
 
26
#include "lj_bcdump.h"
 
27
#include "lj_char.h"
 
28
#include "lj_lib.h"
 
29
 
 
30
/* ------------------------------------------------------------------------ */
 
31
 
 
32
#define LJLIB_MODULE_string
 
33
 
 
34
LJLIB_ASM(string_len)           LJLIB_REC(.)
 
35
{
 
36
  lj_lib_checkstr(L, 1);
 
37
  return FFH_RETRY;
 
38
}
 
39
 
 
40
LJLIB_ASM(string_byte)          LJLIB_REC(string_range 0)
 
41
{
 
42
  GCstr *s = lj_lib_checkstr(L, 1);
 
43
  int32_t len = (int32_t)s->len;
 
44
  int32_t start = lj_lib_optint(L, 2, 1);
 
45
  int32_t stop = lj_lib_optint(L, 3, start);
 
46
  int32_t n, i;
 
47
  const unsigned char *p;
 
48
  if (stop < 0) stop += len+1;
 
49
  if (start < 0) start += len+1;
 
50
  if (start <= 0) start = 1;
 
51
  if (stop > len) stop = len;
 
52
  if (start > stop) return FFH_RES(0);  /* Empty interval: return no results. */
 
53
  start--;
 
54
  n = stop - start;
 
55
  if ((uint32_t)n > LUAI_MAXCSTACK)
 
56
    lj_err_caller(L, LJ_ERR_STRSLC);
 
57
  lj_state_checkstack(L, (MSize)n);
 
58
  p = (const unsigned char *)strdata(s) + start;
 
59
  for (i = 0; i < n; i++)
 
60
    setintV(L->base + i-1, p[i]);
 
61
  return FFH_RES(n);
 
62
}
 
63
 
 
64
LJLIB_ASM(string_char)
 
65
{
 
66
  int i, nargs = (int)(L->top - L->base);
 
67
  char *buf = lj_str_needbuf(L, &G(L)->tmpbuf, (MSize)nargs);
 
68
  for (i = 1; i <= nargs; i++) {
 
69
    int32_t k = lj_lib_checkint(L, i);
 
70
    if (!checku8(k))
 
71
      lj_err_arg(L, i, LJ_ERR_BADVAL);
 
72
    buf[i-1] = (char)k;
 
73
  }
 
74
  setstrV(L, L->base-1, lj_str_new(L, buf, (size_t)nargs));
 
75
  return FFH_RES(1);
 
76
}
 
77
 
 
78
LJLIB_ASM(string_sub)           LJLIB_REC(string_range 1)
 
79
{
 
80
  lj_lib_checkstr(L, 1);
 
81
  lj_lib_checkint(L, 2);
 
82
  setintV(L->base+2, lj_lib_optint(L, 3, -1));
 
83
  return FFH_RETRY;
 
84
}
 
85
 
 
86
LJLIB_ASM(string_rep)
 
87
{
 
88
  GCstr *s = lj_lib_checkstr(L, 1);
 
89
  int32_t k = lj_lib_checkint(L, 2);
 
90
  GCstr *sep = lj_lib_optstr(L, 3);
 
91
  int32_t len = (int32_t)s->len;
 
92
  global_State *g = G(L);
 
93
  int64_t tlen;
 
94
  const char *src;
 
95
  char *buf;
 
96
  if (k <= 0) {
 
97
  empty:
 
98
    setstrV(L, L->base-1, &g->strempty);
 
99
    return FFH_RES(1);
 
100
  }
 
101
  if (sep) {
 
102
    tlen = (int64_t)len + sep->len;
 
103
    if (tlen > LJ_MAX_STR)
 
104
      lj_err_caller(L, LJ_ERR_STROV);
 
105
    tlen *= k;
 
106
    if (tlen > LJ_MAX_STR)
 
107
      lj_err_caller(L, LJ_ERR_STROV);
 
108
  } else {
 
109
    tlen = (int64_t)k * len;
 
110
    if (tlen > LJ_MAX_STR)
 
111
      lj_err_caller(L, LJ_ERR_STROV);
 
112
  }
 
113
  if (tlen == 0) goto empty;
 
114
  buf = lj_str_needbuf(L, &g->tmpbuf, (MSize)tlen);
 
115
  src = strdata(s);
 
116
  if (sep) {
 
117
    tlen -= sep->len;  /* Ignore trailing separator. */
 
118
    if (k > 1) {  /* Paste one string and one separator. */
 
119
      int32_t i;
 
120
      i = 0; while (i < len) *buf++ = src[i++];
 
121
      src = strdata(sep); len = sep->len;
 
122
      i = 0; while (i < len) *buf++ = src[i++];
 
123
      src = g->tmpbuf.buf; len += s->len; k--;  /* Now copy that k-1 times. */
 
124
    }
 
125
  }
 
126
  do {
 
127
    int32_t i = 0;
 
128
    do { *buf++ = src[i++]; } while (i < len);
 
129
  } while (--k > 0);
 
130
  setstrV(L, L->base-1, lj_str_new(L, g->tmpbuf.buf, (size_t)tlen));
 
131
  return FFH_RES(1);
 
132
}
 
133
 
 
134
LJLIB_ASM(string_reverse)
 
135
{
 
136
  GCstr *s = lj_lib_checkstr(L, 1);
 
137
  lj_str_needbuf(L, &G(L)->tmpbuf, s->len);
 
138
  return FFH_RETRY;
 
139
}
 
140
LJLIB_ASM_(string_lower)
 
141
LJLIB_ASM_(string_upper)
 
142
 
 
143
/* ------------------------------------------------------------------------ */
 
144
 
 
145
static int writer_buf(lua_State *L, const void *p, size_t size, void *b)
 
146
{
 
147
  luaL_addlstring((luaL_Buffer *)b, (const char *)p, size);
 
148
  UNUSED(L);
 
149
  return 0;
 
150
}
 
151
 
 
152
LJLIB_CF(string_dump)
 
153
{
 
154
  GCfunc *fn = lj_lib_checkfunc(L, 1);
 
155
  int strip = L->base+1 < L->top && tvistruecond(L->base+1);
 
156
  luaL_Buffer b;
 
157
  L->top = L->base+1;
 
158
  luaL_buffinit(L, &b);
 
159
  if (!isluafunc(fn) || lj_bcwrite(L, funcproto(fn), writer_buf, &b, strip))
 
160
    lj_err_caller(L, LJ_ERR_STRDUMP);
 
161
  luaL_pushresult(&b);
 
162
  return 1;
 
163
}
 
164
 
 
165
/* ------------------------------------------------------------------------ */
 
166
 
 
167
/* macro to `unsign' a character */
 
168
#define uchar(c)        ((unsigned char)(c))
 
169
 
 
170
#define CAP_UNFINISHED  (-1)
 
171
#define CAP_POSITION    (-2)
 
172
 
 
173
typedef struct MatchState {
 
174
  const char *src_init;  /* init of source string */
 
175
  const char *src_end;  /* end (`\0') of source string */
 
176
  lua_State *L;
 
177
  int level;  /* total number of captures (finished or unfinished) */
 
178
  int depth;
 
179
  struct {
 
180
    const char *init;
 
181
    ptrdiff_t len;
 
182
  } capture[LUA_MAXCAPTURES];
 
183
} MatchState;
 
184
 
 
185
#define L_ESC           '%'
 
186
#define SPECIALS        "^$*+?.([%-"
 
187
 
 
188
static int check_capture(MatchState *ms, int l)
 
189
{
 
190
  l -= '1';
 
191
  if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED)
 
192
    lj_err_caller(ms->L, LJ_ERR_STRCAPI);
 
193
  return l;
 
194
}
 
195
 
 
196
static int capture_to_close(MatchState *ms)
 
197
{
 
198
  int level = ms->level;
 
199
  for (level--; level>=0; level--)
 
200
    if (ms->capture[level].len == CAP_UNFINISHED) return level;
 
201
  lj_err_caller(ms->L, LJ_ERR_STRPATC);
 
202
  return 0;  /* unreachable */
 
203
}
 
204
 
 
205
static const char *classend(MatchState *ms, const char *p)
 
206
{
 
207
  switch (*p++) {
 
208
  case L_ESC:
 
209
    if (*p == '\0')
 
210
      lj_err_caller(ms->L, LJ_ERR_STRPATE);
 
211
    return p+1;
 
212
  case '[':
 
213
    if (*p == '^') p++;
 
214
    do {  /* look for a `]' */
 
215
      if (*p == '\0')
 
216
        lj_err_caller(ms->L, LJ_ERR_STRPATM);
 
217
      if (*(p++) == L_ESC && *p != '\0')
 
218
        p++;  /* skip escapes (e.g. `%]') */
 
219
    } while (*p != ']');
 
220
    return p+1;
 
221
  default:
 
222
    return p;
 
223
  }
 
224
}
 
225
 
 
226
static const unsigned char match_class_map[32] = {
 
227
  0,LJ_CHAR_ALPHA,0,LJ_CHAR_CNTRL,LJ_CHAR_DIGIT,0,0,LJ_CHAR_GRAPH,0,0,0,0,
 
228
  LJ_CHAR_LOWER,0,0,0,LJ_CHAR_PUNCT,0,0,LJ_CHAR_SPACE,0,
 
229
  LJ_CHAR_UPPER,0,LJ_CHAR_ALNUM,LJ_CHAR_XDIGIT,0,0,0,0,0,0,0
 
230
};
 
231
 
 
232
static int match_class(int c, int cl)
 
233
{
 
234
  if ((cl & 0xc0) == 0x40) {
 
235
    int t = match_class_map[(cl&0x1f)];
 
236
    if (t) {
 
237
      t = lj_char_isa(c, t);
 
238
      return (cl & 0x20) ? t : !t;
 
239
    }
 
240
    if (cl == 'z') return c == 0;
 
241
    if (cl == 'Z') return c != 0;
 
242
  }
 
243
  return (cl == c);
 
244
}
 
245
 
 
246
static int matchbracketclass(int c, const char *p, const char *ec)
 
247
{
 
248
  int sig = 1;
 
249
  if (*(p+1) == '^') {
 
250
    sig = 0;
 
251
    p++;  /* skip the `^' */
 
252
  }
 
253
  while (++p < ec) {
 
254
    if (*p == L_ESC) {
 
255
      p++;
 
256
      if (match_class(c, uchar(*p)))
 
257
        return sig;
 
258
    }
 
259
    else if ((*(p+1) == '-') && (p+2 < ec)) {
 
260
      p+=2;
 
261
      if (uchar(*(p-2)) <= c && c <= uchar(*p))
 
262
        return sig;
 
263
    }
 
264
    else if (uchar(*p) == c) return sig;
 
265
  }
 
266
  return !sig;
 
267
}
 
268
 
 
269
static int singlematch(int c, const char *p, const char *ep)
 
270
{
 
271
  switch (*p) {
 
272
  case '.': return 1;  /* matches any char */
 
273
  case L_ESC: return match_class(c, uchar(*(p+1)));
 
274
  case '[': return matchbracketclass(c, p, ep-1);
 
275
  default:  return (uchar(*p) == c);
 
276
  }
 
277
}
 
278
 
 
279
static const char *match(MatchState *ms, const char *s, const char *p);
 
280
 
 
281
static const char *matchbalance(MatchState *ms, const char *s, const char *p)
 
282
{
 
283
  if (*p == 0 || *(p+1) == 0)
 
284
    lj_err_caller(ms->L, LJ_ERR_STRPATU);
 
285
  if (*s != *p) {
 
286
    return NULL;
 
287
  } else {
 
288
    int b = *p;
 
289
    int e = *(p+1);
 
290
    int cont = 1;
 
291
    while (++s < ms->src_end) {
 
292
      if (*s == e) {
 
293
        if (--cont == 0) return s+1;
 
294
      } else if (*s == b) {
 
295
        cont++;
 
296
      }
 
297
    }
 
298
  }
 
299
  return NULL;  /* string ends out of balance */
 
300
}
 
301
 
 
302
static const char *max_expand(MatchState *ms, const char *s,
 
303
                              const char *p, const char *ep)
 
304
{
 
305
  ptrdiff_t i = 0;  /* counts maximum expand for item */
 
306
  while ((s+i)<ms->src_end && singlematch(uchar(*(s+i)), p, ep))
 
307
    i++;
 
308
  /* keeps trying to match with the maximum repetitions */
 
309
  while (i>=0) {
 
310
    const char *res = match(ms, (s+i), ep+1);
 
311
    if (res) return res;
 
312
    i--;  /* else didn't match; reduce 1 repetition to try again */
 
313
  }
 
314
  return NULL;
 
315
}
 
316
 
 
317
static const char *min_expand(MatchState *ms, const char *s,
 
318
                              const char *p, const char *ep)
 
319
{
 
320
  for (;;) {
 
321
    const char *res = match(ms, s, ep+1);
 
322
    if (res != NULL)
 
323
      return res;
 
324
    else if (s<ms->src_end && singlematch(uchar(*s), p, ep))
 
325
      s++;  /* try with one more repetition */
 
326
    else
 
327
      return NULL;
 
328
  }
 
329
}
 
330
 
 
331
static const char *start_capture(MatchState *ms, const char *s,
 
332
                                 const char *p, int what)
 
333
{
 
334
  const char *res;
 
335
  int level = ms->level;
 
336
  if (level >= LUA_MAXCAPTURES) lj_err_caller(ms->L, LJ_ERR_STRCAPN);
 
337
  ms->capture[level].init = s;
 
338
  ms->capture[level].len = what;
 
339
  ms->level = level+1;
 
340
  if ((res=match(ms, s, p)) == NULL)  /* match failed? */
 
341
    ms->level--;  /* undo capture */
 
342
  return res;
 
343
}
 
344
 
 
345
static const char *end_capture(MatchState *ms, const char *s,
 
346
                               const char *p)
 
347
{
 
348
  int l = capture_to_close(ms);
 
349
  const char *res;
 
350
  ms->capture[l].len = s - ms->capture[l].init;  /* close capture */
 
351
  if ((res = match(ms, s, p)) == NULL)  /* match failed? */
 
352
    ms->capture[l].len = CAP_UNFINISHED;  /* undo capture */
 
353
  return res;
 
354
}
 
355
 
 
356
static const char *match_capture(MatchState *ms, const char *s, int l)
 
357
{
 
358
  size_t len;
 
359
  l = check_capture(ms, l);
 
360
  len = (size_t)ms->capture[l].len;
 
361
  if ((size_t)(ms->src_end-s) >= len &&
 
362
      memcmp(ms->capture[l].init, s, len) == 0)
 
363
    return s+len;
 
364
  else
 
365
    return NULL;
 
366
}
 
367
 
 
368
static const char *match(MatchState *ms, const char *s, const char *p)
 
369
{
 
370
  if (++ms->depth > LJ_MAX_XLEVEL)
 
371
    lj_err_caller(ms->L, LJ_ERR_STRPATX);
 
372
  init: /* using goto's to optimize tail recursion */
 
373
  switch (*p) {
 
374
  case '(':  /* start capture */
 
375
    if (*(p+1) == ')')  /* position capture? */
 
376
      s = start_capture(ms, s, p+2, CAP_POSITION);
 
377
    else
 
378
      s = start_capture(ms, s, p+1, CAP_UNFINISHED);
 
379
    break;
 
380
  case ')':  /* end capture */
 
381
    s = end_capture(ms, s, p+1);
 
382
    break;
 
383
  case L_ESC:
 
384
    switch (*(p+1)) {
 
385
    case 'b':  /* balanced string? */
 
386
      s = matchbalance(ms, s, p+2);
 
387
      if (s == NULL) break;
 
388
      p+=4;
 
389
      goto init;  /* else s = match(ms, s, p+4); */
 
390
    case 'f': {  /* frontier? */
 
391
      const char *ep; char previous;
 
392
      p += 2;
 
393
      if (*p != '[')
 
394
        lj_err_caller(ms->L, LJ_ERR_STRPATB);
 
395
      ep = classend(ms, p);  /* points to what is next */
 
396
      previous = (s == ms->src_init) ? '\0' : *(s-1);
 
397
      if (matchbracketclass(uchar(previous), p, ep-1) ||
 
398
         !matchbracketclass(uchar(*s), p, ep-1)) { s = NULL; break; }
 
399
      p=ep;
 
400
      goto init;  /* else s = match(ms, s, ep); */
 
401
      }
 
402
    default:
 
403
      if (lj_char_isdigit(uchar(*(p+1)))) {  /* capture results (%0-%9)? */
 
404
        s = match_capture(ms, s, uchar(*(p+1)));
 
405
        if (s == NULL) break;
 
406
        p+=2;
 
407
        goto init;  /* else s = match(ms, s, p+2) */
 
408
      }
 
409
      goto dflt;  /* case default */
 
410
    }
 
411
    break;
 
412
  case '\0':  /* end of pattern */
 
413
    break;  /* match succeeded */
 
414
  case '$':
 
415
    /* is the `$' the last char in pattern? */
 
416
    if (*(p+1) != '\0') goto dflt;
 
417
    if (s != ms->src_end) s = NULL;  /* check end of string */
 
418
    break;
 
419
  default: dflt: {  /* it is a pattern item */
 
420
    const char *ep = classend(ms, p);  /* points to what is next */
 
421
    int m = s<ms->src_end && singlematch(uchar(*s), p, ep);
 
422
    switch (*ep) {
 
423
    case '?': {  /* optional */
 
424
      const char *res;
 
425
      if (m && ((res=match(ms, s+1, ep+1)) != NULL)) {
 
426
        s = res;
 
427
        break;
 
428
      }
 
429
      p=ep+1;
 
430
      goto init;  /* else s = match(ms, s, ep+1); */
 
431
      }
 
432
    case '*':  /* 0 or more repetitions */
 
433
      s = max_expand(ms, s, p, ep);
 
434
      break;
 
435
    case '+':  /* 1 or more repetitions */
 
436
      s = (m ? max_expand(ms, s+1, p, ep) : NULL);
 
437
      break;
 
438
    case '-':  /* 0 or more repetitions (minimum) */
 
439
      s = min_expand(ms, s, p, ep);
 
440
      break;
 
441
    default:
 
442
      if (m) { s++; p=ep; goto init; }  /* else s = match(ms, s+1, ep); */
 
443
      s = NULL;
 
444
      break;
 
445
    }
 
446
    break;
 
447
    }
 
448
  }
 
449
  ms->depth--;
 
450
  return s;
 
451
}
 
452
 
 
453
static const char *lmemfind(const char *s1, size_t l1,
 
454
                            const char *s2, size_t l2)
 
455
{
 
456
  if (l2 == 0) {
 
457
    return s1;  /* empty strings are everywhere */
 
458
  } else if (l2 > l1) {
 
459
    return NULL;  /* avoids a negative `l1' */
 
460
  } else {
 
461
    const char *init;  /* to search for a `*s2' inside `s1' */
 
462
    l2--;  /* 1st char will be checked by `memchr' */
 
463
    l1 = l1-l2;  /* `s2' cannot be found after that */
 
464
    while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {
 
465
      init++;   /* 1st char is already checked */
 
466
      if (memcmp(init, s2+1, l2) == 0) {
 
467
        return init-1;
 
468
      } else {  /* correct `l1' and `s1' to try again */
 
469
        l1 -= (size_t)(init-s1);
 
470
        s1 = init;
 
471
      }
 
472
    }
 
473
    return NULL;  /* not found */
 
474
  }
 
475
}
 
476
 
 
477
static void push_onecapture(MatchState *ms, int i, const char *s, const char *e)
 
478
{
 
479
  if (i >= ms->level) {
 
480
    if (i == 0)  /* ms->level == 0, too */
 
481
      lua_pushlstring(ms->L, s, (size_t)(e - s));  /* add whole match */
 
482
    else
 
483
      lj_err_caller(ms->L, LJ_ERR_STRCAPI);
 
484
  } else {
 
485
    ptrdiff_t l = ms->capture[i].len;
 
486
    if (l == CAP_UNFINISHED) lj_err_caller(ms->L, LJ_ERR_STRCAPU);
 
487
    if (l == CAP_POSITION)
 
488
      lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1);
 
489
    else
 
490
      lua_pushlstring(ms->L, ms->capture[i].init, (size_t)l);
 
491
  }
 
492
}
 
493
 
 
494
static int push_captures(MatchState *ms, const char *s, const char *e)
 
495
{
 
496
  int i;
 
497
  int nlevels = (ms->level == 0 && s) ? 1 : ms->level;
 
498
  luaL_checkstack(ms->L, nlevels, "too many captures");
 
499
  for (i = 0; i < nlevels; i++)
 
500
    push_onecapture(ms, i, s, e);
 
501
  return nlevels;  /* number of strings pushed */
 
502
}
 
503
 
 
504
static ptrdiff_t posrelat(ptrdiff_t pos, size_t len)
 
505
{
 
506
  /* relative string position: negative means back from end */
 
507
  if (pos < 0) pos += (ptrdiff_t)len + 1;
 
508
  return (pos >= 0) ? pos : 0;
 
509
}
 
510
 
 
511
static int str_find_aux(lua_State *L, int find)
 
512
{
 
513
  size_t l1, l2;
 
514
  const char *s = luaL_checklstring(L, 1, &l1);
 
515
  const char *p = luaL_checklstring(L, 2, &l2);
 
516
  ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;
 
517
  if (init < 0) {
 
518
    init = 0;
 
519
  } else if ((size_t)(init) > l1) {
 
520
#if LJ_52
 
521
    setnilV(L->top-1);
 
522
    return 1;
 
523
#else
 
524
    init = (ptrdiff_t)l1;
 
525
#endif
 
526
  }
 
527
  if (find && (lua_toboolean(L, 4) ||  /* explicit request? */
 
528
      strpbrk(p, SPECIALS) == NULL)) {  /* or no special characters? */
 
529
    /* do a plain search */
 
530
    const char *s2 = lmemfind(s+init, l1-(size_t)init, p, l2);
 
531
    if (s2) {
 
532
      lua_pushinteger(L, s2-s+1);
 
533
      lua_pushinteger(L, s2-s+(ptrdiff_t)l2);
 
534
      return 2;
 
535
    }
 
536
  } else {
 
537
    MatchState ms;
 
538
    int anchor = (*p == '^') ? (p++, 1) : 0;
 
539
    const char *s1=s+init;
 
540
    ms.L = L;
 
541
    ms.src_init = s;
 
542
    ms.src_end = s+l1;
 
543
    do {
 
544
      const char *res;
 
545
      ms.level = ms.depth = 0;
 
546
      if ((res=match(&ms, s1, p)) != NULL) {
 
547
        if (find) {
 
548
          lua_pushinteger(L, s1-s+1);  /* start */
 
549
          lua_pushinteger(L, res-s);   /* end */
 
550
          return push_captures(&ms, NULL, 0) + 2;
 
551
        } else {
 
552
          return push_captures(&ms, s1, res);
 
553
        }
 
554
      }
 
555
    } while (s1++ < ms.src_end && !anchor);
 
556
  }
 
557
  lua_pushnil(L);  /* not found */
 
558
  return 1;
 
559
}
 
560
 
 
561
LJLIB_CF(string_find)
 
562
{
 
563
  return str_find_aux(L, 1);
 
564
}
 
565
 
 
566
LJLIB_CF(string_match)
 
567
{
 
568
  return str_find_aux(L, 0);
 
569
}
 
570
 
 
571
LJLIB_NOREG LJLIB_CF(string_gmatch_aux)
 
572
{
 
573
  const char *p = strVdata(lj_lib_upvalue(L, 2));
 
574
  GCstr *str = strV(lj_lib_upvalue(L, 1));
 
575
  const char *s = strdata(str);
 
576
  TValue *tvpos = lj_lib_upvalue(L, 3);
 
577
  const char *src = s + tvpos->u32.lo;
 
578
  MatchState ms;
 
579
  ms.L = L;
 
580
  ms.src_init = s;
 
581
  ms.src_end = s + str->len;
 
582
  for (; src <= ms.src_end; src++) {
 
583
    const char *e;
 
584
    ms.level = ms.depth = 0;
 
585
    if ((e = match(&ms, src, p)) != NULL) {
 
586
      int32_t pos = (int32_t)(e - s);
 
587
      if (e == src) pos++;  /* Ensure progress for empty match. */
 
588
      tvpos->u32.lo = (uint32_t)pos;
 
589
      return push_captures(&ms, src, e);
 
590
    }
 
591
  }
 
592
  return 0;  /* not found */
 
593
}
 
594
 
 
595
LJLIB_CF(string_gmatch)
 
596
{
 
597
  lj_lib_checkstr(L, 1);
 
598
  lj_lib_checkstr(L, 2);
 
599
  L->top = L->base+3;
 
600
  (L->top-1)->u64 = 0;
 
601
  lj_lib_pushcc(L, lj_cf_string_gmatch_aux, FF_string_gmatch_aux, 3);
 
602
  return 1;
 
603
}
 
604
 
 
605
static void add_s(MatchState *ms, luaL_Buffer *b, const char *s, const char *e)
 
606
{
 
607
  size_t l, i;
 
608
  const char *news = lua_tolstring(ms->L, 3, &l);
 
609
  for (i = 0; i < l; i++) {
 
610
    if (news[i] != L_ESC) {
 
611
      luaL_addchar(b, news[i]);
 
612
    } else {
 
613
      i++;  /* skip ESC */
 
614
      if (!lj_char_isdigit(uchar(news[i]))) {
 
615
        luaL_addchar(b, news[i]);
 
616
      } else if (news[i] == '0') {
 
617
        luaL_addlstring(b, s, (size_t)(e - s));
 
618
      } else {
 
619
        push_onecapture(ms, news[i] - '1', s, e);
 
620
        luaL_addvalue(b);  /* add capture to accumulated result */
 
621
      }
 
622
    }
 
623
  }
 
624
}
 
625
 
 
626
static void add_value(MatchState *ms, luaL_Buffer *b,
 
627
                      const char *s, const char *e)
 
628
{
 
629
  lua_State *L = ms->L;
 
630
  switch (lua_type(L, 3)) {
 
631
    case LUA_TNUMBER:
 
632
    case LUA_TSTRING: {
 
633
      add_s(ms, b, s, e);
 
634
      return;
 
635
    }
 
636
    case LUA_TFUNCTION: {
 
637
      int n;
 
638
      lua_pushvalue(L, 3);
 
639
      n = push_captures(ms, s, e);
 
640
      lua_call(L, n, 1);
 
641
      break;
 
642
    }
 
643
    case LUA_TTABLE: {
 
644
      push_onecapture(ms, 0, s, e);
 
645
      lua_gettable(L, 3);
 
646
      break;
 
647
    }
 
648
  }
 
649
  if (!lua_toboolean(L, -1)) {  /* nil or false? */
 
650
    lua_pop(L, 1);
 
651
    lua_pushlstring(L, s, (size_t)(e - s));  /* keep original text */
 
652
  } else if (!lua_isstring(L, -1)) {
 
653
    lj_err_callerv(L, LJ_ERR_STRGSRV, luaL_typename(L, -1));
 
654
  }
 
655
  luaL_addvalue(b);  /* add result to accumulator */
 
656
}
 
657
 
 
658
LJLIB_CF(string_gsub)
 
659
{
 
660
  size_t srcl;
 
661
  const char *src = luaL_checklstring(L, 1, &srcl);
 
662
  const char *p = luaL_checkstring(L, 2);
 
663
  int  tr = lua_type(L, 3);
 
664
  int max_s = luaL_optint(L, 4, (int)(srcl+1));
 
665
  int anchor = (*p == '^') ? (p++, 1) : 0;
 
666
  int n = 0;
 
667
  MatchState ms;
 
668
  luaL_Buffer b;
 
669
  if (!(tr == LUA_TNUMBER || tr == LUA_TSTRING ||
 
670
        tr == LUA_TFUNCTION || tr == LUA_TTABLE))
 
671
    lj_err_arg(L, 3, LJ_ERR_NOSFT);
 
672
  luaL_buffinit(L, &b);
 
673
  ms.L = L;
 
674
  ms.src_init = src;
 
675
  ms.src_end = src+srcl;
 
676
  while (n < max_s) {
 
677
    const char *e;
 
678
    ms.level = ms.depth = 0;
 
679
    e = match(&ms, src, p);
 
680
    if (e) {
 
681
      n++;
 
682
      add_value(&ms, &b, src, e);
 
683
    }
 
684
    if (e && e>src) /* non empty match? */
 
685
      src = e;  /* skip it */
 
686
    else if (src < ms.src_end)
 
687
      luaL_addchar(&b, *src++);
 
688
    else
 
689
      break;
 
690
    if (anchor)
 
691
      break;
 
692
  }
 
693
  luaL_addlstring(&b, src, (size_t)(ms.src_end-src));
 
694
  luaL_pushresult(&b);
 
695
  lua_pushinteger(L, n);  /* number of substitutions */
 
696
  return 2;
 
697
}
 
698
 
 
699
/* ------------------------------------------------------------------------ */
 
700
 
 
701
/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
 
702
#define MAX_FMTITEM     512
 
703
/* valid flags in a format specification */
 
704
#define FMT_FLAGS       "-+ #0"
 
705
/*
 
706
** maximum size of each format specification (such as '%-099.99d')
 
707
** (+10 accounts for %99.99x plus margin of error)
 
708
*/
 
709
#define MAX_FMTSPEC     (sizeof(FMT_FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
 
710
 
 
711
static void addquoted(lua_State *L, luaL_Buffer *b, int arg)
 
712
{
 
713
  GCstr *str = lj_lib_checkstr(L, arg);
 
714
  int32_t len = (int32_t)str->len;
 
715
  const char *s = strdata(str);
 
716
  luaL_addchar(b, '"');
 
717
  while (len--) {
 
718
    uint32_t c = uchar(*s);
 
719
    if (c == '"' || c == '\\' || c == '\n') {
 
720
      luaL_addchar(b, '\\');
 
721
    } else if (lj_char_iscntrl(c)) {  /* This can only be 0-31 or 127. */
 
722
      uint32_t d;
 
723
      luaL_addchar(b, '\\');
 
724
      if (c >= 100 || lj_char_isdigit(uchar(s[1]))) {
 
725
        luaL_addchar(b, '0'+(c >= 100)); if (c >= 100) c -= 100;
 
726
        goto tens;
 
727
      } else if (c >= 10) {
 
728
      tens:
 
729
        d = (c * 205) >> 11; c -= d * 10; luaL_addchar(b, '0'+d);
 
730
      }
 
731
      c += '0';
 
732
    }
 
733
    luaL_addchar(b, c);
 
734
    s++;
 
735
  }
 
736
  luaL_addchar(b, '"');
 
737
}
 
738
 
 
739
static const char *scanformat(lua_State *L, const char *strfrmt, char *form)
 
740
{
 
741
  const char *p = strfrmt;
 
742
  while (*p != '\0' && strchr(FMT_FLAGS, *p) != NULL) p++;  /* skip flags */
 
743
  if ((size_t)(p - strfrmt) >= sizeof(FMT_FLAGS))
 
744
    lj_err_caller(L, LJ_ERR_STRFMTR);
 
745
  if (lj_char_isdigit(uchar(*p))) p++;  /* skip width */
 
746
  if (lj_char_isdigit(uchar(*p))) p++;  /* (2 digits at most) */
 
747
  if (*p == '.') {
 
748
    p++;
 
749
    if (lj_char_isdigit(uchar(*p))) p++;  /* skip precision */
 
750
    if (lj_char_isdigit(uchar(*p))) p++;  /* (2 digits at most) */
 
751
  }
 
752
  if (lj_char_isdigit(uchar(*p)))
 
753
    lj_err_caller(L, LJ_ERR_STRFMTW);
 
754
  *(form++) = '%';
 
755
  strncpy(form, strfrmt, (size_t)(p - strfrmt + 1));
 
756
  form += p - strfrmt + 1;
 
757
  *form = '\0';
 
758
  return p;
 
759
}
 
760
 
 
761
static void addintlen(char *form)
 
762
{
 
763
  size_t l = strlen(form);
 
764
  char spec = form[l - 1];
 
765
  strcpy(form + l - 1, LUA_INTFRMLEN);
 
766
  form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;
 
767
  form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0';
 
768
}
 
769
 
 
770
static unsigned LUA_INTFRM_T num2intfrm(lua_State *L, int arg)
 
771
{
 
772
  if (sizeof(LUA_INTFRM_T) == 4) {
 
773
    return (LUA_INTFRM_T)lj_lib_checkbit(L, arg);
 
774
  } else {
 
775
    cTValue *o;
 
776
    lj_lib_checknumber(L, arg);
 
777
    o = L->base+arg-1;
 
778
    if (tvisint(o))
 
779
      return (LUA_INTFRM_T)intV(o);
 
780
    else
 
781
      return (LUA_INTFRM_T)numV(o);
 
782
  }
 
783
}
 
784
 
 
785
static unsigned LUA_INTFRM_T num2uintfrm(lua_State *L, int arg)
 
786
{
 
787
  if (sizeof(LUA_INTFRM_T) == 4) {
 
788
    return (unsigned LUA_INTFRM_T)lj_lib_checkbit(L, arg);
 
789
  } else {
 
790
    cTValue *o;
 
791
    lj_lib_checknumber(L, arg);
 
792
    o = L->base+arg-1;
 
793
    if (tvisint(o))
 
794
      return (unsigned LUA_INTFRM_T)intV(o);
 
795
    else if ((int32_t)o->u32.hi < 0)
 
796
      return (unsigned LUA_INTFRM_T)(LUA_INTFRM_T)numV(o);
 
797
    else
 
798
      return (unsigned LUA_INTFRM_T)numV(o);
 
799
  }
 
800
}
 
801
 
 
802
static GCstr *meta_tostring(lua_State *L, int arg)
 
803
{
 
804
  TValue *o = L->base+arg-1;
 
805
  cTValue *mo;
 
806
  lua_assert(o < L->top);  /* Caller already checks for existence. */
 
807
  if (LJ_LIKELY(tvisstr(o)))
 
808
    return strV(o);
 
809
  if (!tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) {
 
810
    copyTV(L, L->top++, mo);
 
811
    copyTV(L, L->top++, o);
 
812
    lua_call(L, 1, 1);
 
813
    L->top--;
 
814
    if (tvisstr(L->top))
 
815
      return strV(L->top);
 
816
    o = L->base+arg-1;
 
817
    copyTV(L, o, L->top);
 
818
  }
 
819
  if (tvisnumber(o)) {
 
820
    return lj_str_fromnumber(L, o);
 
821
  } else if (tvisnil(o)) {
 
822
    return lj_str_newlit(L, "nil");
 
823
  } else if (tvisfalse(o)) {
 
824
    return lj_str_newlit(L, "false");
 
825
  } else if (tvistrue(o)) {
 
826
    return lj_str_newlit(L, "true");
 
827
  } else {
 
828
    if (tvisfunc(o) && isffunc(funcV(o)))
 
829
      lj_str_pushf(L, "function: builtin#%d", funcV(o)->c.ffid);
 
830
    else
 
831
      lj_str_pushf(L, "%s: %p", lj_typename(o), lua_topointer(L, arg));
 
832
    L->top--;
 
833
    return strV(L->top);
 
834
  }
 
835
}
 
836
 
 
837
LJLIB_CF(string_format)
 
838
{
 
839
  int arg = 1, top = (int)(L->top - L->base);
 
840
  GCstr *fmt = lj_lib_checkstr(L, arg);
 
841
  const char *strfrmt = strdata(fmt);
 
842
  const char *strfrmt_end = strfrmt + fmt->len;
 
843
  luaL_Buffer b;
 
844
  luaL_buffinit(L, &b);
 
845
  while (strfrmt < strfrmt_end) {
 
846
    if (*strfrmt != L_ESC) {
 
847
      luaL_addchar(&b, *strfrmt++);
 
848
    } else if (*++strfrmt == L_ESC) {
 
849
      luaL_addchar(&b, *strfrmt++);  /* %% */
 
850
    } else { /* format item */
 
851
      char form[MAX_FMTSPEC];  /* to store the format (`%...') */
 
852
      char buff[MAX_FMTITEM];  /* to store the formatted item */
 
853
      if (++arg > top)
 
854
        luaL_argerror(L, arg, lj_obj_typename[0]);
 
855
      strfrmt = scanformat(L, strfrmt, form);
 
856
      switch (*strfrmt++) {
 
857
      case 'c':
 
858
        sprintf(buff, form, lj_lib_checkint(L, arg));
 
859
        break;
 
860
      case 'd':  case 'i':
 
861
        addintlen(form);
 
862
        sprintf(buff, form, num2intfrm(L, arg));
 
863
        break;
 
864
      case 'o':  case 'u':  case 'x':  case 'X':
 
865
        addintlen(form);
 
866
        sprintf(buff, form, num2uintfrm(L, arg));
 
867
        break;
 
868
      case 'e':  case 'E': case 'f': case 'g': case 'G': case 'a': case 'A': {
 
869
        TValue tv;
 
870
        tv.n = lj_lib_checknum(L, arg);
 
871
        if (LJ_UNLIKELY((tv.u32.hi << 1) >= 0xffe00000)) {
 
872
          /* Canonicalize output of non-finite values. */
 
873
          char *p, nbuf[LJ_STR_NUMBUF];
 
874
          size_t len = lj_str_bufnum(nbuf, &tv);
 
875
          if (strfrmt[-1] < 'a') {
 
876
            nbuf[len-3] = nbuf[len-3] - 0x20;
 
877
            nbuf[len-2] = nbuf[len-2] - 0x20;
 
878
            nbuf[len-1] = nbuf[len-1] - 0x20;
 
879
          }
 
880
          nbuf[len] = '\0';
 
881
          for (p = form; *p < 'A' && *p != '.'; p++) ;
 
882
          *p++ = 's'; *p = '\0';
 
883
          sprintf(buff, form, nbuf);
 
884
          break;
 
885
        }
 
886
        sprintf(buff, form, (double)tv.n);
 
887
        break;
 
888
        }
 
889
      case 'q':
 
890
        addquoted(L, &b, arg);
 
891
        continue;
 
892
      case 'p':
 
893
        lj_str_pushf(L, "%p", lua_topointer(L, arg));
 
894
        luaL_addvalue(&b);
 
895
        continue;
 
896
      case 's': {
 
897
        GCstr *str = meta_tostring(L, arg);
 
898
        if (!strchr(form, '.') && str->len >= 100) {
 
899
          /* no precision and string is too long to be formatted;
 
900
             keep original string */
 
901
          setstrV(L, L->top++, str);
 
902
          luaL_addvalue(&b);
 
903
          continue;
 
904
        }
 
905
        sprintf(buff, form, strdata(str));
 
906
        break;
 
907
        }
 
908
      default:
 
909
        lj_err_callerv(L, LJ_ERR_STRFMTO, *(strfrmt -1));
 
910
        break;
 
911
      }
 
912
      luaL_addlstring(&b, buff, strlen(buff));
 
913
    }
 
914
  }
 
915
  luaL_pushresult(&b);
 
916
  return 1;
 
917
}
 
918
 
 
919
/* ------------------------------------------------------------------------ */
 
920
 
 
921
#include "lj_libdef.h"
 
922
 
 
923
LUALIB_API int luaopen_string(lua_State *L)
 
924
{
 
925
  GCtab *mt;
 
926
  global_State *g;
 
927
  LJ_LIB_REG(L, LUA_STRLIBNAME, string);
 
928
#if defined(LUA_COMPAT_GFIND) && !LJ_52
 
929
  lua_getfield(L, -1, "gmatch");
 
930
  lua_setfield(L, -2, "gfind");
 
931
#endif
 
932
  mt = lj_tab_new(L, 0, 1);
 
933
  /* NOBARRIER: basemt is a GC root. */
 
934
  g = G(L);
 
935
  setgcref(basemt_it(g, LJ_TSTR), obj2gco(mt));
 
936
  settabV(L, lj_tab_setstr(L, mt, mmname_str(g, MM_index)), tabV(L->top-1));
 
937
  mt->nomm = (uint8_t)(~(1u<<MM_index));
 
938
  return 1;
 
939
}
 
940