zig-pug 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +346 -0
  3. package/binding.c +375 -0
  4. package/binding.gyp +28 -0
  5. package/common.gypi +5 -0
  6. package/include/zigpug.h +135 -0
  7. package/index.js +205 -0
  8. package/package.json +87 -0
  9. package/vendor/mujs/COPYING +16 -0
  10. package/vendor/mujs/README +50 -0
  11. package/vendor/mujs/astnames.h +92 -0
  12. package/vendor/mujs/jsarray.c +832 -0
  13. package/vendor/mujs/jsboolean.c +38 -0
  14. package/vendor/mujs/jsbuiltin.c +249 -0
  15. package/vendor/mujs/jscompile.c +1428 -0
  16. package/vendor/mujs/jsdate.c +861 -0
  17. package/vendor/mujs/jsdtoa.c +749 -0
  18. package/vendor/mujs/jserror.c +139 -0
  19. package/vendor/mujs/jsfunction.c +231 -0
  20. package/vendor/mujs/jsgc.c +284 -0
  21. package/vendor/mujs/jsi.h +870 -0
  22. package/vendor/mujs/jsintern.c +137 -0
  23. package/vendor/mujs/jslex.c +878 -0
  24. package/vendor/mujs/jsmath.c +194 -0
  25. package/vendor/mujs/jsnumber.c +198 -0
  26. package/vendor/mujs/jsobject.c +560 -0
  27. package/vendor/mujs/json.c +422 -0
  28. package/vendor/mujs/jsparse.c +1065 -0
  29. package/vendor/mujs/jsproperty.c +341 -0
  30. package/vendor/mujs/jsregexp.c +232 -0
  31. package/vendor/mujs/jsrepr.c +285 -0
  32. package/vendor/mujs/jsrun.c +2096 -0
  33. package/vendor/mujs/jsstate.c +334 -0
  34. package/vendor/mujs/jsstring.c +852 -0
  35. package/vendor/mujs/jsvalue.c +708 -0
  36. package/vendor/mujs/libmujs.a +0 -0
  37. package/vendor/mujs/main.c +396 -0
  38. package/vendor/mujs/mujs.h +253 -0
  39. package/vendor/mujs/one.c +25 -0
  40. package/vendor/mujs/opnames.h +85 -0
  41. package/vendor/mujs/pp.c +980 -0
  42. package/vendor/mujs/regexp.c +1277 -0
  43. package/vendor/mujs/regexp.h +46 -0
  44. package/vendor/mujs/utf.c +305 -0
  45. package/vendor/mujs/utf.h +52 -0
  46. package/vendor/mujs/utfdata.h +2209 -0
@@ -0,0 +1,852 @@
1
+ #include "jsi.h"
2
+ #include "utf.h"
3
+ #include "regexp.h"
4
+
5
+ static int js_doregexec(js_State *J, Reprog *prog, const char *string, Resub *sub, int eflags)
6
+ {
7
+ int result = js_regexec(prog, string, sub, eflags);
8
+ if (result < 0)
9
+ js_error(J, "regexec failed");
10
+ return result;
11
+ }
12
+
13
+ static const char *checkstring(js_State *J, int idx)
14
+ {
15
+ if (!js_iscoercible(J, idx))
16
+ js_typeerror(J, "string function called on null or undefined");
17
+ return js_tostring(J, idx);
18
+ }
19
+
20
+ int js_runeat(js_State *J, const char *s, int i)
21
+ {
22
+ Rune rune = EOF;
23
+ while (i >= 0) {
24
+ rune = *(unsigned char*)s;
25
+ if (rune < Runeself) {
26
+ if (rune == 0)
27
+ return EOF;
28
+ ++s;
29
+ --i;
30
+ } else {
31
+ s += chartorune(&rune, s);
32
+ if (rune >= 0x10000)
33
+ i -= 2;
34
+ else
35
+ --i;
36
+ }
37
+ }
38
+ if (rune >= 0x10000) {
39
+ /* high surrogate */
40
+ if (i == -2)
41
+ return 0xd800 + ((rune - 0x10000) >> 10);
42
+ /* low surrogate */
43
+ else
44
+ return 0xdc00 + ((rune - 0x10000) & 0x3ff);
45
+ }
46
+ return rune;
47
+ }
48
+
49
+ int js_utflen(const char *s)
50
+ {
51
+ int c;
52
+ int n;
53
+ Rune rune;
54
+
55
+ n = 0;
56
+ for(;;) {
57
+ c = *(unsigned char *)s;
58
+ if (c < Runeself) {
59
+ if (c == 0)
60
+ return n;
61
+ s++;
62
+ n++;
63
+ } else {
64
+ s += chartorune(&rune, s);
65
+ if (rune >= 0x10000)
66
+ n += 2;
67
+ else
68
+ n++;
69
+ }
70
+ }
71
+ }
72
+
73
+ int js_utfptrtoidx(const char *s, const char *p)
74
+ {
75
+ Rune rune;
76
+ int i = 0;
77
+ while (s < p) {
78
+ if (*(unsigned char *)s < Runeself)
79
+ ++s;
80
+ else
81
+ s += chartorune(&rune, s);
82
+ if (rune >= 0x10000)
83
+ i += 2;
84
+ else
85
+ i += 1;
86
+ }
87
+ return i;
88
+ }
89
+
90
+ static void jsB_new_String(js_State *J)
91
+ {
92
+ js_newstring(J, js_gettop(J) > 1 ? js_tostring(J, 1) : "");
93
+ }
94
+
95
+ static void jsB_String(js_State *J)
96
+ {
97
+ js_pushstring(J, js_gettop(J) > 1 ? js_tostring(J, 1) : "");
98
+ }
99
+
100
+ static void Sp_toString(js_State *J)
101
+ {
102
+ js_Object *self = js_toobject(J, 0);
103
+ if (self->type != JS_CSTRING) js_typeerror(J, "not a string");
104
+ js_pushstring(J, self->u.s.string);
105
+ }
106
+
107
+ static void Sp_valueOf(js_State *J)
108
+ {
109
+ js_Object *self = js_toobject(J, 0);
110
+ if (self->type != JS_CSTRING) js_typeerror(J, "not a string");
111
+ js_pushstring(J, self->u.s.string);
112
+ }
113
+
114
+ static void Sp_charAt(js_State *J)
115
+ {
116
+ char buf[UTFmax + 1];
117
+ const char *s = checkstring(J, 0);
118
+ int pos = js_tointeger(J, 1);
119
+ Rune rune = js_runeat(J, s, pos);
120
+ if (rune >= 0) {
121
+ buf[runetochar(buf, &rune)] = 0;
122
+ js_pushstring(J, buf);
123
+ } else {
124
+ js_pushliteral(J, "");
125
+ }
126
+ }
127
+
128
+ static void Sp_charCodeAt(js_State *J)
129
+ {
130
+ const char *s = checkstring(J, 0);
131
+ int pos = js_tointeger(J, 1);
132
+ Rune rune = js_runeat(J, s, pos);
133
+ if (rune >= 0)
134
+ js_pushnumber(J, rune);
135
+ else
136
+ js_pushnumber(J, NAN);
137
+ }
138
+
139
+ static void Sp_concat(js_State *J)
140
+ {
141
+ int i, top = js_gettop(J);
142
+ int n;
143
+ char * volatile out = NULL;
144
+ const char *s;
145
+
146
+ if (top == 1)
147
+ return;
148
+
149
+ s = checkstring(J, 0);
150
+ n = 1 + strlen(s);
151
+
152
+ if (js_try(J)) {
153
+ js_free(J, out);
154
+ js_throw(J);
155
+ }
156
+
157
+ if (n > JS_STRLIMIT)
158
+ js_rangeerror(J, "invalid string length");
159
+ out = js_malloc(J, n);
160
+ strcpy(out, s);
161
+
162
+ for (i = 1; i < top; ++i) {
163
+ s = js_tostring(J, i);
164
+ n += strlen(s);
165
+ if (n > JS_STRLIMIT)
166
+ js_rangeerror(J, "invalid string length");
167
+ out = js_realloc(J, out, n);
168
+ strcat(out, s);
169
+ }
170
+
171
+ js_pushstring(J, out);
172
+ js_endtry(J);
173
+ js_free(J, out);
174
+ }
175
+
176
+ static void Sp_indexOf(js_State *J)
177
+ {
178
+ const char *haystack = checkstring(J, 0);
179
+ const char *needle = js_tostring(J, 1);
180
+ int pos = js_tointeger(J, 2);
181
+ int len = strlen(needle);
182
+ int k = 0;
183
+ Rune rune;
184
+ while (*haystack) {
185
+ if (k >= pos && !strncmp(haystack, needle, len)) {
186
+ js_pushnumber(J, k);
187
+ return;
188
+ }
189
+ haystack += chartorune(&rune, haystack);
190
+ ++k;
191
+ }
192
+ js_pushnumber(J, -1);
193
+ }
194
+
195
+ static void Sp_lastIndexOf(js_State *J)
196
+ {
197
+ const char *haystack = checkstring(J, 0);
198
+ const char *needle = js_tostring(J, 1);
199
+ int pos = js_isdefined(J, 2) ? js_tointeger(J, 2) : (int)strlen(haystack);
200
+ int len = strlen(needle);
201
+ int k = 0, last = -1;
202
+ Rune rune;
203
+ while (*haystack && k <= pos) {
204
+ if (!strncmp(haystack, needle, len))
205
+ last = k;
206
+ haystack += chartorune(&rune, haystack);
207
+ ++k;
208
+ }
209
+ js_pushnumber(J, last);
210
+ }
211
+
212
+ static void Sp_localeCompare(js_State *J)
213
+ {
214
+ const char *a = checkstring(J, 0);
215
+ const char *b = js_tostring(J, 1);
216
+ js_pushnumber(J, strcmp(a, b));
217
+ }
218
+
219
+ static void Sp_substring_imp(js_State *J, const char *s, int a, int n)
220
+ {
221
+ Rune head_rune = 0, tail_rune = 0;
222
+ const char *head, *tail;
223
+ char *p;
224
+ int i, k, head_len, tail_len;
225
+
226
+ /* find start of substring */
227
+ head = s;
228
+ for (i = 0; i < a; ++i) {
229
+ head += chartorune(&head_rune, head);
230
+ if (head_rune >= 0x10000)
231
+ ++i;
232
+ }
233
+
234
+ /* find end of substring */
235
+ tail = head;
236
+ for (k = i - a; k < n; ++k) {
237
+ tail += chartorune(&tail_rune, tail);
238
+ if (tail_rune >= 0x10000)
239
+ ++k;
240
+ }
241
+
242
+ /* no surrogate pair splits! */
243
+ if (i == a && k == n) {
244
+ js_pushlstring(J, head, tail - head);
245
+ return;
246
+ }
247
+
248
+ if (js_try(J)) {
249
+ js_free(J, p);
250
+ js_throw(J);
251
+ }
252
+
253
+ p = js_malloc(J, UTFmax + (tail - head));
254
+
255
+ /* substring starts with low surrogate (head is just after character) */
256
+ if (i > a) {
257
+ head_rune = 0xdc00 + ((head_rune - 0x10000) & 0x3ff);
258
+ head_len = runetochar(p, &head_rune);
259
+ memcpy(p + head_len, head, tail - head);
260
+ js_pushlstring(J, p, head_len + (tail - head));
261
+ }
262
+
263
+ /* substring ends with high surrogate (tail is just after character) */
264
+ if (k > n) {
265
+ tail -= runelen(tail_rune);
266
+ memcpy(p, head, tail - head);
267
+ tail_rune = 0xd800 + ((tail_rune - 0x10000) >> 10);
268
+ tail_len = runetochar(p + (tail - head), &tail_rune);
269
+ js_pushlstring(J, p, (tail - head) + tail_len);
270
+ }
271
+
272
+ js_endtry(J);
273
+ js_free(J, p);
274
+ }
275
+
276
+ static void Sp_slice(js_State *J)
277
+ {
278
+ const char *str = checkstring(J, 0);
279
+ int len = js_utflen(str);
280
+ int s = js_tointeger(J, 1);
281
+ int e = js_isdefined(J, 2) ? js_tointeger(J, 2) : len;
282
+
283
+ s = s < 0 ? s + len : s;
284
+ e = e < 0 ? e + len : e;
285
+
286
+ s = s < 0 ? 0 : s > len ? len : s;
287
+ e = e < 0 ? 0 : e > len ? len : e;
288
+
289
+ if (s < e)
290
+ Sp_substring_imp(J, str, s, e - s);
291
+ else if (s > e)
292
+ Sp_substring_imp(J, str, e, s - e);
293
+ else
294
+ js_pushliteral(J, "");
295
+ }
296
+
297
+ static void Sp_substring(js_State *J)
298
+ {
299
+ const char *str = checkstring(J, 0);
300
+ int len = js_utflen(str);
301
+ int s = js_tointeger(J, 1);
302
+ int e = js_isdefined(J, 2) ? js_tointeger(J, 2) : len;
303
+
304
+ s = s < 0 ? 0 : s > len ? len : s;
305
+ e = e < 0 ? 0 : e > len ? len : e;
306
+
307
+ if (s < e)
308
+ Sp_substring_imp(J, str, s, e - s);
309
+ else if (s > e)
310
+ Sp_substring_imp(J, str, e, s - e);
311
+ else
312
+ js_pushliteral(J, "");
313
+ }
314
+
315
+ static void Sp_toLowerCase(js_State *J)
316
+ {
317
+ const char *s, *s0 = checkstring(J, 0);
318
+ char * volatile dst = NULL;
319
+ char *d;
320
+ Rune rune;
321
+ const Rune *full;
322
+ int n;
323
+
324
+ n = 1;
325
+ for (s = s0; *s;) {
326
+ s += chartorune(&rune, s);
327
+ full = tolowerrune_full(rune);
328
+ if (full) {
329
+ while (*full) {
330
+ n += runelen(*full);
331
+ ++full;
332
+ }
333
+ } else {
334
+ rune = tolowerrune(rune);
335
+ n += runelen(rune);
336
+ }
337
+ }
338
+
339
+ if (js_try(J)) {
340
+ js_free(J, dst);
341
+ js_throw(J);
342
+ }
343
+
344
+ d = dst = js_malloc(J, n);
345
+ for (s = s0; *s;) {
346
+ s += chartorune(&rune, s);
347
+ full = tolowerrune_full(rune);
348
+ if (full) {
349
+ while (*full) {
350
+ d += runetochar(d, full);
351
+ ++full;
352
+ }
353
+ } else {
354
+ rune = tolowerrune(rune);
355
+ d += runetochar(d, &rune);
356
+ }
357
+ }
358
+ *d = 0;
359
+
360
+ js_pushstring(J, dst);
361
+ js_endtry(J);
362
+ js_free(J, dst);
363
+ }
364
+
365
+ static void Sp_toUpperCase(js_State *J)
366
+ {
367
+ const char *s, *s0 = checkstring(J, 0);
368
+ char * volatile dst = NULL;
369
+ char *d;
370
+ const Rune *full;
371
+ Rune rune;
372
+ int n;
373
+
374
+ n = 1;
375
+ for (s = s0; *s;) {
376
+ s += chartorune(&rune, s);
377
+ full = toupperrune_full(rune);
378
+ if (full) {
379
+ while (*full) {
380
+ n += runelen(*full);
381
+ ++full;
382
+ }
383
+ } else {
384
+ rune = toupperrune(rune);
385
+ n += runelen(rune);
386
+ }
387
+ }
388
+
389
+ if (js_try(J)) {
390
+ js_free(J, dst);
391
+ js_throw(J);
392
+ }
393
+
394
+ d = dst = js_malloc(J, n);
395
+ for (s = s0; *s;) {
396
+ s += chartorune(&rune, s);
397
+ full = toupperrune_full(rune);
398
+ if (full) {
399
+ while (*full) {
400
+ d += runetochar(d, full);
401
+ ++full;
402
+ }
403
+ } else {
404
+ rune = toupperrune(rune);
405
+ d += runetochar(d, &rune);
406
+ }
407
+ }
408
+ *d = 0;
409
+
410
+ js_pushstring(J, dst);
411
+ js_endtry(J);
412
+ js_free(J, dst);
413
+ }
414
+
415
+ static int istrim(int c)
416
+ {
417
+ return c == 0x9 || c == 0xB || c == 0xC || c == 0x20 || c == 0xA0 || c == 0xFEFF ||
418
+ c == 0xA || c == 0xD || c == 0x2028 || c == 0x2029;
419
+ }
420
+
421
+ static void Sp_trim(js_State *J)
422
+ {
423
+ const char *s, *e;
424
+ s = checkstring(J, 0);
425
+ while (istrim(*s))
426
+ ++s;
427
+ e = s + strlen(s);
428
+ while (e > s && istrim(e[-1]))
429
+ --e;
430
+ js_pushlstring(J, s, e - s);
431
+ }
432
+
433
+ static void S_fromCharCode(js_State *J)
434
+ {
435
+ int i, top = js_gettop(J);
436
+ char * volatile s = NULL;
437
+ char *p;
438
+ Rune c;
439
+
440
+ if (js_try(J)) {
441
+ js_free(J, s);
442
+ js_throw(J);
443
+ }
444
+
445
+ s = p = js_malloc(J, (top-1) * UTFmax + 1);
446
+
447
+ for (i = 1; i < top; ++i) {
448
+ c = js_touint32(J, i);
449
+ p += runetochar(p, &c);
450
+ }
451
+ *p = 0;
452
+
453
+ js_pushstring(J, s);
454
+ js_endtry(J);
455
+ js_free(J, s);
456
+ }
457
+
458
+ static void Sp_match(js_State *J)
459
+ {
460
+ js_Regexp *re;
461
+ const char *text;
462
+ int len;
463
+ const char *a, *b, *c, *e;
464
+ Resub m;
465
+
466
+ text = checkstring(J, 0);
467
+
468
+ if (js_isregexp(J, 1))
469
+ js_copy(J, 1);
470
+ else if (js_isundefined(J, 1))
471
+ js_newregexp(J, "", 0);
472
+ else
473
+ js_newregexp(J, js_tostring(J, 1), 0);
474
+
475
+ re = js_toregexp(J, -1);
476
+ if (!(re->flags & JS_REGEXP_G)) {
477
+ js_RegExp_prototype_exec(J, re, text);
478
+ return;
479
+ }
480
+
481
+ re->last = 0;
482
+
483
+ js_newarray(J);
484
+
485
+ len = 0;
486
+ a = text;
487
+ e = text + strlen(text);
488
+ while (a <= e) {
489
+ if (js_doregexec(J, re->prog, a, &m, a > text ? REG_NOTBOL : 0))
490
+ break;
491
+
492
+ b = m.sub[0].sp;
493
+ c = m.sub[0].ep;
494
+
495
+ js_pushlstring(J, b, c - b);
496
+ js_setindex(J, -2, len++);
497
+
498
+ a = c;
499
+ if (c - b == 0)
500
+ ++a;
501
+ }
502
+
503
+ if (len == 0) {
504
+ js_pop(J, 1);
505
+ js_pushnull(J);
506
+ }
507
+ }
508
+
509
+ static void Sp_search(js_State *J)
510
+ {
511
+ js_Regexp *re;
512
+ const char *text;
513
+ Resub m;
514
+
515
+ text = checkstring(J, 0);
516
+
517
+ if (js_isregexp(J, 1))
518
+ js_copy(J, 1);
519
+ else if (js_isundefined(J, 1))
520
+ js_newregexp(J, "", 0);
521
+ else
522
+ js_newregexp(J, js_tostring(J, 1), 0);
523
+
524
+ re = js_toregexp(J, -1);
525
+
526
+ if (!js_doregexec(J, re->prog, text, &m, 0))
527
+ js_pushnumber(J, js_utfptrtoidx(text, m.sub[0].sp));
528
+ else
529
+ js_pushnumber(J, -1);
530
+ }
531
+
532
+ static void Sp_replace_regexp(js_State *J)
533
+ {
534
+ js_Regexp *re;
535
+ const char *source, *s, *r;
536
+ js_Buffer *sb = NULL;
537
+ int n, x;
538
+ Resub m;
539
+
540
+ source = checkstring(J, 0);
541
+ re = js_toregexp(J, 1);
542
+
543
+ if (js_doregexec(J, re->prog, source, &m, 0)) {
544
+ js_copy(J, 0);
545
+ return;
546
+ }
547
+
548
+ re->last = 0;
549
+
550
+ loop:
551
+ s = m.sub[0].sp;
552
+ n = m.sub[0].ep - m.sub[0].sp;
553
+
554
+ if (js_iscallable(J, 2)) {
555
+ js_copy(J, 2);
556
+ js_pushundefined(J);
557
+ for (x = 0; m.sub[x].sp; ++x) /* arg 0..x: substring and subexps that matched */
558
+ js_pushlstring(J, m.sub[x].sp, m.sub[x].ep - m.sub[x].sp);
559
+ js_pushnumber(J, s - source); /* arg x+2: offset within search string */
560
+ js_copy(J, 0); /* arg x+3: search string */
561
+ js_call(J, 2 + x);
562
+ r = js_tostring(J, -1);
563
+ js_putm(J, &sb, source, s);
564
+ js_puts(J, &sb, r);
565
+ js_pop(J, 1);
566
+ } else {
567
+ r = js_tostring(J, 2);
568
+ js_putm(J, &sb, source, s);
569
+ while (*r) {
570
+ if (*r == '$') {
571
+ switch (*(++r)) {
572
+ case 0: --r; /* end of string; back up */
573
+ /* fallthrough */
574
+ case '$': js_putc(J, &sb, '$'); break;
575
+ case '`': js_putm(J, &sb, source, s); break;
576
+ case '\'': js_puts(J, &sb, s + n); break;
577
+ case '&':
578
+ js_putm(J, &sb, s, s + n);
579
+ break;
580
+ case '0': case '1': case '2': case '3': case '4':
581
+ case '5': case '6': case '7': case '8': case '9':
582
+ x = *r - '0';
583
+ if (r[1] >= '0' && r[1] <= '9')
584
+ x = x * 10 + *(++r) - '0';
585
+ if (x > 0 && x < m.nsub) {
586
+ js_putm(J, &sb, m.sub[x].sp, m.sub[x].ep);
587
+ } else {
588
+ js_putc(J, &sb, '$');
589
+ if (x > 10) {
590
+ js_putc(J, &sb, '0' + x / 10);
591
+ js_putc(J, &sb, '0' + x % 10);
592
+ } else {
593
+ js_putc(J, &sb, '0' + x);
594
+ }
595
+ }
596
+ break;
597
+ default:
598
+ js_putc(J, &sb, '$');
599
+ js_putc(J, &sb, *r);
600
+ break;
601
+ }
602
+ ++r;
603
+ } else {
604
+ js_putc(J, &sb, *r++);
605
+ }
606
+ }
607
+ }
608
+
609
+ if (re->flags & JS_REGEXP_G) {
610
+ source = m.sub[0].ep;
611
+ if (n == 0) {
612
+ if (*source)
613
+ js_putc(J, &sb, *source++);
614
+ else
615
+ goto end;
616
+ }
617
+ if (!js_doregexec(J, re->prog, source, &m, REG_NOTBOL))
618
+ goto loop;
619
+ }
620
+
621
+ end:
622
+ js_puts(J, &sb, s + n);
623
+ js_putc(J, &sb, 0);
624
+
625
+ if (js_try(J)) {
626
+ js_free(J, sb);
627
+ js_throw(J);
628
+ }
629
+ js_pushstring(J, sb ? sb->s : "");
630
+ js_endtry(J);
631
+ js_free(J, sb);
632
+ }
633
+
634
+ static void Sp_replace_string(js_State *J)
635
+ {
636
+ const char *source, *needle, *s, *r;
637
+ js_Buffer *sb = NULL;
638
+ int n;
639
+
640
+ source = checkstring(J, 0);
641
+ needle = js_tostring(J, 1);
642
+
643
+ s = strstr(source, needle);
644
+ if (!s) {
645
+ js_copy(J, 0);
646
+ return;
647
+ }
648
+ n = strlen(needle);
649
+
650
+ if (js_iscallable(J, 2)) {
651
+ js_copy(J, 2);
652
+ js_pushundefined(J);
653
+ js_pushlstring(J, s, n); /* arg 1: substring that matched */
654
+ js_pushnumber(J, s - source); /* arg 2: offset within search string */
655
+ js_copy(J, 0); /* arg 3: search string */
656
+ js_call(J, 3);
657
+ r = js_tostring(J, -1);
658
+ js_putm(J, &sb, source, s);
659
+ js_puts(J, &sb, r);
660
+ js_puts(J, &sb, s + n);
661
+ js_putc(J, &sb, 0);
662
+ js_pop(J, 1);
663
+ } else {
664
+ r = js_tostring(J, 2);
665
+ js_putm(J, &sb, source, s);
666
+ while (*r) {
667
+ if (*r == '$') {
668
+ switch (*(++r)) {
669
+ case 0: --r; /* end of string; back up */
670
+ /* fallthrough */
671
+ case '$': js_putc(J, &sb, '$'); break;
672
+ case '&': js_putm(J, &sb, s, s + n); break;
673
+ case '`': js_putm(J, &sb, source, s); break;
674
+ case '\'': js_puts(J, &sb, s + n); break;
675
+ default: js_putc(J, &sb, '$'); js_putc(J, &sb, *r); break;
676
+ }
677
+ ++r;
678
+ } else {
679
+ js_putc(J, &sb, *r++);
680
+ }
681
+ }
682
+ js_puts(J, &sb, s + n);
683
+ js_putc(J, &sb, 0);
684
+ }
685
+
686
+ if (js_try(J)) {
687
+ js_free(J, sb);
688
+ js_throw(J);
689
+ }
690
+ js_pushstring(J, sb ? sb->s : "");
691
+ js_endtry(J);
692
+ js_free(J, sb);
693
+ }
694
+
695
+ static void Sp_replace(js_State *J)
696
+ {
697
+ if (js_isregexp(J, 1))
698
+ Sp_replace_regexp(J);
699
+ else
700
+ Sp_replace_string(J);
701
+ }
702
+
703
+ static void Sp_split_regexp(js_State *J)
704
+ {
705
+ js_Regexp *re;
706
+ const char *text;
707
+ int limit, len, k;
708
+ const char *p, *a, *b, *c, *e;
709
+ Resub m;
710
+
711
+ text = checkstring(J, 0);
712
+ re = js_toregexp(J, 1);
713
+ limit = js_isdefined(J, 2) ? js_tointeger(J, 2) : 1 << 30;
714
+
715
+ js_newarray(J);
716
+ len = 0;
717
+
718
+ if (limit == 0)
719
+ return;
720
+
721
+ e = text + strlen(text);
722
+
723
+ /* splitting the empty string */
724
+ if (e == text) {
725
+ if (js_doregexec(J, re->prog, text, &m, 0)) {
726
+ js_pushliteral(J, "");
727
+ js_setindex(J, -2, 0);
728
+ }
729
+ return;
730
+ }
731
+
732
+ p = a = text;
733
+ while (a < e) {
734
+ if (js_doregexec(J, re->prog, a, &m, a > text ? REG_NOTBOL : 0))
735
+ break; /* no match */
736
+
737
+ b = m.sub[0].sp;
738
+ c = m.sub[0].ep;
739
+
740
+ /* empty string at end of last match */
741
+ if (b == c && b == p) {
742
+ ++a;
743
+ continue;
744
+ }
745
+
746
+ if (len == limit) return;
747
+ js_pushlstring(J, p, b - p);
748
+ js_setindex(J, -2, len++);
749
+
750
+ for (k = 1; k < m.nsub; ++k) {
751
+ if (len == limit) return;
752
+ js_pushlstring(J, m.sub[k].sp, m.sub[k].ep - m.sub[k].sp);
753
+ js_setindex(J, -2, len++);
754
+ }
755
+
756
+ a = p = c;
757
+ }
758
+
759
+ if (len == limit) return;
760
+ js_pushstring(J, p);
761
+ js_setindex(J, -2, len);
762
+ }
763
+
764
+ static void Sp_split_string(js_State *J)
765
+ {
766
+ const char *str = checkstring(J, 0);
767
+ const char *sep = js_tostring(J, 1);
768
+ int limit = js_isdefined(J, 2) ? js_tointeger(J, 2) : 1 << 30;
769
+ int i, n;
770
+
771
+ js_newarray(J);
772
+
773
+ if (limit == 0)
774
+ return;
775
+
776
+ n = strlen(sep);
777
+
778
+ /* empty string */
779
+ if (n == 0) {
780
+ Rune rune;
781
+ for (i = 0; *str && i < limit; ++i) {
782
+ n = chartorune(&rune, str);
783
+ js_pushlstring(J, str, n);
784
+ js_setindex(J, -2, i);
785
+ str += n;
786
+ }
787
+ return;
788
+ }
789
+
790
+ for (i = 0; str && i < limit; ++i) {
791
+ const char *s = strstr(str, sep);
792
+ if (s) {
793
+ js_pushlstring(J, str, s-str);
794
+ js_setindex(J, -2, i);
795
+ str = s + n;
796
+ } else {
797
+ js_pushstring(J, str);
798
+ js_setindex(J, -2, i);
799
+ str = NULL;
800
+ }
801
+ }
802
+ }
803
+
804
+ static void Sp_split(js_State *J)
805
+ {
806
+ if (js_isundefined(J, 1)) {
807
+ js_newarray(J);
808
+ js_pushstring(J, js_tostring(J, 0));
809
+ js_setindex(J, -2, 0);
810
+ } else if (js_isregexp(J, 1)) {
811
+ Sp_split_regexp(J);
812
+ } else {
813
+ Sp_split_string(J);
814
+ }
815
+ }
816
+
817
+ void jsB_initstring(js_State *J)
818
+ {
819
+ J->String_prototype->u.s.shrstr[0] = 0;
820
+ J->String_prototype->u.s.string = J->String_prototype->u.s.shrstr;
821
+ J->String_prototype->u.s.length = 0;
822
+
823
+ js_pushobject(J, J->String_prototype);
824
+ {
825
+ jsB_propf(J, "String.prototype.toString", Sp_toString, 0);
826
+ jsB_propf(J, "String.prototype.valueOf", Sp_valueOf, 0);
827
+ jsB_propf(J, "String.prototype.charAt", Sp_charAt, 1);
828
+ jsB_propf(J, "String.prototype.charCodeAt", Sp_charCodeAt, 1);
829
+ jsB_propf(J, "String.prototype.concat", Sp_concat, 0); /* 1 */
830
+ jsB_propf(J, "String.prototype.indexOf", Sp_indexOf, 1);
831
+ jsB_propf(J, "String.prototype.lastIndexOf", Sp_lastIndexOf, 1);
832
+ jsB_propf(J, "String.prototype.localeCompare", Sp_localeCompare, 1);
833
+ jsB_propf(J, "String.prototype.match", Sp_match, 1);
834
+ jsB_propf(J, "String.prototype.replace", Sp_replace, 2);
835
+ jsB_propf(J, "String.prototype.search", Sp_search, 1);
836
+ jsB_propf(J, "String.prototype.slice", Sp_slice, 2);
837
+ jsB_propf(J, "String.prototype.split", Sp_split, 2);
838
+ jsB_propf(J, "String.prototype.substring", Sp_substring, 2);
839
+ jsB_propf(J, "String.prototype.toLowerCase", Sp_toLowerCase, 0);
840
+ jsB_propf(J, "String.prototype.toLocaleLowerCase", Sp_toLowerCase, 0);
841
+ jsB_propf(J, "String.prototype.toUpperCase", Sp_toUpperCase, 0);
842
+ jsB_propf(J, "String.prototype.toLocaleUpperCase", Sp_toUpperCase, 0);
843
+
844
+ /* ES5 */
845
+ jsB_propf(J, "String.prototype.trim", Sp_trim, 0);
846
+ }
847
+ js_newcconstructor(J, jsB_String, jsB_new_String, "String", 0); /* 1 */
848
+ {
849
+ jsB_propf(J, "String.fromCharCode", S_fromCharCode, 0); /* 1 */
850
+ }
851
+ js_defglobal(J, "String", JS_DONTENUM);
852
+ }