Tamar 0.7.5 → 0.7.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data/.gitmodules +3 -0
  2. data/HISTORY +22 -5
  3. data/Tamar.gemspec +114 -1
  4. data/VERSION +1 -1
  5. data/src/lua/CMakeLists.txt +176 -0
  6. data/src/lua/COPYRIGHT +34 -0
  7. data/src/lua/FindReadline.cmake +25 -0
  8. data/src/lua/HISTORY +183 -0
  9. data/src/lua/INSTALL +99 -0
  10. data/src/lua/Makefile +128 -0
  11. data/src/lua/README +46 -0
  12. data/src/lua/dist.cmake +450 -0
  13. data/src/lua/dist.info +10 -0
  14. data/src/lua/doc/amazon.gif +0 -0
  15. data/src/lua/doc/contents.html +499 -0
  16. data/src/lua/doc/cover.png +0 -0
  17. data/src/lua/doc/logo.gif +0 -0
  18. data/src/lua/doc/lua.1 +163 -0
  19. data/src/lua/doc/lua.css +41 -0
  20. data/src/lua/doc/lua.html +172 -0
  21. data/src/lua/doc/luac.1 +136 -0
  22. data/src/lua/doc/luac.html +145 -0
  23. data/src/lua/doc/manual.css +13 -0
  24. data/src/lua/doc/manual.html +8801 -0
  25. data/src/lua/doc/readme.html +40 -0
  26. data/src/lua/etc/Makefile +44 -0
  27. data/src/lua/etc/README +37 -0
  28. data/src/lua/etc/all.c +38 -0
  29. data/src/lua/etc/lua.hpp +9 -0
  30. data/src/lua/etc/lua.ico +0 -0
  31. data/src/lua/etc/lua.pc +31 -0
  32. data/src/lua/etc/luavs.bat +28 -0
  33. data/src/lua/etc/min.c +39 -0
  34. data/src/lua/etc/noparser.c +50 -0
  35. data/src/lua/etc/strict.lua +41 -0
  36. data/src/lua/src/Makefile +182 -0
  37. data/src/lua/src/lapi.c +1087 -0
  38. data/src/lua/src/lapi.h +16 -0
  39. data/src/lua/src/lauxlib.c +652 -0
  40. data/src/lua/src/lauxlib.h +174 -0
  41. data/src/lua/src/lbaselib.c +653 -0
  42. data/src/lua/src/lcode.c +831 -0
  43. data/src/lua/src/lcode.h +76 -0
  44. data/src/lua/src/ldblib.c +398 -0
  45. data/src/lua/src/ldebug.c +638 -0
  46. data/src/lua/src/ldebug.h +33 -0
  47. data/src/lua/src/ldo.c +518 -0
  48. data/src/lua/src/ldo.h +57 -0
  49. data/src/lua/src/ldump.c +164 -0
  50. data/src/lua/src/lfunc.c +174 -0
  51. data/src/lua/src/lfunc.h +34 -0
  52. data/src/lua/src/lgc.c +711 -0
  53. data/src/lua/src/lgc.h +110 -0
  54. data/src/lua/src/linit.c +38 -0
  55. data/src/lua/src/liolib.c +556 -0
  56. data/src/lua/src/llex.c +463 -0
  57. data/src/lua/src/llex.h +81 -0
  58. data/src/lua/src/llimits.h +128 -0
  59. data/src/lua/src/lmathlib.c +263 -0
  60. data/src/lua/src/lmem.c +86 -0
  61. data/src/lua/src/lmem.h +49 -0
  62. data/src/lua/src/loadlib.c +666 -0
  63. data/src/lua/src/loadlib_rel.c +719 -0
  64. data/src/lua/src/lobject.c +214 -0
  65. data/src/lua/src/lobject.h +381 -0
  66. data/src/lua/src/lopcodes.c +102 -0
  67. data/src/lua/src/lopcodes.h +268 -0
  68. data/src/lua/src/loslib.c +243 -0
  69. data/src/lua/src/lparser.c +1339 -0
  70. data/src/lua/src/lparser.h +82 -0
  71. data/src/lua/src/lstate.c +214 -0
  72. data/src/lua/src/lstate.h +169 -0
  73. data/src/lua/src/lstring.c +111 -0
  74. data/src/lua/src/lstring.h +31 -0
  75. data/src/lua/src/lstrlib.c +871 -0
  76. data/src/lua/src/ltable.c +588 -0
  77. data/src/lua/src/ltable.h +40 -0
  78. data/src/lua/src/ltablib.c +287 -0
  79. data/src/lua/src/ltm.c +75 -0
  80. data/src/lua/src/ltm.h +54 -0
  81. data/src/lua/src/lua.c +392 -0
  82. data/src/lua/src/lua.def +131 -0
  83. data/src/lua/src/lua.h +388 -0
  84. data/src/lua/src/lua.rc +28 -0
  85. data/src/lua/src/lua_dll.rc +26 -0
  86. data/src/lua/src/luac.c +200 -0
  87. data/src/lua/src/luac.rc +1 -0
  88. data/src/lua/src/luaconf.h.in +724 -0
  89. data/src/lua/src/luaconf.h.orig +763 -0
  90. data/src/lua/src/lualib.h +53 -0
  91. data/src/lua/src/lundump.c +227 -0
  92. data/src/lua/src/lundump.h +36 -0
  93. data/src/lua/src/lvm.c +766 -0
  94. data/src/lua/src/lvm.h +36 -0
  95. data/src/lua/src/lzio.c +82 -0
  96. data/src/lua/src/lzio.h +67 -0
  97. data/src/lua/src/print.c +227 -0
  98. data/src/lua/test/README +26 -0
  99. data/src/lua/test/bisect.lua +27 -0
  100. data/src/lua/test/cf.lua +16 -0
  101. data/src/lua/test/echo.lua +5 -0
  102. data/src/lua/test/env.lua +7 -0
  103. data/src/lua/test/factorial.lua +32 -0
  104. data/src/lua/test/fib.lua +40 -0
  105. data/src/lua/test/fibfor.lua +13 -0
  106. data/src/lua/test/globals.lua +13 -0
  107. data/src/lua/test/hello.lua +3 -0
  108. data/src/lua/test/life.lua +111 -0
  109. data/src/lua/test/luac.lua +7 -0
  110. data/src/lua/test/printf.lua +7 -0
  111. data/src/lua/test/readonly.lua +12 -0
  112. data/src/lua/test/sieve.lua +29 -0
  113. data/src/lua/test/sort.lua +66 -0
  114. data/src/lua/test/table.lua +12 -0
  115. data/src/lua/test/trace-calls.lua +32 -0
  116. data/src/lua/test/trace-globals.lua +38 -0
  117. data/src/lua/test/xd.lua +14 -0
  118. metadata +115 -2
@@ -0,0 +1,871 @@
1
+ /*
2
+ ** $Id: lstrlib.c,v 1.132.1.5 2010/05/14 15:34:19 roberto Exp $
3
+ ** Standard library for string operations and pattern-matching
4
+ ** See Copyright Notice in lua.h
5
+ */
6
+
7
+
8
+ #include <ctype.h>
9
+ #include <stddef.h>
10
+ #include <stdio.h>
11
+ #include <stdlib.h>
12
+ #include <string.h>
13
+
14
+ #define lstrlib_c
15
+ #define LUA_LIB
16
+
17
+ #include "lua.h"
18
+
19
+ #include "lauxlib.h"
20
+ #include "lualib.h"
21
+
22
+
23
+ /* macro to `unsign' a character */
24
+ #define uchar(c) ((unsigned char)(c))
25
+
26
+
27
+
28
+ static int str_len (lua_State *L) {
29
+ size_t l;
30
+ luaL_checklstring(L, 1, &l);
31
+ lua_pushinteger(L, l);
32
+ return 1;
33
+ }
34
+
35
+
36
+ static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) {
37
+ /* relative string position: negative means back from end */
38
+ if (pos < 0) pos += (ptrdiff_t)len + 1;
39
+ return (pos >= 0) ? pos : 0;
40
+ }
41
+
42
+
43
+ static int str_sub (lua_State *L) {
44
+ size_t l;
45
+ const char *s = luaL_checklstring(L, 1, &l);
46
+ ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l);
47
+ ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l);
48
+ if (start < 1) start = 1;
49
+ if (end > (ptrdiff_t)l) end = (ptrdiff_t)l;
50
+ if (start <= end)
51
+ lua_pushlstring(L, s+start-1, end-start+1);
52
+ else lua_pushliteral(L, "");
53
+ return 1;
54
+ }
55
+
56
+
57
+ static int str_reverse (lua_State *L) {
58
+ size_t l;
59
+ luaL_Buffer b;
60
+ const char *s = luaL_checklstring(L, 1, &l);
61
+ luaL_buffinit(L, &b);
62
+ while (l--) luaL_addchar(&b, s[l]);
63
+ luaL_pushresult(&b);
64
+ return 1;
65
+ }
66
+
67
+
68
+ static int str_lower (lua_State *L) {
69
+ size_t l;
70
+ size_t i;
71
+ luaL_Buffer b;
72
+ const char *s = luaL_checklstring(L, 1, &l);
73
+ luaL_buffinit(L, &b);
74
+ for (i=0; i<l; i++)
75
+ luaL_addchar(&b, tolower(uchar(s[i])));
76
+ luaL_pushresult(&b);
77
+ return 1;
78
+ }
79
+
80
+
81
+ static int str_upper (lua_State *L) {
82
+ size_t l;
83
+ size_t i;
84
+ luaL_Buffer b;
85
+ const char *s = luaL_checklstring(L, 1, &l);
86
+ luaL_buffinit(L, &b);
87
+ for (i=0; i<l; i++)
88
+ luaL_addchar(&b, toupper(uchar(s[i])));
89
+ luaL_pushresult(&b);
90
+ return 1;
91
+ }
92
+
93
+ static int str_rep (lua_State *L) {
94
+ size_t l;
95
+ luaL_Buffer b;
96
+ const char *s = luaL_checklstring(L, 1, &l);
97
+ int n = luaL_checkint(L, 2);
98
+ luaL_buffinit(L, &b);
99
+ while (n-- > 0)
100
+ luaL_addlstring(&b, s, l);
101
+ luaL_pushresult(&b);
102
+ return 1;
103
+ }
104
+
105
+
106
+ static int str_byte (lua_State *L) {
107
+ size_t l;
108
+ const char *s = luaL_checklstring(L, 1, &l);
109
+ ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l);
110
+ ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l);
111
+ int n, i;
112
+ if (posi <= 0) posi = 1;
113
+ if ((size_t)pose > l) pose = l;
114
+ if (posi > pose) return 0; /* empty interval; return no values */
115
+ n = (int)(pose - posi + 1);
116
+ if (posi + n <= pose) /* overflow? */
117
+ luaL_error(L, "string slice too long");
118
+ luaL_checkstack(L, n, "string slice too long");
119
+ for (i=0; i<n; i++)
120
+ lua_pushinteger(L, uchar(s[posi+i-1]));
121
+ return n;
122
+ }
123
+
124
+
125
+ static int str_char (lua_State *L) {
126
+ int n = lua_gettop(L); /* number of arguments */
127
+ int i;
128
+ luaL_Buffer b;
129
+ luaL_buffinit(L, &b);
130
+ for (i=1; i<=n; i++) {
131
+ int c = luaL_checkint(L, i);
132
+ luaL_argcheck(L, uchar(c) == c, i, "invalid value");
133
+ luaL_addchar(&b, uchar(c));
134
+ }
135
+ luaL_pushresult(&b);
136
+ return 1;
137
+ }
138
+
139
+
140
+ static int writer (lua_State *L, const void* b, size_t size, void* B) {
141
+ (void)L;
142
+ luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);
143
+ return 0;
144
+ }
145
+
146
+
147
+ static int str_dump (lua_State *L) {
148
+ luaL_Buffer b;
149
+ luaL_checktype(L, 1, LUA_TFUNCTION);
150
+ lua_settop(L, 1);
151
+ luaL_buffinit(L,&b);
152
+ if (lua_dump(L, writer, &b) != 0)
153
+ luaL_error(L, "unable to dump given function");
154
+ luaL_pushresult(&b);
155
+ return 1;
156
+ }
157
+
158
+
159
+
160
+ /*
161
+ ** {======================================================
162
+ ** PATTERN MATCHING
163
+ ** =======================================================
164
+ */
165
+
166
+
167
+ #define CAP_UNFINISHED (-1)
168
+ #define CAP_POSITION (-2)
169
+
170
+ typedef struct MatchState {
171
+ const char *src_init; /* init of source string */
172
+ const char *src_end; /* end (`\0') of source string */
173
+ lua_State *L;
174
+ int level; /* total number of captures (finished or unfinished) */
175
+ struct {
176
+ const char *init;
177
+ ptrdiff_t len;
178
+ } capture[LUA_MAXCAPTURES];
179
+ } MatchState;
180
+
181
+
182
+ #define L_ESC '%'
183
+ #define SPECIALS "^$*+?.([%-"
184
+
185
+
186
+ static int check_capture (MatchState *ms, int l) {
187
+ l -= '1';
188
+ if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED)
189
+ return luaL_error(ms->L, "invalid capture index");
190
+ return l;
191
+ }
192
+
193
+
194
+ static int capture_to_close (MatchState *ms) {
195
+ int level = ms->level;
196
+ for (level--; level>=0; level--)
197
+ if (ms->capture[level].len == CAP_UNFINISHED) return level;
198
+ return luaL_error(ms->L, "invalid pattern capture");
199
+ }
200
+
201
+
202
+ static const char *classend (MatchState *ms, const char *p) {
203
+ switch (*p++) {
204
+ case L_ESC: {
205
+ if (*p == '\0')
206
+ luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")");
207
+ return p+1;
208
+ }
209
+ case '[': {
210
+ if (*p == '^') p++;
211
+ do { /* look for a `]' */
212
+ if (*p == '\0')
213
+ luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")");
214
+ if (*(p++) == L_ESC && *p != '\0')
215
+ p++; /* skip escapes (e.g. `%]') */
216
+ } while (*p != ']');
217
+ return p+1;
218
+ }
219
+ default: {
220
+ return p;
221
+ }
222
+ }
223
+ }
224
+
225
+
226
+ static int match_class (int c, int cl) {
227
+ int res;
228
+ switch (tolower(cl)) {
229
+ case 'a' : res = isalpha(c); break;
230
+ case 'c' : res = iscntrl(c); break;
231
+ case 'd' : res = isdigit(c); break;
232
+ case 'l' : res = islower(c); break;
233
+ case 'p' : res = ispunct(c); break;
234
+ case 's' : res = isspace(c); break;
235
+ case 'u' : res = isupper(c); break;
236
+ case 'w' : res = isalnum(c); break;
237
+ case 'x' : res = isxdigit(c); break;
238
+ case 'z' : res = (c == 0); break;
239
+ default: return (cl == c);
240
+ }
241
+ return (islower(cl) ? res : !res);
242
+ }
243
+
244
+
245
+ static int matchbracketclass (int c, const char *p, const char *ec) {
246
+ int sig = 1;
247
+ if (*(p+1) == '^') {
248
+ sig = 0;
249
+ p++; /* skip the `^' */
250
+ }
251
+ while (++p < ec) {
252
+ if (*p == L_ESC) {
253
+ p++;
254
+ if (match_class(c, uchar(*p)))
255
+ return sig;
256
+ }
257
+ else if ((*(p+1) == '-') && (p+2 < ec)) {
258
+ p+=2;
259
+ if (uchar(*(p-2)) <= c && c <= uchar(*p))
260
+ return sig;
261
+ }
262
+ else if (uchar(*p) == c) return sig;
263
+ }
264
+ return !sig;
265
+ }
266
+
267
+
268
+ static int singlematch (int c, const char *p, const char *ep) {
269
+ switch (*p) {
270
+ case '.': return 1; /* matches any char */
271
+ case L_ESC: return match_class(c, uchar(*(p+1)));
272
+ case '[': return matchbracketclass(c, p, ep-1);
273
+ default: return (uchar(*p) == c);
274
+ }
275
+ }
276
+
277
+
278
+ static const char *match (MatchState *ms, const char *s, const char *p);
279
+
280
+
281
+ static const char *matchbalance (MatchState *ms, const char *s,
282
+ const char *p) {
283
+ if (*p == 0 || *(p+1) == 0)
284
+ luaL_error(ms->L, "unbalanced pattern");
285
+ if (*s != *p) return NULL;
286
+ else {
287
+ int b = *p;
288
+ int e = *(p+1);
289
+ int cont = 1;
290
+ while (++s < ms->src_end) {
291
+ if (*s == e) {
292
+ if (--cont == 0) return s+1;
293
+ }
294
+ else if (*s == b) cont++;
295
+ }
296
+ }
297
+ return NULL; /* string ends out of balance */
298
+ }
299
+
300
+
301
+ static const char *max_expand (MatchState *ms, const char *s,
302
+ const char *p, const char *ep) {
303
+ ptrdiff_t i = 0; /* counts maximum expand for item */
304
+ while ((s+i)<ms->src_end && singlematch(uchar(*(s+i)), p, ep))
305
+ i++;
306
+ /* keeps trying to match with the maximum repetitions */
307
+ while (i>=0) {
308
+ const char *res = match(ms, (s+i), ep+1);
309
+ if (res) return res;
310
+ i--; /* else didn't match; reduce 1 repetition to try again */
311
+ }
312
+ return NULL;
313
+ }
314
+
315
+
316
+ static const char *min_expand (MatchState *ms, const char *s,
317
+ const char *p, const char *ep) {
318
+ for (;;) {
319
+ const char *res = match(ms, s, ep+1);
320
+ if (res != NULL)
321
+ return res;
322
+ else if (s<ms->src_end && singlematch(uchar(*s), p, ep))
323
+ s++; /* try with one more repetition */
324
+ else return NULL;
325
+ }
326
+ }
327
+
328
+
329
+ static const char *start_capture (MatchState *ms, const char *s,
330
+ const char *p, int what) {
331
+ const char *res;
332
+ int level = ms->level;
333
+ if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures");
334
+ ms->capture[level].init = s;
335
+ ms->capture[level].len = what;
336
+ ms->level = level+1;
337
+ if ((res=match(ms, s, p)) == NULL) /* match failed? */
338
+ ms->level--; /* undo capture */
339
+ return res;
340
+ }
341
+
342
+
343
+ static const char *end_capture (MatchState *ms, const char *s,
344
+ const char *p) {
345
+ int l = capture_to_close(ms);
346
+ const char *res;
347
+ ms->capture[l].len = s - ms->capture[l].init; /* close capture */
348
+ if ((res = match(ms, s, p)) == NULL) /* match failed? */
349
+ ms->capture[l].len = CAP_UNFINISHED; /* undo capture */
350
+ return res;
351
+ }
352
+
353
+
354
+ static const char *match_capture (MatchState *ms, const char *s, int l) {
355
+ size_t len;
356
+ l = check_capture(ms, l);
357
+ len = ms->capture[l].len;
358
+ if ((size_t)(ms->src_end-s) >= len &&
359
+ memcmp(ms->capture[l].init, s, len) == 0)
360
+ return s+len;
361
+ else return NULL;
362
+ }
363
+
364
+
365
+ static const char *match (MatchState *ms, const char *s, const char *p) {
366
+ init: /* using goto's to optimize tail recursion */
367
+ switch (*p) {
368
+ case '(': { /* start capture */
369
+ if (*(p+1) == ')') /* position capture? */
370
+ return start_capture(ms, s, p+2, CAP_POSITION);
371
+ else
372
+ return start_capture(ms, s, p+1, CAP_UNFINISHED);
373
+ }
374
+ case ')': { /* end capture */
375
+ return end_capture(ms, s, p+1);
376
+ }
377
+ case L_ESC: {
378
+ switch (*(p+1)) {
379
+ case 'b': { /* balanced string? */
380
+ s = matchbalance(ms, s, p+2);
381
+ if (s == NULL) return NULL;
382
+ p+=4; goto init; /* else return match(ms, s, p+4); */
383
+ }
384
+ case 'f': { /* frontier? */
385
+ const char *ep; char previous;
386
+ p += 2;
387
+ if (*p != '[')
388
+ luaL_error(ms->L, "missing " LUA_QL("[") " after "
389
+ LUA_QL("%%f") " in pattern");
390
+ ep = classend(ms, p); /* points to what is next */
391
+ previous = (s == ms->src_init) ? '\0' : *(s-1);
392
+ if (matchbracketclass(uchar(previous), p, ep-1) ||
393
+ !matchbracketclass(uchar(*s), p, ep-1)) return NULL;
394
+ p=ep; goto init; /* else return match(ms, s, ep); */
395
+ }
396
+ default: {
397
+ if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */
398
+ s = match_capture(ms, s, uchar(*(p+1)));
399
+ if (s == NULL) return NULL;
400
+ p+=2; goto init; /* else return match(ms, s, p+2) */
401
+ }
402
+ goto dflt; /* case default */
403
+ }
404
+ }
405
+ }
406
+ case '\0': { /* end of pattern */
407
+ return s; /* match succeeded */
408
+ }
409
+ case '$': {
410
+ if (*(p+1) == '\0') /* is the `$' the last char in pattern? */
411
+ return (s == ms->src_end) ? s : NULL; /* check end of string */
412
+ else goto dflt;
413
+ }
414
+ default: dflt: { /* it is a pattern item */
415
+ const char *ep = classend(ms, p); /* points to what is next */
416
+ int m = s<ms->src_end && singlematch(uchar(*s), p, ep);
417
+ switch (*ep) {
418
+ case '?': { /* optional */
419
+ const char *res;
420
+ if (m && ((res=match(ms, s+1, ep+1)) != NULL))
421
+ return res;
422
+ p=ep+1; goto init; /* else return match(ms, s, ep+1); */
423
+ }
424
+ case '*': { /* 0 or more repetitions */
425
+ return max_expand(ms, s, p, ep);
426
+ }
427
+ case '+': { /* 1 or more repetitions */
428
+ return (m ? max_expand(ms, s+1, p, ep) : NULL);
429
+ }
430
+ case '-': { /* 0 or more repetitions (minimum) */
431
+ return min_expand(ms, s, p, ep);
432
+ }
433
+ default: {
434
+ if (!m) return NULL;
435
+ s++; p=ep; goto init; /* else return match(ms, s+1, ep); */
436
+ }
437
+ }
438
+ }
439
+ }
440
+ }
441
+
442
+
443
+
444
+ static const char *lmemfind (const char *s1, size_t l1,
445
+ const char *s2, size_t l2) {
446
+ if (l2 == 0) return s1; /* empty strings are everywhere */
447
+ else if (l2 > l1) return NULL; /* avoids a negative `l1' */
448
+ else {
449
+ const char *init; /* to search for a `*s2' inside `s1' */
450
+ l2--; /* 1st char will be checked by `memchr' */
451
+ l1 = l1-l2; /* `s2' cannot be found after that */
452
+ while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {
453
+ init++; /* 1st char is already checked */
454
+ if (memcmp(init, s2+1, l2) == 0)
455
+ return init-1;
456
+ else { /* correct `l1' and `s1' to try again */
457
+ l1 -= init-s1;
458
+ s1 = init;
459
+ }
460
+ }
461
+ return NULL; /* not found */
462
+ }
463
+ }
464
+
465
+
466
+ static void push_onecapture (MatchState *ms, int i, const char *s,
467
+ const char *e) {
468
+ if (i >= ms->level) {
469
+ if (i == 0) /* ms->level == 0, too */
470
+ lua_pushlstring(ms->L, s, e - s); /* add whole match */
471
+ else
472
+ luaL_error(ms->L, "invalid capture index");
473
+ }
474
+ else {
475
+ ptrdiff_t l = ms->capture[i].len;
476
+ if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture");
477
+ if (l == CAP_POSITION)
478
+ lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1);
479
+ else
480
+ lua_pushlstring(ms->L, ms->capture[i].init, l);
481
+ }
482
+ }
483
+
484
+
485
+ static int push_captures (MatchState *ms, const char *s, const char *e) {
486
+ int i;
487
+ int nlevels = (ms->level == 0 && s) ? 1 : ms->level;
488
+ luaL_checkstack(ms->L, nlevels, "too many captures");
489
+ for (i = 0; i < nlevels; i++)
490
+ push_onecapture(ms, i, s, e);
491
+ return nlevels; /* number of strings pushed */
492
+ }
493
+
494
+
495
+ static int str_find_aux (lua_State *L, int find) {
496
+ size_t l1, l2;
497
+ const char *s = luaL_checklstring(L, 1, &l1);
498
+ const char *p = luaL_checklstring(L, 2, &l2);
499
+ ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;
500
+ if (init < 0) init = 0;
501
+ else if ((size_t)(init) > l1) init = (ptrdiff_t)l1;
502
+ if (find && (lua_toboolean(L, 4) || /* explicit request? */
503
+ strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */
504
+ /* do a plain search */
505
+ const char *s2 = lmemfind(s+init, l1-init, p, l2);
506
+ if (s2) {
507
+ lua_pushinteger(L, s2-s+1);
508
+ lua_pushinteger(L, s2-s+l2);
509
+ return 2;
510
+ }
511
+ }
512
+ else {
513
+ MatchState ms;
514
+ int anchor = (*p == '^') ? (p++, 1) : 0;
515
+ const char *s1=s+init;
516
+ ms.L = L;
517
+ ms.src_init = s;
518
+ ms.src_end = s+l1;
519
+ do {
520
+ const char *res;
521
+ ms.level = 0;
522
+ if ((res=match(&ms, s1, p)) != NULL) {
523
+ if (find) {
524
+ lua_pushinteger(L, s1-s+1); /* start */
525
+ lua_pushinteger(L, res-s); /* end */
526
+ return push_captures(&ms, NULL, 0) + 2;
527
+ }
528
+ else
529
+ return push_captures(&ms, s1, res);
530
+ }
531
+ } while (s1++ < ms.src_end && !anchor);
532
+ }
533
+ lua_pushnil(L); /* not found */
534
+ return 1;
535
+ }
536
+
537
+
538
+ static int str_find (lua_State *L) {
539
+ return str_find_aux(L, 1);
540
+ }
541
+
542
+
543
+ static int str_match (lua_State *L) {
544
+ return str_find_aux(L, 0);
545
+ }
546
+
547
+
548
+ static int gmatch_aux (lua_State *L) {
549
+ MatchState ms;
550
+ size_t ls;
551
+ const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
552
+ const char *p = lua_tostring(L, lua_upvalueindex(2));
553
+ const char *src;
554
+ ms.L = L;
555
+ ms.src_init = s;
556
+ ms.src_end = s+ls;
557
+ for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3));
558
+ src <= ms.src_end;
559
+ src++) {
560
+ const char *e;
561
+ ms.level = 0;
562
+ if ((e = match(&ms, src, p)) != NULL) {
563
+ lua_Integer newstart = e-s;
564
+ if (e == src) newstart++; /* empty match? go at least one position */
565
+ lua_pushinteger(L, newstart);
566
+ lua_replace(L, lua_upvalueindex(3));
567
+ return push_captures(&ms, src, e);
568
+ }
569
+ }
570
+ return 0; /* not found */
571
+ }
572
+
573
+
574
+ static int gmatch (lua_State *L) {
575
+ luaL_checkstring(L, 1);
576
+ luaL_checkstring(L, 2);
577
+ lua_settop(L, 2);
578
+ lua_pushinteger(L, 0);
579
+ lua_pushcclosure(L, gmatch_aux, 3);
580
+ return 1;
581
+ }
582
+
583
+
584
+ static int gfind_nodef (lua_State *L) {
585
+ return luaL_error(L, LUA_QL("string.gfind") " was renamed to "
586
+ LUA_QL("string.gmatch"));
587
+ }
588
+
589
+
590
+ static void add_s (MatchState *ms, luaL_Buffer *b, const char *s,
591
+ const char *e) {
592
+ size_t l, i;
593
+ const char *news = lua_tolstring(ms->L, 3, &l);
594
+ for (i = 0; i < l; i++) {
595
+ if (news[i] != L_ESC)
596
+ luaL_addchar(b, news[i]);
597
+ else {
598
+ i++; /* skip ESC */
599
+ if (!isdigit(uchar(news[i])))
600
+ luaL_addchar(b, news[i]);
601
+ else if (news[i] == '0')
602
+ luaL_addlstring(b, s, e - s);
603
+ else {
604
+ push_onecapture(ms, news[i] - '1', s, e);
605
+ luaL_addvalue(b); /* add capture to accumulated result */
606
+ }
607
+ }
608
+ }
609
+ }
610
+
611
+
612
+ static void add_value (MatchState *ms, luaL_Buffer *b, const char *s,
613
+ const char *e) {
614
+ lua_State *L = ms->L;
615
+ switch (lua_type(L, 3)) {
616
+ case LUA_TNUMBER:
617
+ case LUA_TSTRING: {
618
+ add_s(ms, b, s, e);
619
+ return;
620
+ }
621
+ case LUA_TFUNCTION: {
622
+ int n;
623
+ lua_pushvalue(L, 3);
624
+ n = push_captures(ms, s, e);
625
+ lua_call(L, n, 1);
626
+ break;
627
+ }
628
+ case LUA_TTABLE: {
629
+ push_onecapture(ms, 0, s, e);
630
+ lua_gettable(L, 3);
631
+ break;
632
+ }
633
+ }
634
+ if (!lua_toboolean(L, -1)) { /* nil or false? */
635
+ lua_pop(L, 1);
636
+ lua_pushlstring(L, s, e - s); /* keep original text */
637
+ }
638
+ else if (!lua_isstring(L, -1))
639
+ luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1));
640
+ luaL_addvalue(b); /* add result to accumulator */
641
+ }
642
+
643
+
644
+ static int str_gsub (lua_State *L) {
645
+ size_t srcl;
646
+ const char *src = luaL_checklstring(L, 1, &srcl);
647
+ const char *p = luaL_checkstring(L, 2);
648
+ int tr = lua_type(L, 3);
649
+ int max_s = luaL_optint(L, 4, srcl+1);
650
+ int anchor = (*p == '^') ? (p++, 1) : 0;
651
+ int n = 0;
652
+ MatchState ms;
653
+ luaL_Buffer b;
654
+ luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||
655
+ tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,
656
+ "string/function/table expected");
657
+ luaL_buffinit(L, &b);
658
+ ms.L = L;
659
+ ms.src_init = src;
660
+ ms.src_end = src+srcl;
661
+ while (n < max_s) {
662
+ const char *e;
663
+ ms.level = 0;
664
+ e = match(&ms, src, p);
665
+ if (e) {
666
+ n++;
667
+ add_value(&ms, &b, src, e);
668
+ }
669
+ if (e && e>src) /* non empty match? */
670
+ src = e; /* skip it */
671
+ else if (src < ms.src_end)
672
+ luaL_addchar(&b, *src++);
673
+ else break;
674
+ if (anchor) break;
675
+ }
676
+ luaL_addlstring(&b, src, ms.src_end-src);
677
+ luaL_pushresult(&b);
678
+ lua_pushinteger(L, n); /* number of substitutions */
679
+ return 2;
680
+ }
681
+
682
+ /* }====================================================== */
683
+
684
+
685
+ /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */
686
+ #define MAX_ITEM 512
687
+ /* valid flags in a format specification */
688
+ #define FLAGS "-+ #0"
689
+ /*
690
+ ** maximum size of each format specification (such as '%-099.99d')
691
+ ** (+10 accounts for %99.99x plus margin of error)
692
+ */
693
+ #define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)
694
+
695
+
696
+ static void addquoted (lua_State *L, luaL_Buffer *b, int arg) {
697
+ size_t l;
698
+ const char *s = luaL_checklstring(L, arg, &l);
699
+ luaL_addchar(b, '"');
700
+ while (l--) {
701
+ switch (*s) {
702
+ case '"': case '\\': case '\n': {
703
+ luaL_addchar(b, '\\');
704
+ luaL_addchar(b, *s);
705
+ break;
706
+ }
707
+ case '\r': {
708
+ luaL_addlstring(b, "\\r", 2);
709
+ break;
710
+ }
711
+ case '\0': {
712
+ luaL_addlstring(b, "\\000", 4);
713
+ break;
714
+ }
715
+ default: {
716
+ luaL_addchar(b, *s);
717
+ break;
718
+ }
719
+ }
720
+ s++;
721
+ }
722
+ luaL_addchar(b, '"');
723
+ }
724
+
725
+ static const char *scanformat (lua_State *L, const char *strfrmt, char *form) {
726
+ const char *p = strfrmt;
727
+ while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */
728
+ if ((size_t)(p - strfrmt) >= sizeof(FLAGS))
729
+ luaL_error(L, "invalid format (repeated flags)");
730
+ if (isdigit(uchar(*p))) p++; /* skip width */
731
+ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
732
+ if (*p == '.') {
733
+ p++;
734
+ if (isdigit(uchar(*p))) p++; /* skip precision */
735
+ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */
736
+ }
737
+ if (isdigit(uchar(*p)))
738
+ luaL_error(L, "invalid format (width or precision too long)");
739
+ *(form++) = '%';
740
+ strncpy(form, strfrmt, p - strfrmt + 1);
741
+ form += p - strfrmt + 1;
742
+ *form = '\0';
743
+ return p;
744
+ }
745
+
746
+
747
+ static void addintlen (char *form) {
748
+ size_t l = strlen(form);
749
+ char spec = form[l - 1];
750
+ strcpy(form + l - 1, LUA_INTFRMLEN);
751
+ form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;
752
+ form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0';
753
+ }
754
+
755
+
756
+ static int str_format (lua_State *L) {
757
+ int top = lua_gettop(L);
758
+ int arg = 1;
759
+ size_t sfl;
760
+ const char *strfrmt = luaL_checklstring(L, arg, &sfl);
761
+ const char *strfrmt_end = strfrmt+sfl;
762
+ luaL_Buffer b;
763
+ luaL_buffinit(L, &b);
764
+ while (strfrmt < strfrmt_end) {
765
+ if (*strfrmt != L_ESC)
766
+ luaL_addchar(&b, *strfrmt++);
767
+ else if (*++strfrmt == L_ESC)
768
+ luaL_addchar(&b, *strfrmt++); /* %% */
769
+ else { /* format item */
770
+ char form[MAX_FORMAT]; /* to store the format (`%...') */
771
+ char buff[MAX_ITEM]; /* to store the formatted item */
772
+ if (++arg > top)
773
+ luaL_argerror(L, arg, "no value");
774
+ strfrmt = scanformat(L, strfrmt, form);
775
+ switch (*strfrmt++) {
776
+ case 'c': {
777
+ sprintf(buff, form, (int)luaL_checknumber(L, arg));
778
+ break;
779
+ }
780
+ case 'd': case 'i': {
781
+ addintlen(form);
782
+ sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));
783
+ break;
784
+ }
785
+ case 'o': case 'u': case 'x': case 'X': {
786
+ addintlen(form);
787
+ sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));
788
+ break;
789
+ }
790
+ case 'e': case 'E': case 'f':
791
+ case 'g': case 'G': {
792
+ sprintf(buff, form, (double)luaL_checknumber(L, arg));
793
+ break;
794
+ }
795
+ case 'q': {
796
+ addquoted(L, &b, arg);
797
+ continue; /* skip the 'addsize' at the end */
798
+ }
799
+ case 's': {
800
+ size_t l;
801
+ const char *s = luaL_checklstring(L, arg, &l);
802
+ if (!strchr(form, '.') && l >= 100) {
803
+ /* no precision and string is too long to be formatted;
804
+ keep original string */
805
+ lua_pushvalue(L, arg);
806
+ luaL_addvalue(&b);
807
+ continue; /* skip the `addsize' at the end */
808
+ }
809
+ else {
810
+ sprintf(buff, form, s);
811
+ break;
812
+ }
813
+ }
814
+ default: { /* also treat cases `pnLlh' */
815
+ return luaL_error(L, "invalid option " LUA_QL("%%%c") " to "
816
+ LUA_QL("format"), *(strfrmt - 1));
817
+ }
818
+ }
819
+ luaL_addlstring(&b, buff, strlen(buff));
820
+ }
821
+ }
822
+ luaL_pushresult(&b);
823
+ return 1;
824
+ }
825
+
826
+
827
+ static const luaL_Reg strlib[] = {
828
+ {"byte", str_byte},
829
+ {"char", str_char},
830
+ {"dump", str_dump},
831
+ {"find", str_find},
832
+ {"format", str_format},
833
+ {"gfind", gfind_nodef},
834
+ {"gmatch", gmatch},
835
+ {"gsub", str_gsub},
836
+ {"len", str_len},
837
+ {"lower", str_lower},
838
+ {"match", str_match},
839
+ {"rep", str_rep},
840
+ {"reverse", str_reverse},
841
+ {"sub", str_sub},
842
+ {"upper", str_upper},
843
+ {NULL, NULL}
844
+ };
845
+
846
+
847
+ static void createmetatable (lua_State *L) {
848
+ lua_createtable(L, 0, 1); /* create metatable for strings */
849
+ lua_pushliteral(L, ""); /* dummy string */
850
+ lua_pushvalue(L, -2);
851
+ lua_setmetatable(L, -2); /* set string metatable */
852
+ lua_pop(L, 1); /* pop dummy string */
853
+ lua_pushvalue(L, -2); /* string library... */
854
+ lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */
855
+ lua_pop(L, 1); /* pop metatable */
856
+ }
857
+
858
+
859
+ /*
860
+ ** Open string library
861
+ */
862
+ LUALIB_API int luaopen_string (lua_State *L) {
863
+ luaL_register(L, LUA_STRLIBNAME, strlib);
864
+ #if defined(LUA_COMPAT_GFIND)
865
+ lua_getfield(L, -1, "gmatch");
866
+ lua_setfield(L, -2, "gfind");
867
+ #endif
868
+ createmetatable(L);
869
+ return 1;
870
+ }
871
+